pixelkiln 0.20.0 → 0.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts","../src/env.ts","../src/provider.ts","../src/providers/comfyui.ts","../src/hash.ts","../src/png.ts","../src/media.ts","../src/providers/pixellab.ts","../src/client.ts","../src/types.ts","../src/providers/retrodiffusion.ts","../src/providers/scenario.ts","../src/providers/registry.ts","../src/manifest.ts","../src/outputs.ts","../src/lock.ts","../src/pipeline/pack.ts","../src/pipeline/plan.ts","../src/pipeline/quality-profile.ts","../src/pipeline/refine.ts","../src/artifacts.ts","../src/pipeline/audit.ts","../src/pipeline/revision.ts","../src/pipeline/submit.ts","../src/pipeline/poll.ts","../src/pipeline/fetch.ts","../src/source-url.ts","../src/pipeline/doctor.ts","../src/pipeline/adopt.ts","../src/cache.ts","../src/pick/sheet.ts","../src/pick/review-server.ts","../src/pick/server.ts","../src/pipeline/init.ts","../src/pipeline/salvage.ts","../src/workspace.ts","../src/pipeline/workspace.ts","../src/pipeline/cache-health.ts","../src/pipeline/tileset-export.ts","../src/pick/salvage-server.ts","../src/pick/salvage-sheet.ts","../src/recipes.ts","../src/pipeline/quality-regression.ts"],"sourcesContent":["#!/usr/bin/env node\nimport path from \"node:path\"\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { loadEnvFiles } from \"./env.ts\"\nimport {\n formatCost,\n measureBalanceChange,\n requireBalance,\n requireDelete,\n requireList,\n} from \"./provider.ts\"\nimport {\n createProvider,\n providerCredentialEnvs,\n providerFactory,\n type ProviderMode,\n} from \"./providers/registry.ts\"\nimport { loadManifest, resolveSpecs } from \"./manifest.ts\"\nimport { mountStyle, packSprites, packStyle, resolvePackInputs } from \"./pipeline/pack.ts\"\nimport { loadLock, remove as removeLock, saveLock, spendByUnit, upsert as upsertLock } from \"./lock.ts\"\nimport { sha256File } from \"./hash.ts\"\nimport {\n lockKey,\n type GridConfidence,\n type Lock,\n type Manifest,\n type ResolvedSpec,\n} from \"./types.ts\"\nimport { normalizeLockOutputPaths, resolveOutputPath } from \"./outputs.ts\"\nimport { buildPlan, resumeActions, summarize, type Plan } from \"./pipeline/plan.ts\"\nimport { submit } from \"./pipeline/submit.ts\"\nimport { poll } from \"./pipeline/poll.ts\"\nimport { fetchAssets, pushTags } from \"./pipeline/fetch.ts\"\nimport { doctor } from \"./pipeline/doctor.ts\"\nimport { adopt, formatUnmatchedRemote, tagAdopted, writePromptsBack } from \"./pipeline/adopt.ts\"\nimport { runPicker, type ReviewReadyInfo } from \"./pick/server.ts\"\nimport { scanAssets, buildManifest, writeManifestFile } from \"./pipeline/init.ts\"\nimport {\n loadClaims,\n findOrphans,\n groupOrphansByStyle,\n loadSiblingManifests,\n SALVAGED_SPEC_HASH,\n} from \"./pipeline/salvage.ts\"\nimport {\n loadWorkspace,\n saveWorkspace,\n toPortablePath,\n resolveProject,\n validateWorkspace,\n type WorkspaceProject,\n} from \"./workspace.ts\"\nimport { workspaceClaims, workspaceStatus } from \"./pipeline/workspace.ts\"\nimport { auditStyle, evaluateAudit, hex } from \"./pipeline/audit.ts\"\nimport { inspectCaches } from \"./pipeline/cache-health.ts\"\nimport {\n approveQualityRecord,\n checkQualityRecord,\n qualityRecordPath,\n refineAsset,\n} from \"./pipeline/refine.ts\"\nimport {\n inspectQualityProfile,\n refineQualityProfiles,\n requireApprovedQualitySources,\n} from \"./pipeline/quality-profile.ts\"\nimport { exportTileset, type TilesetFormat } from \"./pipeline/tileset-export.ts\"\nimport { runSalvage } from \"./pick/salvage-server.ts\"\nimport type { BalanceInfo, Provider } from \"./provider.ts\"\nimport {\n writeManagedArtifactBundle,\n type ArtifactFile,\n type ArtifactSource,\n} from \"./artifacts.ts\"\nimport {\n installRecipe,\n listBundledRecipes,\n resolveRecipe,\n verifyRecipe,\n} from \"./recipes.ts\"\nimport {\n checkQualityBaseline,\n resolveQualityInputs,\n snapshotQualityBaseline,\n} from \"./pipeline/quality-regression.ts\"\n\nconst log = (msg = \"\") => console.log(msg)\n\ninterface CliWritable {\n isTTY?: boolean\n write(chunk: string): unknown\n}\n\n/**\n * Interactive readiness is progress, not command output. Keep it on stdout in\n * a terminal, but use stderr when stdout is piped so consumers such as `tail`\n * cannot hold the only copy of the live URL until the server exits.\n */\nexport function announceReviewReady(\n info: ReviewReadyInfo,\n stdout: CliWritable = process.stdout,\n stderr: CliWritable = process.stderr,\n): void {\n const stream = stdout.isTTY ? stdout : stderr\n const count = info.keys.length\n stream.write(\n `\\n ${count} asset${count === 1 ? \"\" : \"s\"} awaiting selection: ${info.url}\\n` +\n \" (leave this running; it exits once you apply)\\n\\n\",\n )\n}\n\nasync function provenanceFile(id: string, file: string): Promise<ArtifactSource> {\n const absolute = path.resolve(file)\n return {\n id,\n path: absolute,\n sha256: existsSync(absolute) ? await sha256File(absolute) : null,\n included: true,\n }\n}\n\ninterface Args {\n command: string\n manifest: string\n lock: string\n styles: string[]\n assets: string[]\n force: boolean\n yes: boolean\n budget?: number\n /** Repeatable provider-keyed budgets used by a mixed-provider run. */\n providerBudgets: Record<string, number>\n dryRun: boolean\n all: boolean\n json: boolean\n check: boolean\n noOpen: boolean\n tag: boolean\n from?: string\n out?: string\n generator?: string\n exclude: string[]\n name?: string\n writePrompts: boolean\n columns?: number\n port?: number\n inputs?: string\n claims: string[]\n format?: TilesetFormat\n outputRoles: string[]\n primaryOnly: boolean\n prune: boolean\n maxDistance?: number\n minTransparency?: number\n maxColors?: number\n sigma?: number\n palette: string[]\n fixerPython?: string\n fixerRevision?: string\n minGridConfidence?: GridConfidence\n reviewer?: string\n note?: string\n /** ComfyUI `models` directory used for offline recipe model verification. */\n modelRoot?: string\n /** Subcommand for `quality`, `recipe`, `refine`, or `workspace`. */\n subcommand?: string\n /** Path to a workspace catalog. Defaults to `pixelkiln.workspace.json` in cwd. */\n workspace?: string\n /** Positional target for recipe and workspace subcommands. */\n target?: string\n /** Account provider selector; also the `workspace add` catalog provider hint. */\n provider?: string\n /** `workspace add`: free-form account label, e.g. distinguishing sandboxes. */\n account?: string\n /**\n * Raw `--lock` value with no manifest-relative default applied. `workspace\n * add` needs to know whether the user actually passed `--lock`, since the\n * ambient default (beside `--manifest`, which usually names an unrelated\n * project) is meaningless for the manifest being registered.\n */\n explicitLock?: string\n}\n\nconst VALUE_FLAGS = [\n \"--manifest\", \"--lock\", \"--style\", \"--only\", \"--budget\", \"--port\",\n \"--from\", \"--out\", \"--generator\", \"--exclude\", \"--name\", \"--claims\", \"--columns\", \"--inputs\", \"--format\",\n \"--output-role\", \"--max-distance\", \"--min-transparency\", \"--max-colors\", \"--sigma\", \"--workspace\",\n \"--provider\", \"--account\", \"--palette\", \"--fixer-python\", \"--fixer-revision\", \"--min-grid-confidence\",\n \"--reviewer\", \"--note\",\n \"--model-root\",\n] as const\nconst BOOL_FLAGS = [\n \"--force\", \"--yes\", \"-y\", \"--dry-run\", \"--all\", \"--json\", \"--check\", \"--no-open\", \"--tag\", \"--write-prompts\", \"--primary-only\", \"--prune\",\n] as const\n\nexport const COMMANDS = [\n \"init\", \"plan\", \"doctor\", \"gen\", \"submit\", \"poll\", \"pick\", \"fetch\", \"restore\", \"adopt\", \"accept\",\n \"salvage\", \"purge\", \"prune\", \"audit\", \"cache\", \"pack\", \"mount\", \"export\", \"tag\", \"balance\", \"status\",\n \"quality\", \"refine\", \"recipe\", \"workspace\", \"help\", \"--help\", \"-h\", \"--version\", \"-v\",\n] as const\n\nconst WORKSPACE_SUBCOMMANDS = [\"add\", \"remove\", \"list\", \"status\", \"claims\"] as const\nconst REFINE_SUBCOMMANDS = [\"run\", \"approve\", \"check\"] as const\nconst RECIPE_SUBCOMMANDS = [\"list\", \"inspect\", \"install\", \"verify\"] as const\nconst QUALITY_SUBCOMMANDS = [\"snapshot\", \"check\"] as const\n\n/**\n * Strict parsing. Unknown flags are a hard error rather than being ignored,\n * because a silently-dropped filter is expensive here: `--styles neon` (plural,\n * a typo) would otherwise fall through to \"no filter\" and generate the entire\n * manifest instead of one style.\n */\nexport function parseArgs(argv: string[]): Args {\n const [command = \"help\"] = argv\n if (!(COMMANDS as readonly string[]).includes(command)) {\n throw new Error(`Unknown command \"${command}\". Run \\`pixelkiln help\\` for the list.`)\n }\n\n let rest = argv.slice(1)\n let subcommand: string | undefined\n let target: string | undefined\n if (command === \"quality\") {\n subcommand = rest[0]\n if (subcommand === undefined || subcommand.startsWith(\"-\")) {\n throw new Error(`quality needs a subcommand: ${QUALITY_SUBCOMMANDS.join(\", \")}`)\n }\n if (!(QUALITY_SUBCOMMANDS as readonly string[]).includes(subcommand)) {\n throw new Error(\n `Unknown quality subcommand \"${subcommand}\". Known: ${QUALITY_SUBCOMMANDS.join(\", \")}`,\n )\n }\n rest = rest.slice(1)\n } else if (command === \"recipe\") {\n subcommand = rest[0]\n if (subcommand === undefined || subcommand.startsWith(\"-\")) {\n throw new Error(`recipe needs a subcommand: ${RECIPE_SUBCOMMANDS.join(\", \")}`)\n }\n if (!(RECIPE_SUBCOMMANDS as readonly string[]).includes(subcommand)) {\n throw new Error(\n `Unknown recipe subcommand \"${subcommand}\". Known: ${RECIPE_SUBCOMMANDS.join(\", \")}`,\n )\n }\n rest = rest.slice(1)\n if (subcommand !== \"list\") {\n target = rest[0]\n if (target === undefined || target.startsWith(\"-\")) {\n throw new Error(`recipe ${subcommand} needs a recipe id, selector, or path.`)\n }\n rest = rest.slice(1)\n }\n } else if (command === \"workspace\") {\n subcommand = rest[0]\n if (subcommand === undefined || subcommand.startsWith(\"-\")) {\n throw new Error(`workspace needs a subcommand: ${WORKSPACE_SUBCOMMANDS.join(\", \")}`)\n }\n if (!(WORKSPACE_SUBCOMMANDS as readonly string[]).includes(subcommand)) {\n throw new Error(\n `Unknown workspace subcommand \"${subcommand}\". Known: ${WORKSPACE_SUBCOMMANDS.join(\", \")}`,\n )\n }\n rest = rest.slice(1)\n if (subcommand === \"add\" || subcommand === \"remove\") {\n target = rest[0]\n if (target === undefined || target.startsWith(\"-\")) {\n throw new Error(\n subcommand === \"add\"\n ? \"workspace add needs a manifest path.\"\n : \"workspace remove needs a project id or manifest path.\",\n )\n }\n rest = rest.slice(1)\n }\n } else if (command === \"refine\") {\n subcommand = rest[0]?.startsWith(\"-\") || rest[0] === undefined ? \"run\" : rest[0]\n if (!(REFINE_SUBCOMMANDS as readonly string[]).includes(subcommand)) {\n throw new Error(\n `Unknown refine subcommand \"${subcommand}\". Known: ${REFINE_SUBCOMMANDS.join(\", \")}`,\n )\n }\n if (rest[0] === subcommand) rest = rest.slice(1)\n }\n\n for (let i = 0; i < rest.length; i++) {\n const token = rest[i]!\n if (!token.startsWith(\"-\")) {\n throw new Error(`Unexpected argument \"${token}\". Options must be passed with a named flag.`)\n }\n if ((BOOL_FLAGS as readonly string[]).includes(token)) continue\n if ((VALUE_FLAGS as readonly string[]).includes(token)) {\n const value = rest[i + 1]\n // A numeric token is a value even though it starts with \"-\", so\n // `--budget -5` reaches the range check and reports the real problem.\n const looksLikeFlag = value !== undefined && value.startsWith(\"-\") && !Number.isFinite(Number(value))\n if (value === undefined || looksLikeFlag) {\n throw new Error(`${token} needs a value.`)\n }\n i++\n continue\n }\n throw new Error(\n `Unknown flag \"${token}\". Known flags: ${[...VALUE_FLAGS, ...BOOL_FLAGS].join(\", \")}`,\n )\n }\n\n const get = (flag: string) => {\n const i = rest.indexOf(flag)\n return i >= 0 ? rest[i + 1] : undefined\n }\n /**\n * Collects every occurrence of a list flag, not just the first.\n *\n * `--style a --style b` is the natural way to write this and previously kept\n * only `a`, silently discarding `b` — so a run that looked like it covered\n * two styles covered one, and `plan` quoted a cost for work it would not do.\n * Repeated flags now accumulate; commas still work within each occurrence.\n */\n const list = (flag: string) => {\n const out: string[] = []\n for (let i = 0; i < rest.length; i++) {\n if (rest[i] !== flag) continue\n for (const part of (rest[i + 1] ?? \"\").split(\",\")) {\n const v = part.trim()\n if (v) out.push(v)\n }\n }\n return [...new Set(out)]\n }\n\n const rawColumns = get(\"--columns\")\n let columns: number | undefined\n if (rawColumns !== undefined) {\n columns = Number(rawColumns)\n // Same guard as --budget: NaN would silently fall through to the default\n // and quietly produce a differently-shaped sheet than asked for.\n if (!Number.isInteger(columns) || columns < 1 || columns > 1024) {\n throw new Error(`--columns must be a whole number between 1 and 1024, got \"${rawColumns}\"`)\n }\n }\n\n const rawPort = get(\"--port\")\n let port: number | undefined\n if (rawPort !== undefined) {\n port = Number(rawPort)\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(`--port must be a whole number between 1 and 65535, got \"${rawPort}\"`)\n }\n }\n\n let budget: number | undefined\n // A registry id is intentionally only constrained to non-empty text. Use a\n // null-prototype dictionary so ids such as \"constructor\" cannot interact\n // with Object.prototype while budgets are parsed.\n const providerBudgets: Record<string, number> = Object.create(null)\n const rawBudgets = rest.flatMap((token, index) => token === \"--budget\" ? [rest[index + 1]!] : [])\n for (const rawBudget of rawBudgets) {\n const separator = rawBudget.indexOf(\"=\")\n if (separator >= 0) {\n const providerId = rawBudget.slice(0, separator).trim()\n const rawAmount = rawBudget.slice(separator + 1).trim()\n const amount = Number(rawAmount)\n if (!providerId || /[=\\s]/.test(providerId) || !Number.isFinite(amount) || amount < 0) {\n throw new Error(\n `--budget must be a non-negative number or provider=number, got \"${rawBudget}\".`,\n )\n }\n if (Object.hasOwn(providerBudgets, providerId)) {\n throw new Error(`--budget repeats provider \"${providerId}\".`)\n }\n providerBudgets[providerId] = amount\n continue\n }\n const amount = Number(rawBudget)\n if (!Number.isFinite(amount) || amount < 0) {\n throw new Error(`--budget must be a non-negative number, got \"${rawBudget}\".`)\n }\n if (budget !== undefined) throw new Error(\"Only one unkeyed --budget may be passed.\")\n budget = amount\n }\n if (budget !== undefined && Object.keys(providerBudgets).length) {\n throw new Error(\"Do not mix an unkeyed --budget with provider-keyed budgets.\")\n }\n\n const manifest = get(\"--manifest\") ?? \"pixelkiln.manifest.json\"\n const rawFormat = get(\"--format\")\n if (rawFormat && rawFormat !== \"generic\" && rawFormat !== \"tiled\" && rawFormat !== \"godot\") {\n throw new Error(`--format must be generic, tiled, or godot, got \"${rawFormat}\"`)\n }\n const numberOption = (\n flag: string,\n opts: { min: number; max?: number; integer?: boolean },\n ): number | undefined => {\n const raw = get(flag)\n if (raw === undefined) return undefined\n const value = Number(raw)\n if (\n !Number.isFinite(value) ||\n value < opts.min ||\n (opts.max !== undefined && value > opts.max) ||\n (opts.integer && !Number.isInteger(value))\n ) {\n const range = opts.max === undefined ? `at least ${opts.min}` : `${opts.min} to ${opts.max}`\n throw new Error(`${flag} must be ${opts.integer ? \"a whole number \" : \"a number \"}${range}, got \"${raw}\"`)\n }\n return value\n }\n const rawGridConfidence = get(\"--min-grid-confidence\")\n if (\n rawGridConfidence !== undefined &&\n rawGridConfidence !== \"low\" && rawGridConfidence !== \"medium\" && rawGridConfidence !== \"high\"\n ) {\n throw new Error(\n `--min-grid-confidence must be low, medium, or high, got \"${rawGridConfidence}\"`,\n )\n }\n return {\n command,\n manifest,\n lock: get(\"--lock\") ?? path.join(path.dirname(path.resolve(manifest)), \"pixelkiln.lock.json\"),\n explicitLock: get(\"--lock\"),\n styles: list(\"--style\"),\n assets: list(\"--only\"),\n force: rest.includes(\"--force\"),\n yes: rest.includes(\"--yes\") || rest.includes(\"-y\"),\n budget,\n providerBudgets,\n dryRun: rest.includes(\"--dry-run\"),\n all: rest.includes(\"--all\"),\n json: rest.includes(\"--json\"),\n check: rest.includes(\"--check\"),\n noOpen: rest.includes(\"--no-open\"),\n tag: rest.includes(\"--tag\"),\n from: get(\"--from\"),\n out: get(\"--out\"),\n generator: get(\"--generator\"),\n exclude: list(\"--exclude\"),\n name: get(\"--name\"),\n writePrompts: rest.includes(\"--write-prompts\"),\n columns,\n port,\n inputs: get(\"--inputs\"),\n claims: list(\"--claims\"),\n format: rawFormat as TilesetFormat | undefined,\n outputRoles: list(\"--output-role\"),\n primaryOnly: rest.includes(\"--primary-only\"),\n prune: rest.includes(\"--prune\"),\n maxDistance: numberOption(\"--max-distance\", { min: 0 }),\n minTransparency: numberOption(\"--min-transparency\", { min: 0, max: 1 }),\n maxColors: numberOption(\"--max-colors\", { min: 1, integer: true }),\n sigma: numberOption(\"--sigma\", { min: Number.EPSILON }),\n palette: list(\"--palette\"),\n fixerPython: get(\"--fixer-python\"),\n fixerRevision: get(\"--fixer-revision\"),\n minGridConfidence: rawGridConfidence as GridConfidence | undefined,\n reviewer: get(\"--reviewer\"),\n note: get(\"--note\"),\n modelRoot: get(\"--model-root\"),\n subcommand,\n workspace: get(\"--workspace\"),\n target,\n provider: get(\"--provider\"),\n account: get(\"--account\"),\n }\n}\n\nconst HELP = `pixelkiln — manifest-driven pixel art generation\n\n pixelkiln <command> [options]\n\nCommands\n init Scaffold a manifest from an existing tree of PNGs.\n plan Diff manifest against lockfile and disk. Costs nothing. Start here.\n doctor Validate project state, recovery paths, and provider connectivity.\n gen Full run: submit → poll → pick → fetch. The everyday command.\n submit Queue generation jobs only.\n poll Advance in-flight jobs to their settled state.\n pick Open the contact sheet to choose among candidates.\n fetch Download selected objects to their manifest paths.\n restore Re-download missing generated files without generating new art.\n adopt Match existing account objects to files already in the repo.\n accept Keep existing art after a style reword — re-baseline, do not regenerate.\n salvage Triage account objects no lockfile claims. Recovers usable art.\n One session per matching style unless --style forces a single one.\n audit Measure how consistently a style's assets hold together. Offline.\n refine Build/check manifest quality profiles, or refine one --from PNG.\n Native grid, fixed palette, audit, and human approval. Offline.\n recipe List, inspect, install, or verify versioned workflow packs. Offline.\n quality Snapshot or check measurable image regressions. Offline.\n cache Inspect local recovery/object-hash caches; optionally verify or prune.\n pack Composite sprites into a PNG/atlas/provenance bundle. Offline.\n mount Write a style's sprites into their declared cells of an existing\n sheet, leaving every other pixel untouched. Offline.\n export Build a tile atlas, engine metadata, and offline provenance record.\n purge Delete objects previously tagged discard. Irreversible; asks first.\n prune Drop lock entries the manifest no longer declares. Offline; asks\n first. Local art is untouched.\n tag Push manifest tags to the objects upstream (free).\n balance Show the provider's remaining balance.\n status Summarise the lockfile.\n workspace Register sibling projects and derive account-wide claims/status.\n add/remove/list/status/claims. Offline.\n\nOptions\n --columns <n> pack/export: sprites or tiles per row (default: near-square)\n --port <n> Local review-server port (default: choose a free port)\n --inputs <path> pack/quality snapshot: JSON input list; needs --out\n --format <format> export: generic (default), tiled, or godot\n --output-role <r> pack: include only this output role (repeatable)\n --primary-only pack: include only unambiguous primary/single outputs\n --max-distance <n> audit: maximum palette distance\n --min-transparency <0..1> audit: minimum transparent canvas share\n --max-colors <n> audit: maximum distinct opaque colors\n --sigma <n> audit: relative outlier cutoff (default: 1.5)\n --palette <hexes> refine: final comma-separated #rrggbb colors (repeatable)\n --fixer-python <path> refine: override Python with Pixel Art Fixer installed\n --fixer-revision <sha> refine: Pixel Art Fixer revision to record\n --min-grid-confidence <level> refine: high (default), medium, or low\n --reviewer <name> refine approve: human reviewer recorded in provenance\n --note <text> refine approve: optional review note\n --model-root <dir> recipe verify: also hash required local model files\n --prune cache: remove invalid/unreferenced local cache data\n --manifest <path> Default: pixelkiln.manifest.json\n --lock <path> Default: pixelkiln.lock.json beside the manifest\n --style a,b Restrict to these styles\n --only id1,id2 Restrict to these asset ids\n --budget <n|provider=n> Refuse to exceed one provider ceiling; repeat keyed budgets\n for a mixed-provider run\n --provider <id> Choose the account for balance/adopt/salvage/purge in a mixed manifest\n --force Regenerate, replace a fetch destination, or rebuild managed output\n --dry-run Never spend; doctor also skips provider connectivity\n --all salvage --dry-run: list every unclaimed object, not just the first 30\n --json Machine-readable output where supported, including quality checks\n --check plan/audit/cache: exit nonzero when the selected state is unsafe\n --yes, -y Skip the confirmation prompt\n --no-open Do not auto-open the browser during pick\n --tag Also push tags upstream after fetch\n --claims a.json,b Other projects' lockfiles (salvage; required if account is shared)\n --workspace <path> Workspace catalog (default: pixelkiln.workspace.json). Also\n derives salvage's claim set instead of repeated --claims.\n --from <path> Source for init/path-mode refine, or baseline for quality check\n --write-prompts adopt: recover prompts into the manifest\n\nExamples\n pixelkiln plan\n pixelkiln gen --style heybud-premium --budget 400\n pixelkiln gen --only first_review --force\n pixelkiln adopt --tag\n pixelkiln pack --style heybud-premium\n pixelkiln pack --inputs sprites.json --out dist/sheet # no manifest needed\n pixelkiln mount --style ground\n pixelkiln export --style ground --only terrain --format tiled\n pixelkiln refine --style environment\n pixelkiln refine check --style environment\n pixelkiln refine --from source.png --out final.png --palette \"#101820,#f2aa4c\"\n pixelkiln refine approve --from final.pixelkiln.json --reviewer \"Your Name\"\n pixelkiln refine check --from final.pixelkiln.json\n pixelkiln recipe list\n pixelkiln recipe install comfyui/pixel-art-xl-environment\n pixelkiln recipe verify pixelkiln-recipes/comfyui/pixel-art-xl-environment/1.0.0 --model-root /path/to/ComfyUI/models\n pixelkiln quality snapshot --inputs quality-inputs.json --out pixelkiln.quality.json\n pixelkiln quality check --from pixelkiln.quality.json\n pixelkiln workspace add ../other-game/pixelkiln.manifest.json\n pixelkiln workspace status --json\n pixelkiln salvage --workspace pixelkiln.workspace.json\n`\n\nfunction printPlan(plan: Plan): void {\n const counts = summarize(plan)\n const order = [\n \"blocked\", \"missing\", \"untracked\", \"stale\", \"failed\", \"recoverable\", \"in-flight\", \"orphaned\", \"ok\",\n ] as const\n for (const state of order) {\n const items = plan.items.filter((i) => i.state === state)\n if (!items.length) continue\n log(`\\n ${state} (${items.length})`)\n for (const item of items.slice(0, 40)) {\n log(` ${item.key.padEnd(42)} ${item.reason}`)\n }\n if (items.length > 40) log(` … and ${items.length - 40} more`)\n }\n log(\n `\\n totals: ${counts.ok} ok · ${counts.blocked} blocked · ${counts.missing} missing · ${counts.untracked} untracked · ` +\n `${counts.stale} stale · ${counts[\"in-flight\"]} in-flight · ${counts.orphaned} orphaned · ` +\n `${counts.recoverable} recoverable · ${counts.failed} failed`,\n )\n if (plan.actionable.length) {\n for (const group of plan.groups) {\n log(\n ` ${group.provider}: ${group.actionable.length} asset(s) — ` +\n `${formatCost(group.costUnit, group.cost)}, ` +\n `${group.candidates} candidate/output image(s)`,\n )\n }\n } else {\n log(` nothing to generate`)\n }\n const qualityItems = plan.items.flatMap((item) => item.quality ? [item.quality] : [])\n if (qualityItems.length) {\n const approved = qualityItems.filter((item) => item.state === \"approved\").length\n log(`\\n quality: ${approved}/${qualityItems.length} approved`)\n for (const item of qualityItems.filter((item) => item.state !== \"approved\").slice(0, 40)) {\n log(` ${item.state.padEnd(16)} ${item.key} ${item.reason}`)\n }\n }\n}\n\nfunction printResumeActions(specs: ResolvedSpec[], lock: Lock): number {\n const actions = resumeActions(specs, lock)\n for (const action of actions) {\n const shown = action.keys.slice(0, 3).join(\", \")\n const more = action.keys.length > 3 ? `, +${action.keys.length - 3} more` : \"\"\n log(\n ` next: pixelkiln ${action.command} — ${action.keys.length} asset` +\n `${action.keys.length === 1 ? \"\" : \"s\"} (${shown}${more})`,\n )\n }\n return actions.length\n}\n\nfunction manifestProviderIds(manifest: Manifest): string[] {\n return [...new Set(\n Object.values(manifest.styles).map((style) => style.provider ?? manifest.provider),\n )].sort()\n}\n\nfunction specsByRecordedProvider(specs: ResolvedSpec[], lock: Lock): Map<string, ResolvedSpec[]> {\n const grouped = new Map<string, ResolvedSpec[]>()\n for (const spec of specs) {\n const key = lockKey(spec.styleId, spec.assetId)\n const provider = lock.entries[key]?.provider ?? spec.provider\n grouped.set(provider, [...(grouped.get(provider) ?? []), spec])\n }\n return grouped\n}\n\nfunction accountProviderId(manifest: Manifest, requested: string | undefined, command: string): string {\n const providers = manifestProviderIds(manifest)\n if (requested) {\n if (!providers.includes(requested)) {\n throw new Error(\n `Provider \"${requested}\" is not used by this manifest. Used: ${providers.join(\", \")}.`,\n )\n }\n return requested\n }\n if (providers.length > 1) {\n throw new Error(\n `${command} is account-scoped and this manifest uses ${providers.join(\", \")}. ` +\n `Pass --provider <id>.`,\n )\n }\n return providers[0] ?? manifest.provider\n}\n\nfunction budgetsForPlan(plan: Plan, args: Args): Map<string, number | undefined> {\n const providerIds = new Set(plan.groups.map((group) => group.provider))\n const keyed = Object.entries(args.providerBudgets)\n for (const [provider] of keyed) {\n if (!providerIds.has(provider)) {\n throw new Error(\n `Budget names provider \"${provider}\", but this run has work only for ` +\n `${[...providerIds].join(\", \") || \"no providers\"}.`,\n )\n }\n }\n if (plan.groups.length > 1 && args.budget !== undefined) {\n throw new Error(\n \"A mixed-provider run needs provider-keyed budgets, for example \" +\n \"--budget pixellab=40 --budget retrodiffusion=1.25.\",\n )\n }\n const out = new Map<string, number | undefined>()\n for (const group of plan.groups) {\n const ceiling = args.providerBudgets[group.provider]\n if (\n plan.groups.length > 1 &&\n group.costUnit !== \"free\" &&\n group.cost > 0 &&\n ceiling === undefined\n ) {\n throw new Error(\n `Mixed-provider run is missing --budget ${group.provider}=<amount> for ` +\n `${formatCost(group.costUnit, group.cost)} of planned work.`,\n )\n }\n out.set(group.provider, ceiling ?? (plan.groups.length === 1 ? args.budget : undefined))\n }\n return out\n}\n\nasync function confirm(question: string, auto: boolean): Promise<boolean> {\n if (auto) return true\n if (!process.stdin.isTTY) {\n log(` (non-interactive; pass --yes to proceed)`)\n return false\n }\n process.stdout.write(`${question} [y/N] `)\n const answer = await new Promise<string>((resolve) => {\n process.stdin.setEncoding(\"utf8\")\n process.stdin.once(\"data\", (d) => resolve(String(d).trim().toLowerCase()))\n })\n process.stdin.pause()\n return answer === \"y\" || answer === \"yes\"\n}\n\n/**\n * Loads a workspace catalog and derives its complete claim set, refusing when\n * the catalog itself is unsafe — missing entirely, or containing duplicate\n * ids/locks, or a registered manifest or lock that does not exist — rather\n * than silently deriving a partial (or empty) claim set. `loadWorkspace`\n * treats a missing file as an empty catalog because that's the right\n * behavior for `workspace add` (creating one for the first time); a claim\n * consumer needs the opposite default, the same way `--claims` treats a\n * missing lockfile path as a hard error (`loadClaims`,\n * `src/pipeline/salvage.ts`) rather than skipping it. `workspaceClaims`\n * separately guards against an unreadable lock that passed the existence\n * check.\n */\nasync function requireCompleteWorkspaceClaims(workspacePath: string) {\n if (!existsSync(workspacePath)) {\n throw new Error(`Workspace catalog not found: ${workspacePath}`)\n }\n const dir = path.dirname(path.resolve(workspacePath))\n const ws = await loadWorkspace(workspacePath)\n const diagnostics = validateWorkspace(ws, dir)\n const errors = diagnostics.filter((d) => d.level === \"error\")\n if (errors.length) {\n throw new Error(\n `Workspace catalog at ${workspacePath} is not safe to derive a claim set from:\\n` +\n errors.map((d) => ` ${d.id}: ${d.message}`).join(\"\\n\"),\n )\n }\n const claims = await workspaceClaims(ws, dir)\n return { ws, dir, diagnostics, claims }\n}\n\nasync function main() {\n const args = parseArgs(process.argv.slice(2))\n if (args.command === \"help\" || args.command === \"--help\" || args.command === \"-h\") {\n log(HELP)\n return\n }\n\n if (args.command === \"--version\" || args.command === \"-v\") {\n const pkg = JSON.parse(\n await readFile(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n ) as { name: string; version: string }\n log(`${pkg.name} ${pkg.version}`)\n return\n }\n\n if (args.command === \"quality\") {\n if (args.subcommand === \"snapshot\") {\n if (!args.inputs) throw new Error(\"quality snapshot needs --inputs <quality-inputs.json>.\")\n if (!args.out) throw new Error(\"quality snapshot needs --out <pixelkiln.quality.json>.\")\n let raw: unknown\n try {\n raw = JSON.parse(await readFile(path.resolve(args.inputs), \"utf8\"))\n } catch (error) {\n throw new Error(\n `Could not read quality inputs ${path.resolve(args.inputs)}: ` +\n `${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n )\n }\n const inputs = resolveQualityInputs(raw, args.inputs)\n if (path.resolve(args.inputs) === path.resolve(args.out)) {\n throw new Error(\"quality snapshot --out must not overwrite its --inputs file.\")\n }\n const result = await snapshotQualityBaseline(inputs, args.out, { force: args.force })\n if (args.json) {\n log(JSON.stringify({\n version: 1,\n path: result.path,\n changed: result.changed,\n baseline: result.baseline,\n }, null, 2))\n } else {\n log(\n ` ${result.changed ? \"wrote\" : \"unchanged\"} ` +\n `${path.relative(process.cwd(), result.path)} (${result.baseline.cases.length} case(s))`,\n )\n log(` Review the tolerances, commit the baseline, then run quality check in CI.`)\n }\n return\n }\n\n if (!args.from) throw new Error(\"quality check needs --from <pixelkiln.quality.json>.\")\n const report = await checkQualityBaseline(args.from)\n if (args.json) {\n log(JSON.stringify(report, null, 2))\n } else {\n for (const entry of report.cases) {\n log(` ${entry.status === \"pass\" ? \"ok\" : \"ERROR\"} ${entry.id}`)\n for (const violation of entry.violations) log(` ${violation}`)\n for (const warning of entry.warnings) log(` WARN ${warning}`)\n }\n log(\n `\\n ${report.summary.passed}/${report.summary.total} passed` +\n (report.summary.changed ? ` · ${report.summary.changed} image hash(es) changed` : \"\"),\n )\n log(` Metrics catch structural regressions; they do not replace art review.`)\n }\n if (!report.safe) process.exitCode = 1\n return\n }\n\n if (args.command === \"recipe\") {\n if (args.subcommand === \"list\") {\n const recipes = await listBundledRecipes()\n if (args.json) {\n log(JSON.stringify({\n version: 1,\n recipes: recipes.map(({ recipe }) => ({\n id: recipe.id,\n version: recipe.version,\n provider: recipe.provider,\n summary: recipe.summary,\n selector: `${recipe.id}@${recipe.version}`,\n })),\n }, null, 2))\n } else {\n log(` ${recipes.length} bundled recipe(s):`)\n for (const { recipe } of recipes) {\n log(` ${(recipe.id + \"@\" + recipe.version).padEnd(52)} ${recipe.summary}`)\n }\n }\n return\n }\n\n const target = args.target!\n if (args.subcommand === \"inspect\") {\n const { recipe, path: recipePath, bundled } = await resolveRecipe(target)\n if (args.json) {\n log(JSON.stringify({ ...recipe, path: recipePath, bundled }, null, 2))\n } else {\n log(` ${recipe.id}@${recipe.version}`)\n log(` ${recipe.summary}`)\n log(` provider: ${recipe.provider} · style: ${recipe.styleId} · stage: ${recipe.quality.stage}`)\n log(\n ` native target: ${recipe.quality.recommendedNativeSize.min}–` +\n `${recipe.quality.recommendedNativeSize.max}px · palette: ` +\n `${recipe.quality.paletteColors.min}–${recipe.quality.paletteColors.max} colors`,\n )\n if (recipe.workflow) log(` workflow: ${recipe.workflow.path} · ${recipe.workflow.numImages} candidate(s)`)\n for (const model of recipe.models) log(` model: ${model.path} · ${model.license}`)\n log(` source: ${recipePath}${bundled ? \" (bundled)\" : \"\"}`)\n }\n return\n }\n\n if (args.subcommand === \"verify\") {\n const report = await verifyRecipe(target, { modelRoot: args.modelRoot })\n if (args.json) {\n log(JSON.stringify(report, null, 2))\n } else {\n log(` ${report.ok ? \"ok\" : \"ERROR\"} ${report.recipe.id}@${report.recipe.version}`)\n log(` ${report.integrity.status.padEnd(9)} recipe metadata`)\n for (const file of report.files) log(` ${file.status.padEnd(9)} ${file.path}`)\n for (const model of report.models) log(` ${model.status.padEnd(9)} ${model.path}`)\n if (!report.modelRoot && report.models.length) {\n log(` models were not checked; pass --model-root <ComfyUI/models> to verify this workstation`)\n }\n }\n if (!report.ok) process.exitCode = 1\n return\n }\n\n if (args.subcommand === \"install\") {\n const result = await installRecipe(target, { out: args.out, force: args.force })\n if (args.json) {\n log(JSON.stringify({\n version: 1,\n recipe: `${result.recipe.id}@${result.recipe.version}`,\n destination: result.destination,\n changed: result.changed,\n unchanged: result.unchanged,\n styleId: result.styleId,\n style: result.style,\n }, null, 2))\n } else {\n log(` installed ${result.recipe.id}@${result.recipe.version}`)\n log(` ${path.relative(process.cwd(), result.destination) || \".\"}`)\n log(`\\n Add this entry under your manifest's styles object:`)\n log(JSON.stringify({ [result.styleId]: result.style }, null, 2))\n if (result.recipe.models.length) {\n log(`\\n Models are not downloaded automatically. Verify them with:`)\n log(` pixelkiln recipe verify ${path.relative(process.cwd(), result.destination)} --model-root <ComfyUI/models>`)\n }\n }\n return\n }\n }\n\n // Path mode stays manifest-free. Without --from, `refine run/check` falls\n // through to the manifest quality-profile workflow below.\n if (args.command === \"refine\" && (args.from || args.subcommand === \"approve\")) {\n if (!args.from) {\n throw new Error(\n args.subcommand === \"run\"\n ? \"refine needs --from <source.png>.\"\n : `refine ${args.subcommand} needs --from <output.pixelkiln.json>.`,\n )\n }\n\n if (args.subcommand === \"run\") {\n if (!args.out) throw new Error(\"refine needs --out <final.png>.\")\n if (!args.palette.length) {\n throw new Error(\"refine needs an explicit final palette via --palette <#rrggbb,...>.\")\n }\n const result = await refineAsset({\n source: args.from,\n output: args.out,\n palette: args.palette,\n fixerPython: args.fixerPython,\n fixerRevision: args.fixerRevision,\n minGridConfidence: args.minGridConfidence,\n minTransparency: args.minTransparency,\n force: args.force,\n })\n if (args.json) {\n log(JSON.stringify(result, null, 2))\n } else {\n log(\n ` recovered ${result.detection.columns}x${result.detection.rows} native grid ` +\n `(${result.detection.confidence}: ${result.detection.consensus})`,\n )\n log(` enforced ${result.palette.length}-color palette without dithering`)\n log(` wrote ${path.relative(process.cwd(), result.output)}`)\n log(` quality record: ${path.relative(process.cwd(), result.record)}`)\n log(`\\n Automated checks passed. Human 1× review is still required:`)\n log(\n ` pixelkiln refine approve --from ${path.relative(process.cwd(), result.record)} ` +\n `--reviewer \"Your Name\"`,\n )\n }\n return\n }\n\n if (args.subcommand === \"approve\") {\n if (!args.reviewer?.trim()) {\n throw new Error(\"refine approve needs --reviewer <name>.\")\n }\n const pending = await checkQualityRecord(args.from)\n log(\n pending.options.frameSet\n ? ` Inspect all ${pending.options.frameSet.count} ordered frames at 1×, integer zoom, and playback speed.`\n : ` Inspect the final PNG at 1× and integer zoom.`,\n )\n log(` Confirm crisp edges, readable forms, palette separation, alpha, and seams.`)\n if (!(await confirm(\n pending.options.frameSet\n ? \" Record this complete frame set as human-approved?\"\n : \" Record this asset as human-approved?\",\n args.yes,\n ))) {\n log(\" approval not recorded\")\n return\n }\n const result = await approveQualityRecord(args.from, {\n reviewer: args.reviewer,\n note: args.note,\n })\n if (args.json) log(JSON.stringify(result, null, 2))\n else {\n log(\n result.options.frameSet\n ? ` approved ${result.outputs.length} frames in ${path.relative(process.cwd(), result.record)} by ${args.reviewer.trim()}`\n : ` approved ${path.relative(process.cwd(), result.output)} by ${args.reviewer.trim()}`,\n )\n }\n return\n }\n\n const result = await checkQualityRecord(args.from)\n if (args.json) {\n log(JSON.stringify(result, null, 2))\n } else {\n log(` ${result.safe ? \"release-ready\" : \"not release-ready\"}: ${path.relative(process.cwd(), result.output || result.record)}`)\n for (const reason of result.reasons) log(` ${reason}`)\n }\n if (!result.safe) process.exitCode = 1\n return\n }\n\n if (args.command === \"balance\") {\n loadEnvFiles(path.dirname(path.resolve(args.manifest)))\n loadEnvFiles(process.cwd())\n const loaded = await loadManifest(args.manifest)\n const selectedProvider = accountProviderId(loaded.manifest, args.provider, \"balance\")\n const p = createProvider(selectedProvider, \"online\")\n const b = await requireBalance(p)()\n log(` provider: ${p.id}`)\n log(` plan: ${b.plan ?? \"n/a\"}`)\n log(` remaining: ${formatCost(b.unit, b.remaining)}${b.total ? ` of ${b.total}` : \"\"}`)\n return\n }\n\n if (args.command === \"init\") {\n if (!args.from) throw new Error(\"init needs --from <dir> pointing at your existing PNGs.\")\n const root = path.resolve(args.from)\n if (!existsSync(root)) throw new Error(`No directory at ${root}`)\n\n const generator = (args.generator ?? \"map\") as \"1dir\" | \"map\"\n if (generator !== \"1dir\" && generator !== \"map\") {\n throw new Error(`--generator must be \"1dir\" or \"map\", got \"${args.generator}\".`)\n }\n\n const target = path.resolve(args.out ?? \"pixelkiln.manifest.json\")\n const { assets, skipped } = await scanAssets(root, { exclude: args.exclude })\n if (!assets.length) throw new Error(`No PNGs found under ${root}`)\n\n const manifest = buildManifest(\n args.name ?? path.basename(path.dirname(target)),\n args.styles[0] ?? \"base\",\n generator,\n path.relative(path.dirname(target), root) || \".\",\n assets,\n )\n await writeManifestFile(target, manifest)\n\n log(` scanned ${assets.length} PNG(s) under ${path.relative(process.cwd(), root)}`)\n if (skipped.length) log(` skipped ${skipped.length} unreadable file(s)`)\n log(` wrote ${path.relative(process.cwd(), target)}`)\n log(`\\n Prompts are intentionally empty. To recover the real ones from your`)\n log(` PixelLab account instead of inventing them:`)\n log(`\\n pixelkiln adopt --manifest ${path.relative(process.cwd(), target)} --write-prompts\\n`)\n return\n }\n\n if (args.command === \"cache\") {\n const lock = await loadLock(args.lock)\n const report = await inspectCaches(lock, args.lock, { prune: args.prune })\n if (args.json) {\n log(JSON.stringify(report, null, 2))\n } else {\n const size = report.content.bytes < 1024\n ? `${report.content.bytes} B`\n : `${(report.content.bytes / 1024).toFixed(1)} KB`\n log(` content cache: ${report.content.path}`)\n log(\n report.content.exists\n ? ` ${report.content.valid} valid PNG(s), ${report.content.referenced} referenced, ` +\n `${report.content.unreferenced.length} unreferenced — ${size}`\n : \" not created yet\",\n )\n if (report.content.missingReferenced.length) {\n log(` ${report.content.missingReferenced.length} lockfile hash(es) are not locally cached`)\n }\n for (const issue of report.content.invalid.slice(0, 10)) {\n log(` invalid ${issue.name}: ${issue.reason}`)\n }\n if (report.content.invalid.length > 10) {\n log(` … and ${report.content.invalid.length - 10} more invalid entr(ies)`)\n }\n\n log(` remote object-hash cache: ${report.remoteHashes.path}`)\n if (!report.remoteHashes.exists) log(\" not created yet\")\n else if (report.remoteHashes.error) {\n log(` invalid cache: ${report.remoteHashes.error.split(\"\\n\")[0]}`)\n } else {\n log(\n ` ${report.remoteHashes.valid} valid entr(ies), ` +\n `${report.remoteHashes.invalidIds.length} invalid`,\n )\n }\n if (args.prune) {\n log(\n ` pruned ${report.removed.contentFiles} content file(s), ` +\n `${report.removed.remoteHashEntries} invalid remote hash entr(ies)` +\n (report.removed.resetRemoteHashCache ? \"; rebuilt malformed remote cache\" : \"\"),\n )\n }\n log(` ${report.safe ? \"cache integrity is healthy\" : \"cache integrity needs attention\"}`)\n }\n if (args.check && !report.safe) process.exitCode = 1\n return\n }\n\n if (args.command === \"pack\" && args.inputs) {\n // Handled before the manifest-required check below, deliberately: the\n // whole point of `--inputs` is packing sprites that were never part of a\n // pixelkiln manifest at all. Requiring one anyway — as this did until a\n // manual smoke test caught it — defeated the feature for exactly the\n // no-manifest consumer it was built for; heybud-admin's sync script never\n // noticed because it happens to run from a directory that has its own\n // manifest for an unrelated reason.\n if (!args.out) throw new Error(\"--inputs requires --out\")\n if (args.primaryOnly || args.outputRoles.length) {\n throw new Error(\"--primary-only and --output-role require manifest-driven pack\")\n }\n\n const raw = JSON.parse(await readFile(path.resolve(args.inputs), \"utf8\")) as unknown\n const inputs = resolvePackInputs(raw, args.inputs)\n\n const { png, atlas, skipped, sources } = packSprites(inputs, { columns: args.columns })\n const base = path.resolve(args.out.replace(/\\.png$/, \"\"))\n const outputs: ArtifactFile[] = [\n { path: `${base}.png`, data: png },\n { path: `${base}.json`, data: JSON.stringify(atlas, null, 2) + \"\\n\" },\n ]\n await writeManagedArtifactBundle(`${base}.pixelkiln.json`, outputs, {\n kind: \"pack\",\n sources: [await provenanceFile(\"$inputs\", args.inputs), ...sources],\n options: { columns: args.columns ?? null, order: \"id\", style: null },\n }, { force: args.force })\n log(\n ` ${atlas.frames.length} sprite(s), ${atlas.sheet.width}x${atlas.sheet.height} ` +\n `in ${atlas.columns} column(s) — ${(png.length / 1024).toFixed(1)} KB`,\n )\n log(` ${path.relative(process.cwd(), base)}.png + .json + .pixelkiln.json`)\n for (const s of skipped) log(` skipped ${s.id}: ${s.reason}`)\n return\n }\n\n if (args.command === \"workspace\") {\n // No manifest is required in cwd for any of these — a catalog is meant to\n // be operated on from outside any one project.\n const workspacePath = path.resolve(args.workspace ?? \"pixelkiln.workspace.json\")\n const dir = path.dirname(workspacePath)\n\n if (args.subcommand === \"add\") {\n const manifestPath = path.resolve(args.target!)\n const loadedTarget = await loadManifest(manifestPath)\n const lockPath = args.explicitLock\n ? path.resolve(args.explicitLock)\n : path.join(path.dirname(manifestPath), \"pixelkiln.lock.json\")\n\n const ws = await loadWorkspace(workspacePath)\n const id = args.name ?? loadedTarget.manifest.name\n if (ws.projects.some((p) => p.id === id)) {\n throw new Error(\n `Project id \"${id}\" is already registered in ${workspacePath}. Pass --name for a different id.`,\n )\n }\n const lockOwner = ws.projects.find((p) => resolveProject(dir, p).lockPath === lockPath)\n if (lockOwner) {\n throw new Error(`Lockfile ${lockPath} is already registered under project id \"${lockOwner.id}\".`)\n }\n\n const project: WorkspaceProject = {\n id,\n manifest: toPortablePath(dir, manifestPath),\n lock: toPortablePath(dir, lockPath),\n provider: args.provider ?? loadedTarget.manifest.provider,\n ...(args.account ? { account: args.account } : {}),\n }\n await saveWorkspace(workspacePath, { version: 1, projects: [...ws.projects, project] })\n log(` registered \"${id}\" in ${path.relative(process.cwd(), workspacePath)}`)\n log(` manifest: ${project.manifest}`)\n log(` lock: ${project.lock}`)\n if (!existsSync(lockPath)) {\n log(\n ` warning: no lockfile there yet — this project contributes no claims until one is generated`,\n )\n }\n return\n }\n\n if (args.subcommand === \"remove\") {\n const ws = await loadWorkspace(workspacePath)\n const resolvedTarget = path.resolve(args.target!)\n const match = ws.projects.find(\n (p) => p.id === args.target || resolveProject(dir, p).manifestPath === resolvedTarget,\n )\n if (!match) {\n throw new Error(`No registered project matches \"${args.target}\" (checked id and manifest path).`)\n }\n await saveWorkspace(workspacePath, {\n version: 1,\n projects: ws.projects.filter((p) => p !== match),\n })\n log(` removed \"${match.id}\" from ${path.relative(process.cwd(), workspacePath)}`)\n return\n }\n\n if (args.subcommand === \"list\") {\n if (!existsSync(workspacePath)) {\n throw new Error(`Workspace catalog not found: ${workspacePath}`)\n }\n const ws = await loadWorkspace(workspacePath)\n const diagnostics = validateWorkspace(ws, dir)\n if (args.json) {\n log(JSON.stringify({ version: 1, workspace: workspacePath, projects: ws.projects, diagnostics }, null, 2))\n } else if (!ws.projects.length) {\n log(` no projects registered in ${path.relative(process.cwd(), workspacePath)}`)\n } else {\n log(` ${ws.projects.length} project(s) in ${path.relative(process.cwd(), workspacePath)}:`)\n for (const p of ws.projects) {\n log(` ${p.id.padEnd(24)} ${p.manifest.padEnd(40)} (${p.provider}${p.account ? `, ${p.account}` : \"\"})`)\n }\n for (const d of diagnostics) log(` ${d.level === \"error\" ? \"ERROR\" : \"WARN \"} ${d.id.padEnd(18)} ${d.message}`)\n }\n if (args.check && diagnostics.some((d) => d.level === \"error\")) process.exitCode = 1\n return\n }\n\n if (args.subcommand === \"status\") {\n if (!existsSync(workspacePath)) {\n throw new Error(`Workspace catalog not found: ${workspacePath}`)\n }\n const ws = await loadWorkspace(workspacePath)\n const report = await workspaceStatus(ws, dir)\n if (args.json) {\n log(JSON.stringify({ ...report, workspace: workspacePath }, null, 2))\n } else {\n log(` workspace: ${path.relative(process.cwd(), workspacePath)}`)\n for (const p of report.projects) {\n if (p.error) {\n log(`\\n ${p.id} — ERROR: ${p.error}`)\n continue\n }\n log(\n `\\n ${p.id} (${p.providers.join(\" + \")}` +\n `${p.account ? `, ${p.account}` : \"\"})`,\n )\n log(` ${p.entries} lock entries`)\n for (const [state, n] of Object.entries(p.byState)) if (n) log(` ${state.padEnd(12)} ${n}`)\n for (const [unit, amount] of Object.entries(p.spendByUnit).sort()) {\n if (amount) log(` spend: ${formatCost(unit, amount)}`)\n }\n }\n log(`\\n totals:`)\n for (const [state, n] of Object.entries(report.totals.byState)) if (n) log(` ${state.padEnd(12)} ${n}`)\n for (const [unit, amount] of Object.entries(report.totals.spendByUnit).sort()) {\n if (amount) log(` spend: ${formatCost(unit, amount)}`)\n }\n log(` claims: ${report.totals.claims}`)\n for (const d of report.diagnostics) log(` ${d.level === \"error\" ? \"ERROR\" : \"WARN \"} ${d.id.padEnd(18)} ${d.message}`)\n }\n if (args.check && !report.safe) process.exitCode = 1\n return\n }\n\n if (args.subcommand === \"claims\") {\n const { claims, diagnostics } = await requireCompleteWorkspaceClaims(workspacePath)\n if (args.json) {\n log(JSON.stringify({\n version: 1,\n claimed: [...claims.claimed].sort(),\n byProject: claims.byProject,\n lockPaths: claims.lockPaths,\n }, null, 2))\n } else {\n log(` ${claims.claimed.size} claimed id(s) across ${claims.lockPaths.length} lockfile(s):`)\n for (const [id, n] of Object.entries(claims.byProject).sort()) log(` ${id.padEnd(24)} ${n}`)\n for (const d of diagnostics) log(` WARN ${d.id.padEnd(18)} ${d.message}`)\n }\n return\n }\n }\n\n if (!existsSync(path.resolve(args.manifest))) {\n throw new Error(\n `No manifest at ${path.resolve(args.manifest)}. Pass --manifest, or run \\`pixelkiln init --from <dir>\\`.`,\n )\n }\n\n // Load env before any provider is constructed, from the manifest's directory\n // and the cwd — the key belongs with the project, not the tool.\n const manifestDir = path.dirname(path.resolve(args.manifest))\n const envFiles = [...loadEnvFiles(manifestDir)]\n if (path.resolve(process.cwd()) !== manifestDir) envFiles.push(...loadEnvFiles(process.cwd()))\n\n const loaded = await loadManifest(args.manifest)\n let specs = await resolveSpecs(loaded, {\n styles: args.styles,\n assets: args.assets,\n })\n const accountCommands = new Set([\"adopt\", \"salvage\", \"purge\"])\n const selectedAccountProvider = accountCommands.has(args.command)\n ? accountProviderId(loaded.manifest, args.provider, args.command)\n : undefined\n if (args.provider && !selectedAccountProvider) {\n throw new Error(\n \"--provider is only used by balance, adopt, salvage, purge, or workspace add.\",\n )\n }\n if (selectedAccountProvider) {\n specs = specs.filter((spec) => spec.provider === selectedAccountProvider)\n }\n const accountManifest: Manifest = selectedAccountProvider\n ? {\n ...loaded.manifest,\n provider: selectedAccountProvider,\n styles: Object.fromEntries(\n Object.entries(loaded.manifest.styles).filter(\n ([, style]) => (style.provider ?? loaded.manifest.provider) === selectedAccountProvider,\n ),\n ),\n }\n : loaded.manifest\n if (\n selectedAccountProvider &&\n args.styles.some((styleId) => !accountManifest.styles[styleId])\n ) {\n throw new Error(\n `Selected style is not assigned to provider \"${selectedAccountProvider}\".`,\n )\n }\n const lock = await loadLock(args.lock)\n normalizeLockOutputPaths(lock, specs)\n\n if (args.command === \"status\") {\n const byStatus: Record<string, number> = {}\n for (const e of Object.values(lock.entries)) byStatus[e.status] = (byStatus[e.status] ?? 0) + 1\n if (args.json) {\n log(JSON.stringify({ entries: Object.keys(lock.entries).length, byStatus, spendByUnit: spendByUnit(lock) }, null, 2))\n return\n }\n log(` ${Object.keys(lock.entries).length} lock entries`)\n for (const [s, n] of Object.entries(byStatus).sort()) log(` ${s.padEnd(12)} ${n}`)\n const spend = spendByUnit(lock)\n let reported = false\n for (const [unit, amount] of Object.entries(spend).sort()) {\n if (amount) {\n log(` recorded successful submissions: ${formatCost(unit, amount)}`)\n reported = true\n }\n }\n if (!reported) log(` no successful submission cost recorded`)\n return\n }\n\n const plan = await buildPlan(specs, lock, { force: args.force })\n\n if (args.command === \"refine\") {\n const pathOwnedFlags = [\n args.out ? \"--out\" : null,\n args.palette.length ? \"--palette\" : null,\n args.fixerRevision ? \"--fixer-revision\" : null,\n args.minGridConfidence ? \"--min-grid-confidence\" : null,\n args.minTransparency != null ? \"--min-transparency\" : null,\n ].filter(Boolean)\n if (pathOwnedFlags.length) {\n throw new Error(\n `${pathOwnedFlags.join(\", \")} require --from. Manifest mode reads output, palette, ` +\n \"revision, and thresholds from style.quality.\",\n )\n }\n\n if (args.subcommand === \"check\") {\n const inspections = (await Promise.all(\n specs.filter((spec) => spec.quality).map((spec) => inspectQualityProfile(spec, lock)),\n )).filter((item) => item !== null)\n if (!inspections.length) throw new Error(\"No selected style has a quality profile.\")\n const safe = inspections.every((item) => item.state === \"approved\")\n if (args.json) {\n log(JSON.stringify({ version: 1, safe, items: inspections }, null, 2))\n } else {\n for (const item of inspections) {\n log(` ${item.state.padEnd(16)} ${item.key} ${item.reason}`)\n }\n }\n if (!safe) process.exitCode = 1\n return\n }\n\n const result = await refineQualityProfiles(specs, lock, {\n fixerPython: args.fixerPython,\n force: args.force,\n })\n if (args.json) {\n log(JSON.stringify({ version: 1, ...result }, null, 2))\n } else {\n for (const item of result.items) {\n log(` ${item.state.padEnd(16)} ${item.key} ${item.reason}`)\n if (item.state === \"needs-approval\") {\n log(\n ` pixelkiln refine approve --from ${path.relative(process.cwd(), item.record)} ` +\n `--reviewer \"Your Name\"`,\n )\n }\n }\n log(`\\n ${result.processed} refined, ${result.skipped} unchanged, ${result.failed} failed`)\n }\n if (result.failed) process.exitCode = 1\n return\n }\n\n if (args.command === \"doctor\") {\n const selectedStyleIds = args.styles.length\n ? args.styles\n : Object.keys(loaded.manifest.styles)\n const providerIds = [...new Set(\n selectedStyleIds.map((styleId) =>\n loaded.manifest.styles[styleId]?.provider ?? loaded.manifest.provider),\n )].sort()\n const providers = providerIds.map((id) => {\n const factory = providerFactory(id)\n const credentialEnvs = providerCredentialEnvs(factory)\n const missingCredentialEnvs = credentialEnvs.filter((name) => !process.env[name])\n const apiKeyPresent = missingCredentialEnvs.length === 0\n return {\n id,\n apiKeyPresent,\n credentialEnv: factory.credentialEnv,\n missingCredentialEnvs,\n provider: !args.dryRun && apiKeyPresent ? createProvider(id, \"online\") : undefined,\n }\n })\n const report = await doctor(loaded, specs, lock, args.lock, {\n providers,\n offline: args.dryRun,\n })\n if (args.json) {\n log(JSON.stringify(report, null, 2))\n } else {\n for (const check of report.checks) {\n const icon = check.level === \"ok\" ? \"ok\" : check.level === \"warning\" ? \"WARN\" : \"ERROR\"\n log(` ${icon.padEnd(5)} ${check.id.padEnd(14)} ${check.message}`)\n }\n }\n if (!report.ok) process.exitCode = 1\n return\n }\n\n if (args.command === \"plan\") {\n if (args.json) {\n log(JSON.stringify({\n totals: summarize(plan),\n cost: plan.cost,\n costUnit: plan.costUnit,\n candidates: plan.candidates,\n groups: plan.groups.map((group) => ({\n provider: group.provider,\n cost: group.cost,\n costUnit: group.costUnit,\n candidates: group.candidates,\n actionable: group.actionable.map((item) => item.key),\n })),\n actionable: plan.actionable.map((i) => i.key),\n items: plan.items.map(({ key, state, reason, quality, spec }) => ({\n key,\n state,\n reason,\n ...(spec.revision\n ? {\n revision: {\n mode: spec.revision.mode,\n from: spec.revision.sourceAssetId,\n sourceSha256: spec.revision.sourceSha256,\n ...(spec.revision.maskSha256\n ? { maskSha256: spec.revision.maskSha256 }\n : {}),\n ...(spec.revision.strength == null ? {} : { strength: spec.revision.strength }),\n },\n }\n : {}),\n ...(quality ? { quality: { state: quality.state, reason: quality.reason } } : {}),\n })),\n }, null, 2))\n } else {\n printPlan(plan)\n }\n if (\n args.check && plan.items.some(\n (item) => item.state !== \"ok\" || (item.quality && item.quality.state !== \"approved\"),\n )\n ) process.exitCode = 1\n return\n }\n\n if (args.command === \"accept\") {\n // Re-baselines stale entries against the current spec without regenerating.\n // For when the style prose was reworded but the existing art is still wanted.\n let accepted = 0\n for (const item of plan.items) {\n if (item.state !== \"stale\") continue\n const entry = lock.entries[item.key]\n // Accepting new wording is safe; accepting a provider change would\n // relabel old remote work as if the new backend produced it.\n if (!entry || entry.provider !== item.spec.provider || entry.outputs.length === 0) continue\n let intact = true\n for (const output of entry.outputs) {\n const file = resolveOutputPath(output.path, item.spec.root)\n if (!existsSync(file) || (await sha256File(file)) !== output.sha256) {\n intact = false\n break\n }\n }\n if (!intact) continue\n upsertLock(lock, item.key, { specHash: item.spec.specHash })\n accepted++\n }\n await saveLock(args.lock, lock)\n log(` accepted ${accepted} existing file(s) as satisfying the current spec`)\n log(` (their artwork is unchanged; only the recorded spec hash moved)`)\n return\n }\n\n if (args.command === \"prune\") {\n // Removes lock entries no style/asset pair in the manifest resolves to.\n // These accumulate when an asset is renamed or moved between styles: the\n // old entry keeps claiming the output path the new one now owns, which is\n // `doctor`'s lock-outputs error. Until `remove` existed there was no way\n // to clear one short of hand-editing the lockfile.\n //\n // Deliberately resolved from the whole manifest rather than the filtered\n // `specs`: under `--style base` every other style's entries would look\n // undeclared, and prune would delete the lot.\n if (args.styles.length || args.assets.length) {\n throw new Error(\n \"prune compares the lockfile against the entire manifest, so --style \" +\n \"and --only would make it delete the entries they filter out. Run it unfiltered.\",\n )\n }\n const declared = new Set((await resolveSpecs(loaded)).map((s) => lockKey(s.styleId, s.assetId)))\n const orphans = Object.keys(lock.entries).filter((key) => !declared.has(key)).sort()\n if (!orphans.length) {\n log(` every lock entry is declared by the manifest — nothing to prune`)\n return\n }\n\n log(`\n ${orphans.length} lock entr(ies) the manifest no longer declares:`)\n for (const key of orphans.slice(0, 20)) {\n const outputs = lock.entries[key]?.outputs ?? []\n const where = outputs[0]?.path ?? \"no recorded output\"\n log(` ${key.padEnd(44)} ${where}`)\n }\n if (orphans.length > 20) log(` … and ${orphans.length - 20} more`)\n\n if (args.dryRun) {\n log(`\n --dry-run: nothing removed.`)\n return\n }\n log(`\n This drops their provenance from the lockfile. The art on disk is`)\n log(` untouched, and nothing is deleted from your provider account — but`)\n log(` the link from those files back to the objects that made them is gone,`)\n log(` and the objects will read as unclaimed the next time you run salvage.`)\n if (!(await confirm(` Remove ${orphans.length} lock entr(ies)?`, args.yes))) {\n log(` aborted`)\n return\n }\n\n let removed = 0\n for (const key of orphans) if (removeLock(lock, key)) removed++\n await saveLock(args.lock, lock)\n log(` removed ${removed} lock entr(ies); ${Object.keys(lock.entries).length} remain`)\n return\n }\n\n if (args.command === \"pack\") {\n // The --inputs form is handled earlier, before the manifest is required\n // at all — reaching here means the manifest-driven (lockfile) form.\n if (args.primaryOnly && args.outputRoles.length) {\n throw new Error(\"pack accepts either --primary-only or --output-role, not both\")\n }\n const manifestDir = path.dirname(path.resolve(args.manifest))\n const styleIds = args.styles.length ? args.styles : Object.keys(loaded.manifest.styles)\n\n for (const styleId of styleIds) {\n const packagingSpecs = await resolveSpecs(loaded, { styles: [styleId] })\n const qualitySources = await requireApprovedQualitySources(packagingSpecs, lock)\n const { png, atlas, skipped, sources } = packStyle(lock, styleId, manifestDir, {\n columns: args.columns,\n outputRoles: args.outputRoles,\n primaryOnly: args.primaryOnly,\n sourceOverrides: qualitySources,\n })\n\n // Default beside the style's own output tree, so sheets for different\n // styles cannot overwrite each other when --out is omitted.\n const style = loaded.manifest.styles[styleId]\n const base = args.out\n ? path.resolve(args.out.replace(/\\.png$/, \"\"))\n : path.resolve(manifestDir, style!.outDir, `${styleId}-sheet`)\n\n const outputs: ArtifactFile[] = [\n { path: `${base}.png`, data: png },\n { path: `${base}.json`, data: JSON.stringify(atlas, null, 2) + \"\\n\" },\n ]\n const qualityRecords = qualitySources\n ? await Promise.all(\n packagingSpecs.filter((spec) => spec.quality).map((spec) =>\n provenanceFile(\n `$quality/${spec.assetId}`,\n qualityRecordPath(spec.quality!.outFile),\n )),\n )\n : []\n await writeManagedArtifactBundle(`${base}.pixelkiln.json`, outputs, {\n kind: \"pack\",\n sources: [\n await provenanceFile(\"$manifest\", args.manifest),\n await provenanceFile(\"$lock\", args.lock),\n ...qualityRecords,\n ...sources,\n ],\n options: {\n columns: args.columns ?? null,\n order: \"id\",\n outputRoles: [...args.outputRoles].sort(),\n primaryOnly: args.primaryOnly,\n style: styleId,\n },\n }, { force: args.force })\n\n log(\n ` ${styleId} — ${atlas.frames.length} sprite(s), ` +\n `${atlas.sheet.width}x${atlas.sheet.height} in ${atlas.columns} column(s)`,\n )\n log(` ${path.relative(process.cwd(), base)}.png + .json + .pixelkiln.json`)\n for (const s of skipped) log(` skipped ${s.id}: ${s.reason}`)\n }\n return\n }\n\n if (args.command === \"mount\") {\n const manifestDir = path.dirname(path.resolve(args.manifest))\n const styleIds = args.styles.length ? args.styles : Object.keys(loaded.manifest.styles)\n\n for (const styleId of styleIds) {\n const style = loaded.manifest.styles[styleId]\n if (!style?.mount) {\n // Not an error when the caller did not name a style — `mount` with no\n // --style should do the mounted ones and stay quiet about the rest.\n if (args.styles.length) {\n throw new Error(\n `Style \"${styleId}\" has no \\`mount\\` block. Add one, or use \\`pack\\` ` +\n `to let pixelkiln choose the layout.`,\n )\n }\n continue\n }\n\n const cells: Record<string, [number, number]> = {}\n const sources: Record<string, string> = {}\n const outputRoles: Record<string, string> = {}\n for (const [assetId, asset] of Object.entries(loaded.manifest.assets)) {\n if (!asset.cell) continue\n cells[assetId] = asset.cell\n if (asset.source) sources[assetId] = asset.source\n if (asset.outputRole) outputRoles[assetId] = asset.outputRole\n }\n const packagingSpecs = await resolveSpecs(loaded, { styles: [styleId] })\n const qualitySources = await requireApprovedQualitySources(\n packagingSpecs,\n lock,\n new Set(Object.keys(cells)),\n outputRoles,\n )\n if (qualitySources) Object.assign(sources, qualitySources)\n\n const { png, atlas, skipped, overBase, sources: artifactSources } = mountStyle(\n lock,\n styleId,\n manifestDir,\n style.mount,\n cells,\n sources,\n outputRoles,\n )\n\n const out = path.resolve(manifestDir, style.mount.out)\n const metadata = out.replace(/\\.png$/, \"\") + \".json\"\n const companion = out.replace(/\\.png$/, \"\") + \".pixelkiln.json\"\n const outputs: ArtifactFile[] = [\n { path: out, data: png },\n { path: metadata, data: JSON.stringify(atlas, null, 2) + \"\\n\" },\n ]\n const qualityRecords = qualitySources\n ? await Promise.all(\n packagingSpecs\n .filter((spec) => spec.quality && Object.hasOwn(cells, spec.assetId))\n .map((spec) =>\n provenanceFile(\n `$quality/${spec.assetId}`,\n qualityRecordPath(spec.quality!.outFile),\n )),\n )\n : []\n await writeManagedArtifactBundle(companion, outputs, {\n kind: \"mount\",\n sources: [\n await provenanceFile(\"$manifest\", args.manifest),\n await provenanceFile(\"$lock\", args.lock),\n ...qualityRecords,\n ...artifactSources.filter(\n (source) => source.id !== \"$base\" || path.resolve(source.path) !== out,\n ),\n ],\n options: {\n cellHeight: style.mount.cellHeight,\n cellWidth: style.mount.cellWidth,\n cells: Object.entries(cells).sort(([a], [b]) => a.localeCompare(b)),\n style: styleId,\n },\n }, { force: args.force })\n\n log(\n ` ${styleId} — ${atlas.frames.length} cell(s) into ` +\n `${atlas.sheet.width}x${atlas.sheet.height}` +\n (overBase ? ` over ${style.mount.base}` : \" (new sheet)\"),\n )\n log(` ${path.relative(process.cwd(), out)} + atlas/provenance JSON`)\n for (const s of skipped) log(` skipped ${s.id}: ${s.reason}`)\n }\n return\n }\n\n if (args.command === \"audit\") {\n const styleIds = args.styles.length ? args.styles : Object.keys(loaded.manifest.styles)\n const reports: Array<{\n audit: Awaited<ReturnType<typeof auditStyle>>\n evaluation: ReturnType<typeof evaluateAudit>\n }> = []\n for (const styleId of styleIds) {\n const audit = await auditStyle(loaded, specs, styleId, lock)\n const evaluation = evaluateAudit(audit, {\n maxDistance: args.maxDistance,\n minTransparency: args.minTransparency,\n maxColors: args.maxColors,\n sigma: args.sigma,\n })\n reports.push({ audit, evaluation })\n if (args.json) continue\n log(`\\n ${styleId} — ${audit.assets.length} asset(s) measured`)\n log(\n ` reference palette: ${audit.referenceFromStyleImages ? \"style images\" : \"the set's own average\"}` +\n ` ${audit.reference.slice(0, 6).map(hex).join(\" \")}`,\n )\n if (!audit.referenceFromStyleImages) {\n log(` (no styleImages set — this finds outliers but cannot tell you the whole set drifted)`)\n }\n\n const offIds = new Set(evaluation.outliers)\n log(`\\n most off-style first:`)\n for (const asset of audit.assets.slice(0, 12)) {\n const flag = offIds.has(asset.id) ? \" ← outlier\" : \"\"\n log(\n ` ${asset.id.padEnd(28)} dist ${asset.paletteDistance.toFixed(1).padStart(6)}` +\n ` colours ${String(asset.colorCount).padStart(4)}` +\n ` transparent ${(asset.transparency * 100).toFixed(0).padStart(3)}%` +\n ` ${asset.palette.slice(0, 3).map(hex).join(\" \")}${flag}`,\n )\n }\n if (audit.assets.length > 12) log(` … and ${audit.assets.length - 12} more`)\n log(`\\n ${evaluation.outliers.length} outlier(s) beyond ${evaluation.thresholds.sigma} sd`)\n if (audit.missing.length) log(` ${audit.missing.length} asset(s) not on disk`)\n for (const u of audit.unreadable) log(` unreadable ${u}`)\n for (const violation of evaluation.violations) {\n log(` check ${violation.id}: ${violation.reasons.join(\"; \")}`)\n }\n }\n if (args.json) {\n log(JSON.stringify({\n version: 1,\n safe: reports.every((report) => report.evaluation.safe),\n styles: reports.map(({ audit, evaluation }) => ({ ...audit, evaluation })),\n }, null, 2))\n }\n if (args.check && reports.some((report) => !report.evaluation.safe)) process.exitCode = 1\n return\n }\n\n if (args.command === \"export\") {\n const format = args.format ?? \"generic\"\n const manifestDir = path.dirname(path.resolve(args.manifest))\n const selected = specs.filter((spec) => {\n if (spec.generator !== \"tiles\") return false\n if (args.styles.length && !args.styles.includes(spec.styleId)) return false\n if (args.assets.length && !args.assets.includes(spec.assetId)) return false\n return Boolean(lock.entries[lockKey(spec.styleId, spec.assetId)])\n })\n if (!selected.length) {\n throw new Error(\"No downloaded tiles entries match the requested --style/--only filters.\")\n }\n if (args.out && selected.length > 1) {\n throw new Error(\"--out can name one tileset only; add --style/--only to select one asset.\")\n }\n\n for (const spec of selected) {\n const entry = lock.entries[lockKey(spec.styleId, spec.assetId)]!\n const style = loaded.manifest.styles[spec.styleId]!\n const defaultBase = path.resolve(manifestDir, style.outDir, `${spec.assetId}-tileset`)\n const base = args.out\n ? path.resolve(args.out.replace(/\\.(?:png|json|tsj|tres)$/i, \"\"))\n : defaultBase\n const result = exportTileset(entry, spec, {\n format,\n manifestDir,\n imageName: path.basename(`${base}.png`),\n columns: args.columns,\n })\n const outputs: ArtifactFile[] = [\n { path: `${base}.png`, data: result.png },\n { path: `${base}${result.extension}`, data: result.document },\n ]\n await writeManagedArtifactBundle(`${base}.pixelkiln.json`, outputs, {\n kind: \"tileset\",\n sources: [\n await provenanceFile(\"$manifest\", args.manifest),\n await provenanceFile(\"$lock\", args.lock),\n ...result.sources,\n ],\n options: {\n asset: spec.assetId,\n columns: args.columns ?? null,\n format,\n image: path.basename(`${base}.png`),\n providerRules: result.generic.providerRules,\n style: spec.styleId,\n tileType: spec.tileType ?? null,\n },\n }, { force: args.force })\n log(\n ` ${spec.styleId}/${spec.assetId} — ${result.generic.tiles.length} tile(s), ` +\n `${result.generic.sheet.width}x${result.generic.sheet.height} (${format})`,\n )\n log(\n ` ${path.relative(process.cwd(), base)}.png + ` +\n `${path.basename(base)}${result.extension} + .pixelkiln.json`,\n )\n }\n return\n }\n\n const providerMode: ProviderMode =\n args.command === \"restore\" || (args.command === \"fetch\" && !args.tag)\n ? \"downloads\"\n : \"online\"\n const providers = new Map<string, Provider>()\n const providerFor = (id: string) => {\n let resolved = providers.get(id)\n if (!resolved) {\n resolved = createProvider(id, providerMode)\n providers.set(id, resolved)\n }\n return resolved\n }\n if (args.command === \"adopt\") {\n const provider = providerFor(selectedAccountProvider!)\n log(`\\n Reconciling account objects against files already on disk…`)\n const res = await adopt(provider, specs, lock, args.lock, { onProgress: log })\n log(`\\n scanned ${res.scanned} remote object(s), adopted ${res.matched}`)\n if (res.ambiguous.length) {\n log(`\\n ambiguous (${res.ambiguous.length}):`)\n for (const a of res.ambiguous.slice(0, 10)) log(` ${a}`)\n }\n if (res.unmatchedLocal.length) {\n log(`\\n local files with no matching remote object (${res.unmatchedLocal.length}):`)\n for (const u of res.unmatchedLocal.slice(0, 15)) log(` ${u}`)\n }\n if (res.unmatchedRemote.length) {\n log(`\\n remote objects not matched by THIS manifest (${res.unmatchedRemote.length}):`)\n log(formatUnmatchedRemote(res.unmatchedRemote))\n log(\n `\\n One account is shared across projects, so this list mixes discarded\\n` +\n ` candidates with assets belonging to other manifests. Do not bulk-delete\\n` +\n ` it — run adopt from each project first, then \\`pixelkiln salvage\\` to\\n` +\n ` triage what is left over.`,\n )\n }\n if (args.tag) {\n const n = await tagAdopted(provider, specs, lock, { onProgress: log })\n log(`\\n tagged ${n} object(s) upstream`)\n }\n if (args.writePrompts) {\n const { filled, stillEmpty } = await writePromptsBack(path.resolve(args.manifest), lock, {\n onProgress: log,\n provider: provider.id,\n assetIds: specs.map((spec) => spec.assetId),\n })\n log(` recovered ${filled} prompt(s) into ${path.relative(process.cwd(), args.manifest)}`)\n\n // Writing prompts rewrites the manifest, which changes every spec hash.\n // Without re-baselining, an adopt that recovered the true prompts would\n // report all of its own work as stale and offer to regenerate it.\n const reloaded = await loadManifest(args.manifest)\n const rebased = (await resolveSpecs(reloaded, {\n styles: args.styles,\n assets: args.assets,\n })).filter((spec) => spec.provider === provider.id)\n let n = 0\n for (const spec of rebased) {\n const key = lockKey(spec.styleId, spec.assetId)\n if (lock.entries[key]?.status !== \"downloaded\") continue\n upsertLock(lock, key, { specHash: spec.specHash })\n n++\n }\n await saveLock(args.lock, lock)\n log(` re-baselined ${n} entr(ies) against the recovered prompts`)\n if (stillEmpty.length) {\n log(` ${stillEmpty.length} asset(s) still have no prompt (not matched upstream):`)\n for (const id of stillEmpty.slice(0, 10)) log(` ${id}`)\n if (stillEmpty.length > 10) log(` … and ${stillEmpty.length - 10} more`)\n }\n }\n log(`\\n lockfile written: ${args.lock}`)\n return\n }\n\n if (args.command === \"salvage\") {\n const provider = providerFor(selectedAccountProvider!)\n // --json is a machine-readable contract: stdout must be the JSON array\n // and nothing else, so `pixelkiln salvage --dry-run --json | jq` works.\n // Every human-oriented line below goes through `diag` instead of `log` so\n // it lands on stderr — visible in a terminal, invisible to a pipe — and\n // only the final JSON.stringify call ever reaches console.log.\n const jsonMode = args.dryRun && args.json\n const diag = jsonMode ? (msg = \"\") => console.error(msg) : log\n\n // Correctness depends on a complete claim set. Missing a lockfile makes\n // another project's shipped art look unclaimed, so this is stated loudly.\n // This project's own lockfile is optional — salvage is a reasonable first\n // command in a fresh project, which has none yet. Paths given via --claims\n // are required, because a typo there silently widens the orphan set.\n const ownLock = path.resolve(args.lock)\n let workspaceProjects: WorkspaceProject[] = []\n let workspaceDir = \"\"\n if (args.workspace) {\n const workspacePath = path.resolve(args.workspace)\n workspaceDir = path.dirname(workspacePath)\n const complete = await requireCompleteWorkspaceClaims(workspacePath)\n workspaceProjects = complete.ws.projects\n for (const d of complete.diagnostics) diag(` WARN ${d.id}: ${d.message}`)\n }\n const workspaceLockPaths = workspaceProjects.map((p) => resolveProject(workspaceDir, p).lockPath)\n const lockPaths = [\n ...new Set([\n ...workspaceLockPaths,\n ...(existsSync(ownLock) ? [ownLock] : []),\n ...args.claims.map((c) => path.resolve(c)),\n ]),\n ]\n diag(` claim set (${lockPaths.length} lockfile(s)):`)\n for (const p of lockPaths) diag(` ${path.relative(process.cwd(), p)}`)\n if (!args.claims.length && !args.workspace) {\n diag(\n `\\n Only this project's lockfile was consulted. If the account is shared,\\n` +\n ` pass every other project's lockfile via --claims a.json,b.json, or\\n` +\n ` register every project in a workspace catalog and pass --workspace.`,\n )\n } else if (\n args.workspace &&\n !workspaceProjects.some((p) => resolveProject(workspaceDir, p).manifestPath === path.resolve(args.manifest))\n ) {\n diag(\n `\\n This project's manifest is not registered in the workspace catalog. Its own\\n` +\n ` lockfile is still included above, so this run's claim set is complete — but\\n` +\n ` \\`pixelkiln workspace add ${args.manifest}\\` would keep it aggregated too.`,\n )\n }\n\n const claimed = await loadClaims(lockPaths, { provider: provider.id })\n const { orphans, total } = await findOrphans(provider, claimed, { onProgress: diag })\n diag(` ${claimed.size} claimed · ${orphans.length} unclaimed of ${total}`)\n if (!orphans.length) {\n if (jsonMode) log(\"[]\")\n else log(`\\n nothing to triage`)\n return\n }\n\n // Each sibling project's manifest, loaded purely so a single-style\n // manifest — which has no pattern of its own to check against — can still\n // recognise \"this looks like project X's art\" instead of silently\n // claiming everything by default.\n const siblings = await loadSiblingManifests(\n args.manifest,\n workspaceProjects.map((p) => resolveProject(workspaceDir, p).manifestPath),\n args.claims,\n )\n\n // Which style each orphan's prompt was most likely generated from, so a\n // shared account's orphan pool doesn't get triaged as one undifferentiated\n // blob under whichever style happens to be first in the manifest.\n const { matched, unmatched, elsewhere } = groupOrphansByStyle(orphans, accountManifest, siblings)\n const multiStyle = Object.keys(accountManifest.styles).length > 1\n if (multiStyle) {\n diag(`\\n by style (matched against each style's prompt prefix/suffix):`)\n for (const [id, list] of matched) diag(` ${id.padEnd(24)} ${list.length}`)\n if (unmatched.length) diag(` ${\"(no style match)\".padEnd(24)} ${unmatched.length}`)\n }\n if (elsewhere.size) {\n diag(`\\n matched a sibling project's own style instead of this one:`)\n for (const [label, list] of elsewhere) diag(` ${label.padEnd(28)} ${list.length}`)\n diag(` excluded from every session below — not this project's art.`)\n }\n if (unmatched.length) {\n diag(\n `\\n ${unmatched.length} object(s) don't match any known style pattern.\\n` +\n ` If the account is shared, they may belong to a different project — check\\n` +\n ` you've passed every sibling project's lockfile via --claims. They're left\\n` +\n ` out of the sessions below; force them into one style with --style <id>.`,\n )\n }\n\n if (args.dryRun) {\n if (args.json) {\n log(JSON.stringify(orphans, null, 2))\n } else {\n const shown = args.all ? orphans : orphans.slice(0, 30)\n for (const o of shown) {\n log(` ${o.id} ${o.width}x${o.height} ${o.createdAt.slice(0, 10)} ${o.prompt.slice(0, 50)}`)\n }\n if (!args.all && orphans.length > 30) {\n log(` … and ${orphans.length - 30} more (--all for the full list, --json for machine-readable)`)\n }\n }\n diag(`\\n --dry-run: nothing changed.`)\n return\n }\n\n const rebaseline = async () => {\n // Imports append to the manifest, so their spec hashes only exist after\n // it is rewritten. Without this every salvaged asset reports `stale` on\n // the next plan and offers to regenerate art that was just recovered —\n // which would re-pay for all of it.\n const reloaded = await loadManifest(args.manifest)\n const rebased = (await resolveSpecs(reloaded)).filter((spec) => spec.provider === provider.id)\n let n = 0\n for (const spec of rebased) {\n const key = lockKey(spec.styleId, spec.assetId)\n const entry = lock.entries[key]\n if (entry?.status !== \"downloaded\" || entry.specHash !== SALVAGED_SPEC_HASH) continue\n upsertLock(lock, key, { specHash: spec.specHash })\n n++\n }\n await saveLock(args.lock, lock)\n if (n) log(` baselined ${n} imported asset(s) against the manifest`)\n }\n\n const runOne = async (styleId: string, list: typeof orphans) => {\n const style = accountManifest.styles[styleId]!\n const res = await runSalvage(\n provider,\n list,\n {\n manifestPath: loaded.path,\n manifest: accountManifest,\n styleId,\n importDir: path.resolve(loaded.root, style.outDir),\n lock,\n lockPath: args.lock,\n },\n { port: args.port, open: !args.noOpen, onProgress: log },\n )\n log(\n ` imported ${res.imported} · kept ${res.kept} · tagged-discard ${res.discarded}` +\n (res.failed ? ` · failed ${res.failed}` : \"\"),\n )\n if (res.imported > 0) await rebaseline()\n return res\n }\n\n // An explicit --style bypasses grouping entirely and runs one session\n // across every unclaimed object, same as before grouping existed — for\n // when the auto-match misses a real candidate and a human already knows\n // where it belongs.\n if (args.styles.length) {\n const res = await runOne(args.styles[0]!, orphans)\n if (res.discarded) {\n log(`\\n Nothing was deleted. To actually remove the discarded objects:`)\n log(` pixelkiln purge\\n`)\n }\n return\n }\n\n if (!matched.size) {\n log(`\\n nothing matched a known style — nothing to triage`)\n return\n }\n\n log(`\\n ${matched.size} session(s), one style at a time:`)\n let totalDiscarded = 0\n for (const [styleId, list] of matched) {\n log(`\\n — ${styleId} (${list.length}) —`)\n const res = await runOne(styleId, list)\n totalDiscarded += res.discarded\n }\n if (totalDiscarded) {\n log(`\\n Nothing was deleted. To actually remove the discarded objects:`)\n log(` pixelkiln purge\\n`)\n }\n return\n }\n\n if (args.command === \"purge\") {\n const provider = providerFor(selectedAccountProvider!)\n const doomed: { id: string; prompt: string }[] = []\n for await (const obj of requireList(provider)()) {\n if (obj.tags.includes(\"pixelkiln:discard\")) {\n doomed.push({ id: obj.id, prompt: obj.prompt })\n }\n }\n if (!doomed.length) {\n log(` nothing tagged pixelkiln:discard — run \\`pixelkiln salvage\\` first`)\n return\n }\n log(`\\n ${doomed.length} object(s) tagged for discard:`)\n for (const d of doomed.slice(0, 20)) log(` ${d.id} ${d.prompt.slice(0, 60)}`)\n if (doomed.length > 20) log(` … and ${doomed.length - 20} more`)\n\n if (args.dryRun) {\n log(`\\n --dry-run: nothing deleted.`)\n return\n }\n log(`\\n This permanently deletes them from your ${provider.id} account.`)\n log(` Any local files already downloaded are untouched, but the objects`)\n log(` and their URLs are gone and cannot be re-downloaded.`)\n if (!(await confirm(` Delete ${doomed.length} object(s)?`, args.yes))) {\n log(` aborted`)\n return\n }\n\n let deleted = 0\n let failed = 0\n for (const d of doomed) {\n try {\n await requireDelete(provider)(d.id)\n deleted++\n } catch (err) {\n failed++\n log(` delete failed ${d.id}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n log(`\\n deleted ${deleted}${failed ? `, failed ${failed}` : \"\"}`)\n return\n }\n\n if (args.command === \"tag\") {\n let tagged = 0\n for (const [providerId, providerSpecsForRun] of specsByRecordedProvider(specs, lock)) {\n tagged += await pushTags(providerFor(providerId), providerSpecsForRun, lock, {\n onProgress: log,\n })\n }\n log(` tagged ${tagged} object(s)`)\n return\n }\n\n if (args.command === \"submit\" || args.command === \"gen\") {\n printPlan(plan)\n if (args.dryRun) {\n log(`\\n --dry-run: stopping before any spend.`)\n return\n }\n if (plan.actionable.length) {\n const budgets = budgetsForPlan(plan, args)\n const balances = new Map<string, BalanceInfo | null>()\n // Validate every ceiling and available balance before the first provider\n // can spend. A later group must never reveal that the whole run was\n // unaffordable only after an earlier group already submitted work.\n for (const group of plan.groups) {\n const groupProvider = providerFor(group.provider)\n const balance = groupProvider.balance ? await groupProvider.balance() : null\n balances.set(group.provider, balance)\n if (balance) {\n log(\n `\\n balance: ${formatCost(balance.unit, balance.remaining)} remaining ` +\n `(${group.provider})`,\n )\n if (balance.unit !== group.costUnit) {\n throw new Error(\n `Provider ${group.provider} estimate unit ${group.costUnit} does not match ` +\n `balance unit ${balance.unit}.`,\n )\n }\n if (balance.unit !== \"free\" && group.cost > balance.remaining) {\n throw new Error(\n `${group.provider} needs ${formatCost(balance.unit, group.cost)} but only ` +\n `${formatCost(balance.unit, balance.remaining)} remain.`,\n )\n }\n } else {\n log(\n `\\n ${group.provider} does not expose an account balance; ` +\n `enforcing its run budget`,\n )\n }\n const ceiling = budgets.get(group.provider)\n if (ceiling !== undefined && group.cost > ceiling) {\n throw new Error(\n `${group.provider} would spend ${formatCost(group.costUnit, group.cost)} but its ` +\n `budget is ${formatCost(group.costUnit, ceiling)}.`,\n )\n }\n }\n const spendSummary = plan.groups\n .map((group) => `${group.provider} ${formatCost(group.costUnit, group.cost)}`)\n .join(\"; \")\n const ok = await confirm(\n ` Spend ${spendSummary} on ${plan.actionable.length} asset(s)?`,\n args.yes,\n )\n if (!ok) {\n log(` aborted`)\n return\n }\n log(`\\n submitting…`)\n for (const group of plan.groups) {\n const groupProvider = providerFor(group.provider)\n const res = await submit(groupProvider, loaded, group.actionable, lock, args.lock, {\n budget: budgets.get(group.provider),\n onProgress: log,\n })\n log(\n `\\n ${group.provider}: submitted ${res.submitted}, failed ${res.failed}, ` +\n `estimated ${formatCost(res.unit, res.spent)}`,\n )\n try {\n const before = balances.get(group.provider)\n const after = before && groupProvider.balance ? await groupProvider.balance() : null\n if (!before || !after) throw new Error(\"balance reporting is unsupported\")\n const measured = measureBalanceChange(before, after)\n if (measured) {\n const movement = measured.credited\n ? `${formatCost(measured.unit, measured.credited)} credited`\n : `${formatCost(measured.unit, measured.spent)} consumed`\n log(` ${group.provider} balance change: ${movement}`)\n } else {\n log(` ${group.provider} changed balance units; no delta reported`)\n }\n } catch (err) {\n log(\n ` ${group.provider} balance recheck unavailable: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n if (res.failed) process.exitCode = 1\n }\n }\n if (args.command === \"submit\") return\n }\n\n if (args.command === \"poll\" || args.command === \"gen\") {\n log(`\\n polling…`)\n const total = { completed: 0, review: 0, failed: 0, stillRunning: 0 }\n for (const [providerId, providerSpecsForRun] of specsByRecordedProvider(specs, lock)) {\n const res = await poll(providerFor(providerId), lock, args.lock, {\n onProgress: log,\n specs: providerSpecsForRun,\n })\n total.completed += res.completed\n total.review += res.review\n total.failed += res.failed\n total.stillRunning += res.stillRunning\n }\n log(\n `\\n ${total.completed} ready · ${total.review} awaiting selection · ` +\n `${total.failed} failed`,\n )\n if (total.failed || total.stillRunning) process.exitCode = 1\n if (args.command === \"poll\") {\n printResumeActions(specs, lock)\n return\n }\n }\n\n if (args.command === \"pick\" || args.command === \"gen\") {\n const total = { selected: 0, skipped: 0 }\n for (const [providerId, providerSpecsForRun] of specsByRecordedProvider(specs, lock)) {\n const res = await runPicker(providerFor(providerId), lock, args.lock, {\n port: args.port,\n open: !args.noOpen,\n onProgress: log,\n onReady: announceReviewReady,\n keys: providerSpecsForRun.map((spec) => lockKey(spec.styleId, spec.assetId)),\n specs: providerSpecsForRun,\n })\n total.selected += res.selected\n total.skipped += res.skipped\n }\n if (total.selected === 0 && total.skipped === 0) {\n log(` nothing awaiting selection`)\n } else {\n log(`\\n selected ${total.selected}, left in review ${total.skipped}`)\n }\n if (args.command === \"gen\" && total.skipped) process.exitCode = 1\n if (args.command === \"pick\") {\n printResumeActions(specs, lock)\n return\n }\n }\n\n if (args.command === \"fetch\" || args.command === \"restore\" || args.command === \"gen\") {\n log(`\\n downloading…`)\n const total = { downloaded: 0, skipped: 0, failed: 0, tagged: 0 }\n for (const [providerId, providerSpecsForRun] of specsByRecordedProvider(specs, lock)) {\n const groupProvider = providerFor(providerId)\n const res = await fetchAssets(groupProvider, providerSpecsForRun, lock, args.lock, {\n onProgress: log,\n repair: args.command === \"restore\",\n force: args.force,\n })\n total.downloaded += res.downloaded\n total.skipped += res.skipped\n total.failed += res.failed\n if (args.tag) {\n total.tagged += await pushTags(groupProvider, providerSpecsForRun, lock, {\n onProgress: log,\n })\n }\n }\n log(\n `\\n downloaded ${total.downloaded}, skipped ${total.skipped}, failed ${total.failed}`,\n )\n if (total.failed) process.exitCode = 1\n if (args.tag) log(` tagged ${total.tagged} object(s) upstream`)\n await saveLock(args.lock, lock)\n log(` lockfile written: ${args.lock}`)\n const resumeActionCount = printResumeActions(specs, lock)\n if (args.command === \"gen\" && specs.some((spec) => spec.quality) && !total.failed) {\n const quality = (await Promise.all(\n specs.filter((spec) => spec.quality).map((spec) => inspectQualityProfile(spec, lock)),\n )).filter((item) => item !== null)\n const blocked = quality.filter((item) => item.state === \"blocked\")\n if (blocked.length) {\n log(\n `\\n ${blocked.length} quality source${blocked.length === 1 ? \" is\" : \"s are\"} not ready; ` +\n (resumeActionCount\n ? \"finish the resume steps above before refining.\"\n : \"run `pixelkiln plan` for the blocking reason before refining.\"),\n )\n } else {\n log(`\\n Raw provider output is ready. Run \\`pixelkiln refine\\` to build the configured quality output.`)\n log(` Packaging stays blocked until each refined PNG has a current human approval.`)\n }\n }\n return\n }\n\n log(HELP)\n}\n\nmain().catch((err) => {\n console.error(`\\n error: ${err instanceof Error ? err.message : String(err)}\\n`)\n process.exit(1)\n})\n","import { readFileSync, existsSync } from \"node:fs\"\nimport path from \"node:path\"\n\n/**\n * Loads `.env.local` then `.env` from a directory into `process.env`.\n *\n * Existing environment variables always win, so an explicit export or a CI\n * secret is never silently overridden by a checked-out file.\n *\n * This exists because the \"PIXELLAB_API_KEY is not set\" error told people to\n * put the key in a .env file next to the manifest — advice the code did not\n * actually implement, so following it correctly still failed.\n */\nexport function loadEnvFiles(dir: string): string[] {\n const loaded: string[] = []\n // .env.local last-writer-wins over .env, matching the Next.js convention\n // these projects already follow — so it is read first and .env cannot\n // clobber it, given the never-override rule below.\n for (const name of [\".env.local\", \".env\"]) {\n const file = path.join(dir, name)\n if (!existsSync(file)) continue\n try {\n applyEnv(readFileSync(file, \"utf8\"))\n loaded.push(file)\n } catch {\n // An unreadable env file is not worth failing the command over; the\n // missing-key error downstream is clearer than a parse trace.\n }\n }\n return loaded\n}\n\nfunction applyEnv(contents: string): void {\n for (const rawLine of contents.split(\"\\n\")) {\n const line = rawLine.trim()\n if (!line || line.startsWith(\"#\")) continue\n\n const eq = line.indexOf(\"=\")\n if (eq <= 0) continue\n\n const key = line.slice(0, eq).replace(/^export\\s+/, \"\").trim()\n if (!key || key in process.env) continue\n\n let value = line.slice(eq + 1).trim()\n // Strip one matching pair of surrounding quotes, if present.\n const quote = value[0]\n if ((quote === '\"' || quote === \"'\") && value.endsWith(quote) && value.length >= 2) {\n value = value.slice(1, -1)\n }\n process.env[key] = value\n }\n}\n","import type { Generator, ResolvedSpec, ResolvedStyleImage, RevisionMode } from \"./types.ts\"\nimport type { MediaType } from \"./media.ts\"\n\n/**\n * Human-readable unit attached to every estimate and recorded charge.\n * Built-ins use generations, USD, free, and compute units. Adapters may report\n * another non-convertible unit without pretending it is dollars.\n */\nexport type CostUnit = \"generations\" | \"usd\" | \"free\" | (string & {})\n\nexport interface CostEstimate {\n unit: CostUnit\n amount: number\n /**\n * How many candidates one call returns. This is a provider property, not a\n * universal truth — PixelLab's `1dir` returns up to 64 for a single fixed\n * price, whereas a per-image provider returns one and charges N times for N.\n * The \"generate small, pick from many\" strategy only pays off where this is\n * greater than 1 at no extra cost.\n */\n candidates: number\n}\n\n/** Runtime guard for third-party adapters before estimates influence a budget. */\nexport function validateCostEstimate(providerId: string, value: unknown): CostEstimate {\n if (!value || typeof value !== \"object\") {\n throw new Error(`Provider \"${providerId}\" returned an invalid cost estimate`)\n }\n const estimate = value as Partial<CostEstimate>\n if (typeof estimate.unit !== \"string\" || !estimate.unit.trim()) {\n throw new Error(`Provider \"${providerId}\" returned an invalid cost unit`)\n }\n if (!Number.isFinite(estimate.amount) || estimate.amount! < 0) {\n throw new Error(`Provider \"${providerId}\" returned an invalid cost amount`)\n }\n if (estimate.unit === \"free\" && estimate.amount !== 0) {\n throw new Error(`Provider \"${providerId}\" returned a nonzero amount with the free cost unit`)\n }\n if (!Number.isInteger(estimate.candidates) || estimate.candidates! < 1) {\n throw new Error(`Provider \"${providerId}\" returned an invalid candidate count`)\n }\n return estimate as CostEstimate\n}\n\nexport interface OutputSource {\n url: string\n /** Stable semantic/index role used in filenames and lockfile outputs. */\n role?: string\n /** Durable byte format. Omission preserves legacy PNG behavior. */\n mediaType?: MediaType\n}\n\nexport type ProviderInputScalar = string | number | boolean\nexport type ProviderInputValue = ProviderInputScalar | ProviderInputScalar[]\n\nexport interface PollContext {\n /** Distinguishes structural tile sets from independent tile candidates. */\n tileFeature?: string\n /** Current resolved intent, needed when output media depends on provider options. */\n spec?: ResolvedSpec\n}\n\n/** Provider-owned, JSON-serializable details needed by downstream exporters. */\nexport type ProviderMetadata = Record<string, unknown>\n\nexport interface ProviderSubmission {\n jobId: string\n /** Authoritative provider details known at submission, such as a live quote. */\n metadata?: ProviderMetadata\n}\n\nexport interface CandidateSelection {\n objectId: string\n sourceUrl: string | null\n /** Details known only after choosing an output, such as its durable asset id. */\n metadata?: ProviderMetadata\n}\n\nexport interface ProviderOptionContext {\n /** Absolute directory containing the manifest. */\n root: string\n styleId: string\n}\n\nexport interface ProviderInputContext extends ProviderOptionContext {\n assetId: string\n generator: Generator\n /** The already-resolved options for this style. */\n providerOptions: Record<string, unknown>\n}\n\nexport interface ResolvedProviderOptions {\n /** Runtime options passed to estimate, validate, and submit. */\n options: Record<string, unknown>\n /** Stable JSON value hashed instead of runtime-only data when present. */\n identity?: unknown\n}\n\nexport interface ResolvedProviderInputs {\n /** Runtime values passed to validate and submit. */\n inputs: Record<string, unknown>\n /** Stable JSON value hashed instead of runtime-only paths when present. */\n identity?: unknown\n}\n\n/** Terminal and non-terminal states a queued job can be observed in. */\nexport type JobState =\n | { status: \"processing\"; progressPercent?: number | null; etaSeconds?: number | null }\n | { status: \"review\"; candidateUrls: string[]; metadata?: ProviderMetadata }\n | {\n status: \"review-set\"\n objectId: string\n frameUrls: string[]\n sources: OutputSource[]\n fps: number\n metadata?: ProviderMetadata\n }\n | {\n status: \"ready\"\n objectId: string\n /** Kept for compatibility with single-output provider implementations. */\n sourceUrl: string | null\n /** Present for structural multi-output results. */\n sources?: OutputSource[]\n /** Preserved under the provider's namespace in the lockfile. */\n metadata?: ProviderMetadata\n }\n | { status: \"failed\"; error: string }\n\n/** A previously generated asset as the provider reports it. */\nexport interface RemoteAsset {\n id: string\n prompt: string\n width: number\n height: number\n createdAt: string\n previewUrl: string | null\n tags: string[]\n status: string\n}\n\nexport interface BalanceInfo {\n unit: CostUnit\n remaining: number\n total?: number\n plan?: string\n}\n\nexport interface BalanceChange {\n unit: CostUnit\n before: number\n after: number\n /** Provider-reported quota/currency consumed between the two readings. */\n spent: number\n /** Quota/currency added between readings, e.g. a refill during the run. */\n credited: number\n}\n\n/** Compare two provider readings without ever combining incompatible units. */\nexport function measureBalanceChange(\n before: BalanceInfo,\n after: BalanceInfo,\n): BalanceChange | null {\n if (\n before.unit !== after.unit ||\n !Number.isFinite(before.remaining) ||\n !Number.isFinite(after.remaining)\n ) return null\n const delta = before.remaining - after.remaining\n return {\n unit: before.unit,\n before: before.remaining,\n after: after.remaining,\n spent: Math.max(0, delta),\n credited: Math.max(0, -delta),\n }\n}\n\n/**\n * Submission constraints a backend enforces upstream, in its own units —\n * `submit` has no business knowing these numbers itself.\n */\nexport interface RateLimit {\n /** Minimum time between successive submissions, global across the account. */\n spacingMs: number\n /** Background jobs allowed in flight at once. */\n maxInFlight: number\n}\n\n/**\n * Used when a provider doesn't declare `rateLimit()` — conservative enough\n * not to be a real constraint for a provider that has none of its own, and\n * overridable per run via `submit`'s own options regardless.\n */\nexport const DEFAULT_RATE_LIMIT: RateLimit = { spacingMs: 2500, maxInFlight: 8 }\n\n/**\n * A backend that turns a resolved spec into durable image or animation bytes.\n *\n * Everything above this interface — the manifest, the lockfile, plan diffing,\n * salvage, the contact sheets — is provider-agnostic. Everything that knows a\n * URL shape or an auth header lives below it.\n *\n * The optional members are genuinely optional capabilities rather than\n * convenience: a provider with no queryable asset list cannot support `adopt`\n * or `salvage`, and the CLI reports that rather than failing obscurely.\n */\nexport interface Provider {\n readonly id: string\n\n /**\n * Resolve provider-owned local files before spec hashing. This must remain\n * offline and return JSON-serializable data. It lets adapters hash file\n * content rather than a machine-specific path.\n */\n resolveOptions?(\n options: Record<string, unknown>,\n context: ProviderOptionContext,\n ): Promise<ResolvedProviderOptions>\n\n /**\n * Resolve adapter-owned per-asset values before spec hashing. This is where\n * local control images become content hashes rather than machine paths.\n */\n resolveInputs?(\n inputs: Record<string, ProviderInputValue>,\n context: ProviderInputContext,\n ): Promise<ResolvedProviderInputs>\n\n /** False for a generator this backend cannot express (e.g. non-square). */\n supports(generator: Generator): boolean\n\n /** True only when the adapter can bind and submit this controlled edit mode. */\n supportsRevision?(mode: RevisionMode): boolean\n\n /** Never performs I/O — `plan` must stay free and offline. */\n estimate(spec: ResolvedSpec): CostEstimate\n\n /** Provider-specific, offline validation after references resolve. */\n validate?(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): void\n\n /** This backend's own submission constraints. Falls back to\n * `DEFAULT_RATE_LIMIT` when absent — see that constant's doc. */\n rateLimit?(): RateLimit\n\n submit(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): Promise<ProviderSubmission>\n\n poll(jobId: string, generator: Generator, context?: PollContext): Promise<JobState>\n\n /**\n * Promote one candidate from a review-status job to a standalone asset.\n * Only meaningful where `estimate().candidates > 1`.\n *\n * `generator` is passed because \"promote\" is not universal: PixelLab's\n * frame-based generators create a new account object, while a tiles\n * variation is already a finished image and there is nothing to promote.\n * A provider that treats every candidate alike can ignore it.\n */\n selectCandidate?(\n jobId: string,\n index: number,\n commonTag?: string,\n generator?: Generator,\n ): Promise<CandidateSelection>\n\n /** Storage URLs are usually public; implementations should not send auth. */\n download(url: string): Promise<Buffer>\n\n /** Query an authoritative account balance when the service exposes one. */\n balance?(): Promise<BalanceInfo>\n\n /** Read-only connectivity probe for providers without a balance endpoint. */\n checkConnection?(): Promise<void>\n\n /** Free-form labels on the remote asset. Absent if unsupported. */\n setTags?(objectId: string, tags: string[]): Promise<void>\n\n /** Walk every asset on the account. Required by `adopt` and `salvage`. */\n list?(): AsyncGenerator<RemoteAsset>\n\n /** Irreversible. Only reached via `purge`, behind explicit confirmation. */\n delete?(assetId: string): Promise<void>\n}\n\nexport class UnsupportedCapabilityError extends Error {\n constructor(providerId: string, capability: string) {\n super(\n `Provider \"${providerId}\" does not support ${capability}. ` +\n `That command is unavailable with this backend.`,\n )\n this.name = \"UnsupportedCapabilityError\"\n }\n}\n\n/** Narrowing helpers so call sites fail with a clear message, not `undefined is not a function`. */\nexport function requireList(provider: Provider): NonNullable<Provider[\"list\"]> {\n if (!provider.list) throw new UnsupportedCapabilityError(provider.id, \"listing remote assets\")\n return provider.list.bind(provider)\n}\n\nexport function requireDelete(provider: Provider): NonNullable<Provider[\"delete\"]> {\n if (!provider.delete) throw new UnsupportedCapabilityError(provider.id, \"deleting remote assets\")\n return provider.delete.bind(provider)\n}\n\nexport function requireSelectCandidate(\n provider: Provider,\n): NonNullable<Provider[\"selectCandidate\"]> {\n if (!provider.selectCandidate) {\n throw new UnsupportedCapabilityError(provider.id, \"candidate selection\")\n }\n return provider.selectCandidate.bind(provider)\n}\n\nexport function requireBalance(provider: Provider): NonNullable<Provider[\"balance\"]> {\n if (!provider.balance) throw new UnsupportedCapabilityError(provider.id, \"account balance\")\n return provider.balance.bind(provider)\n}\n\nexport function formatCost(unit: CostUnit, amount: number): string {\n if (unit === \"free\") return \"free\"\n if (unit === \"usd\") return `$${amount.toFixed(2)}`\n if (unit === \"generations\") return `${amount} generation${amount === 1 ? \"\" : \"s\"}`\n return `${amount} ${unit}`\n}\n","import { randomUUID } from \"node:crypto\"\nimport { readFile } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { sha256 } from \"../hash.ts\"\nimport { MediaType } from \"../media.ts\"\nimport type {\n CostEstimate,\n JobState,\n PollContext,\n Provider,\n ProviderInputContext,\n ProviderInputValue,\n ProviderOptionContext,\n ProviderSubmission,\n RateLimit,\n ResolvedProviderInputs,\n ResolvedProviderOptions,\n} from \"../provider.ts\"\nimport type { Generator, ResolvedSpec, ResolvedStyleImage, RevisionMode } from \"../types.ts\"\n\nconst DEFAULT_BASE_URL = \"http://127.0.0.1:8188\"\n\ntype JsonObject = Record<string, unknown>\ntype ComfyWorkflow = Record<string, { class_type: string; inputs: JsonObject; [key: string]: unknown }>\n\nexport interface ComfyUIBinding {\n nodeId: string\n input: string\n}\n\nexport interface ComfyUIBindings {\n [name: string]: ComfyUIBinding | undefined\n prompt: ComfyUIBinding\n width?: ComfyUIBinding\n height?: ComfyUIBinding\n batchSize?: ComfyUIBinding\n seed?: ComfyUIBinding\n /** LoadImage-compatible input populated from a hashed revision parent. */\n sourceImage?: ComfyUIBinding\n /** LoadImage-compatible input populated from an inpaint mask. */\n maskImage?: ComfyUIBinding\n /** Sampler denoise/edit-strength input. */\n strength?: ComfyUIBinding\n}\n\nexport interface ComfyUIImageInput {\n kind: \"image\"\n /** Absolute local path used only at submission time. */\n path: string\n sha256: string\n format: \"png\" | \"jpeg\"\n}\n\nexport interface ComfyUIFramesOptions {\n /** Project-defined binding whose asset value is an ordered scalar array. */\n vary: string\n /** Optional deterministic seed increment between frames. Defaults to 0. */\n seedStep?: number\n}\n\n/** Options stored under `providerOptions.comfyui` in a manifest style. */\nexport interface ComfyUIOptions {\n /** ComfyUI API-format workflow JSON, relative to the manifest. */\n workflowFile: string\n /** Node whose history output contains the final `images` array. */\n outputNodeId: string\n /** Expected final images from the output node. */\n numImages?: number\n /** Ordered still-frame generation using one varying custom binding. */\n frames?: ComfyUIFramesOptions\n /** Exact workflow inputs PixelKiln is allowed to replace. */\n bindings: ComfyUIBindings\n}\n\ninterface ResolvedComfyUIOptions extends ComfyUIOptions {\n numImages: number\n frames?: { vary: string; seedStep: number }\n workflow: ComfyWorkflow\n workflowSha256: string\n}\n\ninterface ComfyImage {\n filename: string\n subfolder: string\n type: \"output\"\n}\n\ninterface FrameSetJob {\n outputNodeId: string\n promptIds: string[]\n}\n\nconst BUILTIN_BINDINGS = new Set([\n \"prompt\", \"width\", \"height\", \"batchSize\", \"seed\", \"sourceImage\", \"maskImage\", \"strength\",\n])\n\nclass ComfyUIClient {\n readonly baseUrl: string\n\n constructor(\n baseUrl = process.env.COMFYUI_BASE_URL ?? DEFAULT_BASE_URL,\n private readonly request: typeof fetch = fetch,\n ) {\n this.baseUrl = normalizeBaseUrl(baseUrl)\n }\n\n async checkConnection(): Promise<void> {\n const value = await this.json(\"system_stats\")\n if (!isObject(value)) throw new Error(\"ComfyUI returned invalid system stats\")\n }\n\n async submit(workflow: ComfyWorkflow): Promise<string> {\n const value = await this.json(\"prompt\", {\n method: \"POST\",\n body: JSON.stringify({ prompt: workflow, client_id: randomUUID() }),\n })\n if (!isObject(value)) throw new Error(\"ComfyUI returned an invalid queue response\")\n const promptId = value.prompt_id\n if (typeof promptId !== \"string\" || !promptId) {\n const nodes = isObject(value.node_errors) ? Object.keys(value.node_errors) : []\n throw new Error(\n \"ComfyUI did not return a prompt id\" +\n (nodes.length ? `; invalid workflow node(s): ${nodes.slice(0, 8).join(\", \")}` : \"\"),\n )\n }\n return promptId\n }\n\n async uploadImage(\n bytes: Buffer,\n sha256: string,\n format: \"png\" | \"jpeg\",\n ): Promise<string> {\n const extension = format === \"jpeg\" ? \"jpg\" : \"png\"\n const form = new FormData()\n form.append(\n \"image\",\n new Blob([new Uint8Array(bytes)], { type: format === \"jpeg\" ? \"image/jpeg\" : \"image/png\" }),\n `${sha256}.${extension}`,\n )\n form.append(\"type\", \"input\")\n form.append(\"subfolder\", \"pixelkiln\")\n form.append(\"overwrite\", \"true\")\n const url = this.endpoint(\"upload/image\")\n const response = await this.request(url, { method: \"POST\", body: form })\n const text = await response.text()\n let value: unknown = null\n try {\n value = text ? JSON.parse(text) : null\n } catch {\n value = null\n }\n if (!response.ok) {\n throw new Error(\n `ComfyUI image upload failed (${response.status})` +\n (apiError(value) ? `: ${apiError(value)}` : \"\"),\n )\n }\n if (!isObject(value) || typeof value.name !== \"string\" || !value.name) {\n throw new Error(\"ComfyUI image upload returned an invalid response\")\n }\n const subfolder = typeof value.subfolder === \"string\" ? value.subfolder : \"\"\n return subfolder ? `${subfolder.replace(/\\/+$/, \"\")}/${value.name}` : value.name\n }\n\n async history(promptId: string): Promise<unknown> {\n return this.json(`history/${encodeURIComponent(promptId)}`)\n }\n\n viewUrl(image: ComfyImage): string {\n const url = this.endpoint(\"view\")\n url.searchParams.set(\"filename\", image.filename)\n url.searchParams.set(\"subfolder\", image.subfolder)\n url.searchParams.set(\"type\", image.type)\n return url.toString()\n }\n\n async download(source: string): Promise<Buffer> {\n let target = source\n if (source.startsWith(\"comfyui://\")) target = this.viewUrl(parseSource(source))\n const response = await this.request(target)\n if (!response.ok) throw new Error(`ComfyUI download failed (${response.status})`)\n return Buffer.from(await response.arrayBuffer())\n }\n\n private endpoint(route: string): URL {\n return new URL(route.replace(/^\\/+/, \"\"), `${this.baseUrl}/`)\n }\n\n private async json(route: string, init: RequestInit = {}): Promise<unknown> {\n const url = this.endpoint(route)\n const response = await this.request(url, {\n ...init,\n headers: {\n ...(init.body ? { \"Content-Type\": \"application/json\" } : {}),\n ...init.headers,\n },\n })\n const text = await response.text()\n let value: unknown = null\n try {\n value = text ? JSON.parse(text) : null\n } catch {\n if (response.ok) throw new Error(`ComfyUI returned invalid JSON from ${url.pathname}`)\n value = null\n }\n if (!response.ok) {\n const detail = apiError(value)\n throw new Error(\n `ComfyUI request failed (${response.status}) at ${url.pathname}` +\n (detail ? `: ${detail}` : \"\"),\n )\n }\n return value\n }\n}\n\n/** Self-hosted ComfyUI workflow adapter. */\nexport class ComfyUIProvider implements Provider {\n readonly id = \"comfyui\"\n\n constructor(private readonly client: ComfyUIClient = new ComfyUIClient()) {}\n\n static fromEnv(): ComfyUIProvider {\n return new ComfyUIProvider()\n }\n\n static forOffline(): ComfyUIProvider {\n return new ComfyUIProvider(new ComfyUIClient(DEFAULT_BASE_URL))\n }\n\n static forDownloads(): ComfyUIProvider {\n return new ComfyUIProvider()\n }\n\n async resolveOptions(\n value: Record<string, unknown>,\n context: ProviderOptionContext,\n ): Promise<ResolvedProviderOptions> {\n const options = parseOptions(value)\n const workflowPath = path.resolve(context.root, options.workflowFile)\n let raw: string\n try {\n raw = await readFile(workflowPath, \"utf8\")\n } catch (err) {\n throw new Error(\n `ComfyUI workflow for style \"${context.styleId}\" could not be read at ${workflowPath}: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch {\n throw new Error(`ComfyUI workflow for style \"${context.styleId}\" is not valid JSON: ${workflowPath}`)\n }\n const workflow = parseWorkflow(parsed, workflowPath)\n validateWorkflowBindings(workflow, options)\n const workflowSha256 = sha256(JSON.stringify(canonical(workflow)))\n const resolved: ResolvedComfyUIOptions = { ...options, workflow, workflowSha256 }\n return {\n options: resolved as unknown as Record<string, unknown>,\n identity: {\n outputNodeId: options.outputNodeId,\n numImages: options.numImages,\n ...(options.frames ? { frames: options.frames } : {}),\n bindings: options.bindings,\n workflowSha256,\n },\n }\n }\n\n async resolveInputs(\n value: Record<string, ProviderInputValue>,\n context: ProviderInputContext,\n ): Promise<ResolvedProviderInputs> {\n const options = parseOptions(context.providerOptions)\n if (!options.workflow || !options.workflowSha256) {\n throw new Error(\"ComfyUI provider inputs require resolved workflow options\")\n }\n const inputs: Record<string, unknown> = {}\n const identity: Record<string, unknown> = {}\n for (const [name, input] of Object.entries(value)) {\n if (BUILTIN_BINDINGS.has(name)) {\n throw new Error(\n `ComfyUI providerInputs.${name} is reserved; use PixelKiln's built-in ${name} field`,\n )\n }\n const binding = Object.hasOwn(options.bindings, name) ? options.bindings[name] : undefined\n if (!binding) {\n throw new Error(\n `ComfyUI providerInputs.${name} has no matching bindings.${name} target`,\n )\n }\n const resolveValue = async (\n item: string | number | boolean,\n index?: number,\n ): Promise<{ runtime: unknown; stable: unknown }> => {\n const label = `providerInputs.${name}${index == null ? \"\" : `[${index}]`}`\n if (isImageBinding(options.workflow!, binding)) {\n if (typeof item !== \"string\") {\n throw new Error(`ComfyUI ${label} must be a manifest-relative PNG or JPEG path`)\n }\n const file = path.resolve(context.root, item)\n let bytes: Buffer\n try {\n bytes = await readFile(file)\n } catch (error) {\n throw new Error(\n `ComfyUI ${label} could not be read at ${file}: ` +\n `${error instanceof Error ? error.message : String(error)}`,\n )\n }\n const format = inputImageFormat(bytes)\n if (!format) throw new Error(`ComfyUI ${label} is not a PNG or JPEG: ${file}`)\n const hash = sha256(bytes)\n return {\n runtime: { kind: \"image\", path: file, sha256: hash, format } satisfies ComfyUIImageInput,\n stable: { kind: \"image\", sha256: hash, format },\n }\n }\n\n const current = options.workflow![binding.nodeId]!.inputs[binding.input]\n if (typeof current !== \"string\" && typeof current !== \"number\" && typeof current !== \"boolean\") {\n throw new Error(\n `ComfyUI ${label} cannot replace non-scalar ${binding.nodeId}.${binding.input}`,\n )\n }\n if (typeof current !== typeof item) {\n throw new Error(\n `ComfyUI ${label} must be ${typeof current} to match ${binding.nodeId}.${binding.input}`,\n )\n }\n return { runtime: item, stable: item }\n }\n\n if (Array.isArray(input)) {\n if (!options.frames || name !== options.frames.vary) {\n throw new Error(\n `ComfyUI providerInputs.${name} is an array but frames.vary is ` +\n `${options.frames ? `\"${options.frames.vary}\"` : \"not configured\"}`,\n )\n }\n const resolved = await Promise.all(input.map((item, index) => resolveValue(item, index)))\n inputs[name] = resolved.map((item) => item.runtime)\n identity[name] = resolved.map((item) => item.stable)\n } else {\n const resolved = await resolveValue(input)\n inputs[name] = resolved.runtime\n identity[name] = resolved.stable\n }\n }\n return { inputs, identity }\n }\n\n supports(generator: Generator): boolean {\n return generator === \"map\" || generator === \"frames\"\n }\n\n supportsRevision(_mode: RevisionMode): boolean {\n return true\n }\n\n estimate(spec: ResolvedSpec): CostEstimate {\n return {\n unit: \"free\",\n amount: 0,\n candidates: spec.generator === \"frames\" ? 1 : resolvedOptions(spec).numImages,\n }\n }\n\n validate(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): void {\n const options = resolvedOptions(spec)\n // A committed source can be a revision parent in the same style, but it is\n // never submitted. Revision-only workflows therefore do not need the\n // text-to-image bindings that this placeholder spec would otherwise imply.\n if (spec.source && !spec.revision) {\n if (spec.generator === \"frames\") {\n throw new Error(\"ComfyUI frame sets require generated provider outputs, not asset.source\")\n }\n return\n }\n if (spec.width < 16 || spec.height < 16 || spec.width > 4096 || spec.height > 4096) {\n throw new Error(\"ComfyUI output dimensions must be between 16 and 4096 pixels\")\n }\n if (styleImages.length) {\n throw new Error(\"ComfyUI styleImages are not supported yet; keep references inside the workflow\")\n }\n if (spec.palette.length) {\n throw new Error(\"ComfyUI does not map PixelKiln palette values yet; encode palette control in the workflow\")\n }\n if (spec.seed != null && !options.bindings.seed) {\n throw new Error(\"ComfyUI requires bindings.seed when the style declares a seed\")\n }\n if (!options.bindings.width !== !options.bindings.height) {\n throw new Error(\"ComfyUI width and height bindings must be declared together\")\n }\n if (!spec.revision && (!options.bindings.width || !options.bindings.height)) {\n throw new Error(\"ComfyUI text-to-image generation requires width and height bindings\")\n }\n if (options.numImages > 1 && !options.bindings.batchSize) {\n throw new Error(\"ComfyUI numImages greater than 1 requires bindings.batchSize\")\n }\n if (spec.generator === \"frames\") {\n if (!options.frames) throw new Error(\"ComfyUI frames generation requires providerOptions.comfyui.frames\")\n if (options.numImages !== 1) throw new Error(\"ComfyUI frames generation requires numImages: 1\")\n if (spec.revision) throw new Error(\"ComfyUI frame sets do not support asset revisions yet\")\n const values = spec.providerInputs?.[options.frames.vary]\n if (!Array.isArray(values) || values.length < 2 || values.length > 64) {\n throw new Error(\n `ComfyUI frames.vary \"${options.frames.vary}\" requires a providerInputs array of 2–64 values`,\n )\n }\n if (options.frames.seedStep !== 0 && (spec.seed == null || !options.bindings.seed)) {\n throw new Error(\"ComfyUI frames.seedStep requires a style seed and bindings.seed\")\n }\n if (\n spec.seed != null &&\n !Number.isSafeInteger(spec.seed + (values.length - 1) * options.frames.seedStep)\n ) {\n throw new Error(\"ComfyUI frame seed schedule exceeds JavaScript's safe integer range\")\n }\n } else if (options.frames) {\n throw new Error(\"ComfyUI providerOptions.frames requires generator: frames\")\n }\n if (spec.revision) {\n if (!options.bindings.sourceImage) {\n throw new Error(\"ComfyUI revisions require bindings.sourceImage\")\n }\n if (spec.revision.mode === \"inpaint\" && !options.bindings.maskImage) {\n throw new Error(\"ComfyUI inpaint revisions require bindings.maskImage\")\n }\n if (spec.revision.strength != null && !options.bindings.strength) {\n throw new Error(\"ComfyUI revision strength requires bindings.strength\")\n }\n if (\n (!options.bindings.width || !options.bindings.height) &&\n spec.revision.sourceWidth != null &&\n spec.revision.sourceHeight != null &&\n (spec.width !== spec.revision.sourceWidth || spec.height !== spec.revision.sourceHeight)\n ) {\n throw new Error(\n \"ComfyUI revisions without width/height bindings must keep the source dimensions\",\n )\n }\n }\n validateWorkflowBindings(options.workflow, options)\n }\n\n rateLimit(): RateLimit {\n return { spacingMs: 0, maxInFlight: 1 }\n }\n\n async submit(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): Promise<ProviderSubmission> {\n this.validate(spec, styleImages)\n const options = resolvedOptions(spec)\n const uploadedImages = new Map<string, string>()\n const bindInput = async (\n workflow: ComfyWorkflow,\n name: string,\n input: unknown,\n ): Promise<void> => {\n const binding = Object.hasOwn(options.bindings, name) ? options.bindings[name] : undefined\n if (!binding) throw new Error(`ComfyUI provider input \"${name}\" has no binding`)\n if (!isComfyImageInput(input)) {\n setBinding(workflow, binding, input)\n return\n }\n const bytes = await readFile(input.path)\n if (sha256(bytes) !== input.sha256) {\n throw new Error(`ComfyUI provider input \"${name}\" changed before upload`)\n }\n let uploaded = uploadedImages.get(input.sha256)\n if (!uploaded) {\n uploaded = await this.client.uploadImage(bytes, input.sha256, input.format)\n uploadedImages.set(input.sha256, uploaded)\n }\n setBinding(workflow, binding, uploaded)\n }\n const buildWorkflow = async (frameIndex?: number): Promise<ComfyWorkflow> => {\n const workflow = structuredClone(options.workflow)\n setBinding(workflow, options.bindings.prompt, spec.prompt)\n if (options.bindings.width) setBinding(workflow, options.bindings.width, spec.width)\n if (options.bindings.height) setBinding(workflow, options.bindings.height, spec.height)\n if (options.bindings.batchSize) setBinding(workflow, options.bindings.batchSize, options.numImages)\n if (spec.seed != null && options.bindings.seed) {\n const seed = frameIndex == null ? spec.seed : spec.seed + frameIndex * (options.frames?.seedStep ?? 0)\n setBinding(workflow, options.bindings.seed, seed)\n }\n for (const [name, input] of Object.entries(spec.providerInputs ?? {})) {\n const selected = Array.isArray(input)\n ? (frameIndex == null ? input : input[frameIndex])\n : input\n await bindInput(workflow, name, selected)\n }\n return workflow\n }\n\n const inputs = providerInputProvenance(spec.providerInputs)\n if (spec.generator === \"frames\") {\n const frames = options.frames!\n const values = spec.providerInputs![frames.vary] as unknown[]\n const promptIds: string[] = []\n for (let index = 0; index < values.length; index++) {\n promptIds.push(await this.client.submit(await buildWorkflow(index)))\n }\n return {\n jobId: encodeFrameSetJob({ promptIds, outputNodeId: options.outputNodeId }),\n metadata: {\n inputs,\n frameSet: {\n count: values.length,\n vary: frames.vary,\n seedStep: frames.seedStep,\n fps: spec.quality?.fps ?? 12,\n promptIds,\n },\n },\n }\n }\n\n const workflow = await buildWorkflow()\n if (spec.revision) {\n if (!spec.revision.sourceSha256 || !spec.revision.sourceFormat) {\n throw new Error(\"ComfyUI revision source is not ready\")\n }\n const sourceBytes = await readFile(spec.revision.sourceFile)\n if (sha256(sourceBytes) !== spec.revision.sourceSha256) {\n throw new Error(\"ComfyUI revision source changed before upload\")\n }\n const uploadedSource = await this.client.uploadImage(\n sourceBytes,\n spec.revision.sourceSha256,\n spec.revision.sourceFormat,\n )\n setBinding(workflow, options.bindings.sourceImage!, uploadedSource)\n\n if (spec.revision.maskFile) {\n if (!spec.revision.maskSha256 || !spec.revision.maskFormat) {\n throw new Error(\"ComfyUI revision mask is not ready\")\n }\n const maskBytes = await readFile(spec.revision.maskFile)\n if (sha256(maskBytes) !== spec.revision.maskSha256) {\n throw new Error(\"ComfyUI revision mask changed before upload\")\n }\n const uploadedMask = await this.client.uploadImage(\n maskBytes,\n spec.revision.maskSha256,\n spec.revision.maskFormat,\n )\n setBinding(workflow, options.bindings.maskImage!, uploadedMask)\n }\n if (spec.revision.strength != null) {\n setBinding(workflow, options.bindings.strength!, spec.revision.strength)\n }\n }\n const promptId = await this.client.submit(workflow)\n const metadata = {\n ...(Object.keys(inputs).length ? { inputs } : {}),\n ...(spec.revision\n ? {\n revision: {\n mode: spec.revision.mode,\n sourceAssetId: spec.revision.sourceAssetId,\n sourceSha256: spec.revision.sourceSha256,\n ...(spec.revision.maskSha256 ? { maskSha256: spec.revision.maskSha256 } : {}),\n },\n }\n : {}),\n }\n return {\n jobId: encodeJob(promptId, options.outputNodeId),\n ...(Object.keys(metadata).length ? { metadata } : {}),\n }\n }\n\n async poll(jobId: string, generator: Generator, context?: PollContext): Promise<JobState> {\n if (generator === \"frames\") {\n const frameJob = decodeFrameSetJob(jobId)\n const images: ComfyImage[] = []\n for (let index = 0; index < frameJob.promptIds.length; index++) {\n const promptId = frameJob.promptIds[index]!\n const history = await this.client.history(promptId)\n const entry = historyEntry(history, promptId)\n if (!entry) return { status: \"processing\" }\n const status = isObject(entry.status) ? entry.status : {}\n if (status.status_str === \"error\") {\n return { status: \"failed\", error: `frame ${index}: ${historyError(status)}` }\n }\n if (status.completed === false) return { status: \"processing\" }\n const output = outputImages(entry, frameJob.outputNodeId)\n if (output instanceof Error) {\n return { status: \"failed\", error: `frame ${index}: ${output.message}` }\n }\n if (output.length !== 1) {\n return {\n status: \"failed\",\n error: `frame ${index}: ComfyUI returned ${output.length} images, expected 1`,\n }\n }\n images.push(output[0]!)\n }\n const fps = context?.spec?.quality?.fps ?? 12\n const sources = images.map((image, index) => ({\n url: sourceRef(image),\n role: frameRole(index),\n mediaType: MediaType.PNG,\n }))\n return {\n status: \"review-set\",\n objectId: jobId,\n frameUrls: images.map((image) => this.client.viewUrl(image)),\n sources,\n fps,\n metadata: context?.spec\n ? comfyFrameMetadata(context.spec, frameJob, images, fps)\n : { frameSet: { count: images.length, fps, promptIds: frameJob.promptIds } },\n }\n }\n const { promptId, outputNodeId } = decodeJob(jobId)\n const history = await this.client.history(promptId)\n const entry = historyEntry(history, promptId)\n if (!entry) return { status: \"processing\" }\n\n const status = isObject(entry.status) ? entry.status : {}\n const statusText = typeof status.status_str === \"string\" ? status.status_str : \"\"\n if (statusText === \"error\") {\n return { status: \"failed\", error: historyError(status) }\n }\n if (status.completed === false) return { status: \"processing\" }\n\n const images = outputImages(entry, outputNodeId)\n if (images instanceof Error) return { status: \"failed\", error: images.message }\n const expected = context?.spec ? resolvedOptions(context.spec).numImages : null\n if (expected != null && images.length !== expected) {\n return {\n status: \"failed\",\n error: `ComfyUI output node \"${outputNodeId}\" returned ${images.length} image(s), expected ${expected}`,\n }\n }\n const metadata = context?.spec ? comfyMetadata(context.spec, promptId, outputNodeId, images) : {\n promptId,\n outputNodeId,\n outputCount: images.length,\n }\n if (images.length > 1) {\n return {\n status: \"review\",\n candidateUrls: images.map((image) => this.client.viewUrl(image)),\n metadata,\n }\n }\n const sourceUrl = sourceRef(images[0]!)\n return {\n status: \"ready\",\n objectId: `${promptId}#${outputNodeId}#0`,\n sourceUrl,\n sources: [{ url: sourceUrl, mediaType: MediaType.PNG }],\n metadata,\n }\n }\n\n async selectCandidate(\n jobId: string,\n index: number,\n ): Promise<{ objectId: string; sourceUrl: string | null }> {\n const { promptId, outputNodeId } = decodeJob(jobId)\n const history = await this.client.history(promptId)\n const entry = historyEntry(history, promptId)\n if (!entry) throw new Error(`ComfyUI prompt ${promptId} is not complete`)\n const images = outputImages(entry, outputNodeId)\n if (images instanceof Error) throw images\n const image = images[index]\n if (!image) throw new Error(`ComfyUI prompt ${promptId} has no candidate at index ${index}`)\n return {\n objectId: `${promptId}#${outputNodeId}#${index}`,\n sourceUrl: sourceRef(image),\n }\n }\n\n async download(url: string): Promise<Buffer> {\n return this.client.download(url)\n }\n\n async checkConnection(): Promise<void> {\n await this.client.checkConnection()\n }\n}\n\nfunction parseOptions(value: Record<string, unknown>): ResolvedComfyUIOptions {\n const allowed = new Set([\n \"workflowFile\", \"outputNodeId\", \"numImages\", \"frames\", \"bindings\", \"workflow\", \"workflowSha256\",\n ])\n const extra = Object.keys(value).filter((key) => !allowed.has(key))\n if (extra.length) throw new Error(`Unknown ComfyUI option(s): ${extra.join(\", \")}`)\n const workflowFile = requiredString(value.workflowFile, \"workflowFile\")\n const outputNodeId = requiredString(value.outputNodeId, \"outputNodeId\")\n const numImages = value.numImages ?? 1\n if (!Number.isInteger(numImages) || Number(numImages) < 1 || Number(numImages) > 16) {\n throw new Error(\"ComfyUI numImages must be a whole number from 1 to 16\")\n }\n if (!isObject(value.bindings)) throw new Error(\"ComfyUI bindings must be an object\")\n const bindings = Object.fromEntries(\n Object.entries(value.bindings).map(([name, binding]) => [name, parseBinding(binding, name)]),\n ) as unknown as ComfyUIBindings\n if (!bindings.prompt) throw new Error(\"ComfyUI bindings.prompt must be an object\")\n const frames = value.frames == null ? undefined : parseFrames(value.frames)\n if (frames) {\n if (BUILTIN_BINDINGS.has(frames.vary)) {\n throw new Error(`ComfyUI frames.vary must name a custom binding, not \"${frames.vary}\"`)\n }\n if (!Object.hasOwn(bindings, frames.vary)) {\n throw new Error(`ComfyUI frames.vary \"${frames.vary}\" has no matching binding`)\n }\n }\n const workflow = value.workflow == null ? undefined : parseWorkflow(value.workflow, workflowFile)\n const workflowSha256 = value.workflowSha256 == null\n ? undefined\n : requiredString(value.workflowSha256, \"workflowSha256\")\n return {\n workflowFile,\n outputNodeId,\n numImages: Number(numImages),\n bindings,\n ...(frames ? { frames } : {}),\n ...(workflow ? { workflow } : {}),\n ...(workflowSha256 ? { workflowSha256 } : {}),\n } as ResolvedComfyUIOptions\n}\n\nfunction parseFrames(value: unknown): { vary: string; seedStep: number } {\n if (!isObject(value)) throw new Error(\"ComfyUI frames must be an object\")\n const extra = Object.keys(value).filter((key) => key !== \"vary\" && key !== \"seedStep\")\n if (extra.length) throw new Error(`Unknown ComfyUI frames field(s): ${extra.join(\", \")}`)\n const vary = requiredString(value.vary, \"frames.vary\")\n const seedStep = value.seedStep ?? 0\n if (!Number.isSafeInteger(seedStep) || Math.abs(Number(seedStep)) > 1_000_000) {\n throw new Error(\"ComfyUI frames.seedStep must be a safe integer from -1000000 to 1000000\")\n }\n return { vary, seedStep: Number(seedStep) }\n}\n\nfunction resolvedOptions(spec: ResolvedSpec): ResolvedComfyUIOptions {\n const options = parseOptions(spec.providerOptions)\n if (!options.workflow || !options.workflowSha256) {\n throw new Error(\"ComfyUI workflow options were not resolved from workflowFile\")\n }\n return options\n}\n\nfunction parseBinding(value: unknown, name: string): ComfyUIBinding {\n if (!isObject(value)) throw new Error(`ComfyUI bindings.${name} must be an object`)\n const extra = Object.keys(value).filter((key) => key !== \"nodeId\" && key !== \"input\")\n if (extra.length) throw new Error(`Unknown ComfyUI bindings.${name} field(s): ${extra.join(\", \")}`)\n return {\n nodeId: requiredString(value.nodeId, `bindings.${name}.nodeId`),\n input: requiredString(value.input, `bindings.${name}.input`),\n }\n}\n\nfunction parseWorkflow(value: unknown, label: string): ComfyWorkflow {\n if (!isObject(value) || !Object.keys(value).length) {\n throw new Error(`ComfyUI workflow is not a non-empty API-format object: ${label}`)\n }\n for (const [nodeId, node] of Object.entries(value)) {\n if (!isObject(node) || typeof node.class_type !== \"string\" || !isObject(node.inputs)) {\n throw new Error(`ComfyUI workflow node \"${nodeId}\" must contain class_type and inputs`)\n }\n }\n return value as ComfyWorkflow\n}\n\nfunction validateWorkflowBindings(workflow: ComfyWorkflow, options: ComfyUIOptions): void {\n const targets = new Map<string, string>()\n for (const [name, binding] of Object.entries(options.bindings)) {\n if (!binding) continue\n const node = workflow[binding.nodeId]\n if (!node) throw new Error(`ComfyUI ${name} binding refers to missing node \"${binding.nodeId}\"`)\n if (!Object.hasOwn(node.inputs, binding.input)) {\n throw new Error(\n `ComfyUI ${name} binding refers to missing input \"${binding.input}\" on node \"${binding.nodeId}\"`,\n )\n }\n const target = `${binding.nodeId}.${binding.input}`\n const prior = targets.get(target)\n if (prior) {\n throw new Error(`ComfyUI bindings.${name} and bindings.${prior} target the same input ${target}`)\n }\n targets.set(target, name)\n }\n if (!workflow[options.outputNodeId]) {\n throw new Error(`ComfyUI outputNodeId refers to missing node \"${options.outputNodeId}\"`)\n }\n}\n\nfunction setBinding(workflow: ComfyWorkflow, binding: ComfyUIBinding, value: unknown): void {\n const node = workflow[binding.nodeId]\n if (!node || !Object.hasOwn(node.inputs, binding.input)) {\n throw new Error(`ComfyUI binding ${binding.nodeId}.${binding.input} is unavailable`)\n }\n node.inputs[binding.input] = value\n}\n\nfunction historyEntry(history: unknown, promptId: string): JsonObject | null {\n if (!isObject(history)) throw new Error(\"ComfyUI returned invalid history JSON\")\n const entry = history[promptId]\n if (entry == null) return null\n if (!isObject(entry)) throw new Error(`ComfyUI returned invalid history for prompt ${promptId}`)\n return entry\n}\n\nfunction outputImages(entry: JsonObject, outputNodeId: string): ComfyImage[] | Error {\n if (!isObject(entry.outputs)) return new Error(\"ComfyUI completed without workflow outputs\")\n const output = entry.outputs[outputNodeId]\n if (!isObject(output) || !Array.isArray(output.images)) {\n return new Error(`ComfyUI output node \"${outputNodeId}\" returned no images`)\n }\n const images: ComfyImage[] = []\n for (const value of output.images) {\n if (\n !isObject(value) ||\n typeof value.filename !== \"string\" ||\n typeof value.subfolder !== \"string\" ||\n value.type !== \"output\"\n ) {\n return new Error(`ComfyUI output node \"${outputNodeId}\" returned an invalid image record`)\n }\n images.push({ filename: value.filename, subfolder: value.subfolder, type: \"output\" })\n }\n if (!images.length) return new Error(`ComfyUI output node \"${outputNodeId}\" returned no images`)\n return images\n}\n\nfunction comfyMetadata(\n spec: ResolvedSpec,\n promptId: string,\n outputNodeId: string,\n images: ComfyImage[],\n): JsonObject {\n const options = resolvedOptions(spec)\n const inputs = providerInputProvenance(spec.providerInputs)\n return {\n promptId,\n outputNodeId,\n outputCount: images.length,\n workflowFile: options.workflowFile,\n workflowSha256: options.workflowSha256,\n files: images.map((image) => ({ ...image })),\n ...(Object.keys(inputs).length ? { inputs } : {}),\n ...(spec.revision\n ? {\n revision: {\n mode: spec.revision.mode,\n sourceAssetId: spec.revision.sourceAssetId,\n sourceSha256: spec.revision.sourceSha256,\n ...(spec.revision.maskSha256\n ? { maskSha256: spec.revision.maskSha256 }\n : {}),\n ...(spec.revision.strength == null ? {} : { strength: spec.revision.strength }),\n },\n }\n : {}),\n }\n}\n\nfunction comfyFrameMetadata(\n spec: ResolvedSpec,\n job: FrameSetJob,\n images: ComfyImage[],\n fps: number,\n): JsonObject {\n const options = resolvedOptions(spec)\n return {\n workflowFile: options.workflowFile,\n workflowSha256: options.workflowSha256,\n outputNodeId: job.outputNodeId,\n inputs: providerInputProvenance(spec.providerInputs),\n frameSet: {\n count: images.length,\n vary: options.frames!.vary,\n seedStep: options.frames!.seedStep,\n fps,\n promptIds: job.promptIds,\n frames: images.map((image, index) => ({ role: frameRole(index), ...image })),\n },\n }\n}\n\nfunction isImageBinding(workflow: ComfyWorkflow, binding: ComfyUIBinding): boolean {\n const node = workflow[binding.nodeId]\n return binding.input === \"image\" &&\n (node?.class_type === \"LoadImage\" || node?.class_type === \"LoadImageMask\")\n}\n\nfunction isComfyImageInput(value: unknown): value is ComfyUIImageInput {\n return isObject(value) &&\n value.kind === \"image\" &&\n typeof value.path === \"string\" &&\n typeof value.sha256 === \"string\" &&\n (value.format === \"png\" || value.format === \"jpeg\")\n}\n\nfunction providerInputProvenance(\n inputs: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n return Object.fromEntries(Object.entries(inputs ?? {}).map(([name, input]) => [\n name,\n Array.isArray(input)\n ? { kind: \"sequence\", values: input.map(providerInputValueProvenance) }\n : providerInputValueProvenance(input),\n ]))\n}\n\nfunction providerInputValueProvenance(input: unknown): unknown {\n return isComfyImageInput(input)\n ? { kind: \"image\", sha256: input.sha256, format: input.format }\n : { kind: \"value\", value: input }\n}\n\nfunction inputImageFormat(bytes: Buffer): \"png\" | \"jpeg\" | null {\n if (\n bytes.length >= 24 &&\n bytes.readUInt32BE(0) === 0x89504e47 &&\n bytes.readUInt32BE(4) === 0x0d0a1a0a &&\n bytes.toString(\"ascii\", 12, 16) === \"IHDR\" &&\n bytes.readUInt32BE(16) > 0 &&\n bytes.readUInt32BE(20) > 0\n ) return \"png\"\n\n if (bytes.length < 4 || bytes[0] !== 0xff || bytes[1] !== 0xd8) return null\n let offset = 2\n while (offset + 3 < bytes.length) {\n if (bytes[offset] !== 0xff) return null\n while (bytes[offset] === 0xff) offset++\n const marker = bytes[offset++]\n if (marker == null || marker === 0xd9 || marker === 0xda) break\n if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) continue\n if (offset + 2 > bytes.length) return null\n const length = bytes.readUInt16BE(offset)\n if (length < 2 || offset + length > bytes.length) return null\n const isStartOfFrame = marker >= 0xc0 && marker <= 0xcf && ![0xc4, 0xc8, 0xcc].includes(marker)\n if (isStartOfFrame) {\n if (length < 7) return null\n return bytes.readUInt16BE(offset + 3) > 0 && bytes.readUInt16BE(offset + 5) > 0\n ? \"jpeg\"\n : null\n }\n offset += length\n }\n return null\n}\n\nfunction encodeJob(promptId: string, outputNodeId: string): string {\n return `${promptId}#${encodeURIComponent(outputNodeId)}`\n}\n\nfunction frameRole(index: number): string {\n return `frame-${String(index).padStart(2, \"0\")}`\n}\n\nfunction encodeFrameSetJob(job: FrameSetJob): string {\n return `frames:${Buffer.from(JSON.stringify(job)).toString(\"base64url\")}`\n}\n\nfunction decodeFrameSetJob(jobId: string): FrameSetJob {\n if (!jobId.startsWith(\"frames:\")) throw new Error(`Invalid ComfyUI frame-set job id \"${jobId}\"`)\n let value: unknown\n try {\n value = JSON.parse(Buffer.from(jobId.slice(7), \"base64url\").toString(\"utf8\"))\n } catch {\n throw new Error(`Invalid ComfyUI frame-set job id \"${jobId}\"`)\n }\n if (\n !isObject(value) ||\n typeof value.outputNodeId !== \"string\" ||\n !value.outputNodeId ||\n !Array.isArray(value.promptIds) ||\n value.promptIds.length < 2 ||\n value.promptIds.length > 64 ||\n !value.promptIds.every((id) => typeof id === \"string\" && id.length > 0)\n ) {\n throw new Error(`Invalid ComfyUI frame-set job id \"${jobId}\"`)\n }\n return { outputNodeId: value.outputNodeId, promptIds: value.promptIds as string[] }\n}\n\nfunction decodeJob(jobId: string): { promptId: string; outputNodeId: string } {\n const split = jobId.lastIndexOf(\"#\")\n if (split < 1 || split === jobId.length - 1) throw new Error(`Invalid ComfyUI job id \"${jobId}\"`)\n return {\n promptId: jobId.slice(0, split),\n outputNodeId: decodeURIComponent(jobId.slice(split + 1)),\n }\n}\n\nfunction sourceRef(image: ComfyImage): string {\n const url = new URL(\"comfyui://output\")\n url.searchParams.set(\"filename\", image.filename)\n url.searchParams.set(\"subfolder\", image.subfolder)\n url.searchParams.set(\"type\", image.type)\n return url.toString()\n}\n\nfunction parseSource(source: string): ComfyImage {\n let url: URL\n try {\n url = new URL(source)\n } catch {\n throw new Error(\"Invalid ComfyUI output reference\")\n }\n const filename = url.searchParams.get(\"filename\")\n const subfolder = url.searchParams.get(\"subfolder\")\n const type = url.searchParams.get(\"type\")\n if (url.protocol !== \"comfyui:\" || url.hostname !== \"output\" || !filename || subfolder == null || type !== \"output\") {\n throw new Error(\"Invalid ComfyUI output reference\")\n }\n return { filename, subfolder, type }\n}\n\nfunction normalizeBaseUrl(value: string): string {\n let url: URL\n try {\n url = new URL(value)\n } catch {\n throw new Error(\"COMFYUI_BASE_URL must be an absolute HTTP(S) URL\")\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"COMFYUI_BASE_URL must use HTTP or HTTPS\")\n }\n url.hash = \"\"\n url.search = \"\"\n return url.toString().replace(/\\/$/, \"\")\n}\n\nfunction historyError(status: JsonObject): string {\n const messages = Array.isArray(status.messages) ? status.messages : []\n for (const message of messages) {\n if (!Array.isArray(message) || message[0] !== \"execution_error\" || !isObject(message[1])) continue\n const detail = message[1].exception_message\n if (typeof detail === \"string\" && detail.trim()) {\n return `ComfyUI execution failed: ${detail.trim().slice(0, 300)}`\n }\n }\n return \"ComfyUI execution failed\"\n}\n\nfunction apiError(value: unknown): string | null {\n if (!isObject(value)) return null\n const raw = typeof value.error === \"string\"\n ? value.error\n : isObject(value.error) && typeof value.error.message === \"string\"\n ? value.error.message\n : typeof value.message === \"string\"\n ? value.message\n : null\n const nodes = isObject(value.node_errors) ? Object.keys(value.node_errors) : []\n if (nodes.length) {\n return `${raw ? `${raw}; ` : \"\"}invalid workflow node(s): ${nodes.slice(0, 8).join(\", \")}`\n }\n return raw?.trim().slice(0, 300) || null\n}\n\nfunction requiredString(value: unknown, name: string): string {\n if (typeof value !== \"string\" || !value.trim()) throw new Error(`ComfyUI ${name} must be a non-empty string`)\n return value.trim()\n}\n\nfunction isObject(value: unknown): value is JsonObject {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value)\n}\n\nfunction canonical(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonical)\n if (!isObject(value)) return value\n return Object.fromEntries(\n Object.keys(value)\n .sort()\n .map((key) => [key, canonical(value[key])]),\n )\n}\n","import { createHash } from \"node:crypto\"\nimport { createReadStream } from \"node:fs\"\nimport type { ResolvedSpec } from \"./types.ts\"\n\nexport function sha256(data: Buffer | string): string {\n return createHash(\"sha256\").update(data).digest(\"hex\")\n}\n\nexport async function sha256File(path: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const hash = createHash(\"sha256\")\n const stream = createReadStream(path)\n stream.on(\"data\", (chunk) => hash.update(chunk))\n stream.on(\"error\", reject)\n stream.on(\"end\", () => resolve(hash.digest(\"hex\")))\n })\n}\n\n/**\n * Identity of a spec: everything that would change the generated image.\n * Project root, `outFile`, committed `source`, and `tags` are deliberately excluded —\n * moving a checkout, renaming the destination, swapping the committed art a\n * `mount` places, or retagging should not regenerate art.\n *\n * Generator-specific parameters are hashed only where they apply, and are\n * left `undefined` otherwise so `JSON.stringify` drops the key entirely.\n * That matters: adding a field unconditionally rewrites the hash of every\n * spec in every existing lockfile, and each one then reports as `stale` and\n * invites a full regeneration of art that never changed. Adding `palette`\n * unconditionally did exactly that once already.\n */\nexport function specHash(\n spec: Omit<ResolvedSpec, \"specHash\" | \"root\" | \"outFile\" | \"quality\" | \"source\" | \"tags\">,\n styleImageHashes: string[],\n providerOptionIdentity: unknown = spec.providerOptions,\n providerInputIdentity: unknown = spec.providerInputs ?? {},\n): string {\n return sha256(\n JSON.stringify({\n // Preserve every existing PixelLab hash while making a provider switch\n // invalidate the spec. Older manifests implicitly mean pixellab.\n provider: spec.provider === \"pixellab\" ? undefined : spec.provider,\n providerOptions:\n providerOptionIdentity &&\n (typeof providerOptionIdentity !== \"object\" || Object.keys(providerOptionIdentity).length > 0)\n ? providerOptionIdentity\n : undefined,\n providerInputs:\n providerInputIdentity &&\n (typeof providerInputIdentity !== \"object\" || Object.keys(providerInputIdentity).length > 0)\n ? providerInputIdentity\n : undefined,\n generator: spec.generator,\n prompt: spec.prompt,\n width: spec.width,\n height: spec.height,\n view: spec.view,\n outline: spec.outline ?? null,\n shading: spec.shading ?? null,\n detail: spec.detail ?? null,\n seed: spec.seed ?? null,\n palette: spec.palette,\n // `noBackground` only reaches the wire for pixflux; the tile fields are\n // undefined for every other generator. `tileSize` is intentionally\n // absent — width/height are derived from it, so it is already covered.\n noBackground:\n spec.generator === \"pixflux\" || spec.provider !== \"pixellab\"\n ? spec.noBackground\n : undefined,\n tileType: spec.tileType,\n tileView: spec.tileView,\n tileFeature: spec.tileFeature,\n outlineMode: spec.outlineMode,\n styleImages: styleImageHashes,\n revision: spec.revision\n ? {\n mode: spec.revision.mode,\n from: spec.revision.sourceAssetId,\n sourceSha256: spec.revision.sourceSha256,\n maskSha256: spec.revision.maskSha256,\n strength: spec.revision.strength,\n }\n : undefined,\n }),\n )\n}\n","import { deflateSync, inflateSync } from \"node:zlib\"\n\nexport interface DecodedPng {\n width: number\n height: number\n /** RGBA, 4 bytes per pixel, row-major. */\n pixels: Buffer\n}\n\nconst SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])\nconst MAX_DECODED_BYTES = 256 * 1024 * 1024\n\ninterface PngHeader {\n width: number\n height: number\n bitDepth: number\n colorType: number\n channels: number\n}\n\nconst CHANNELS = new Map([\n [0, 1], // greyscale\n [2, 3], // RGB\n [3, 1], // indexed colour\n [4, 2], // greyscale + alpha\n [6, 4], // RGBA\n])\n\nconst LEGAL_DEPTHS = new Map<number, Set<number>>([\n [0, new Set([1, 2, 4, 8, 16])],\n [2, new Set([8, 16])],\n [3, new Set([1, 2, 4, 8])],\n [4, new Set([8, 16])],\n [6, new Set([8, 16])],\n])\n\n/**\n * Dependency-free decoder for standard non-interlaced PNG colour modes.\n *\n * Inputs are normalized to 8-bit RGBA for the audit and sheet pipelines. Adam7\n * remains deliberately unsupported: provider and game-art PNGs are normally\n * non-interlaced, and refusing the uncommon layout is safer than implementing\n * a second scanline geometry without a dedicated image dependency.\n */\nexport function decodePng(buf: Buffer): DecodedPng {\n if (buf.length < 8 || !buf.subarray(0, 8).equals(SIGNATURE)) {\n throw new Error(\"not a PNG\")\n }\n\n let header: PngHeader | null = null\n let palette: Buffer | null = null\n let transparency: Buffer | null = null\n let sawImageData = false\n let sawEnd = false\n const idat: Buffer[] = []\n\n let offset = 8\n while (offset < buf.length) {\n if (offset + 12 > buf.length) throw new Error(\"truncated PNG chunk header\")\n const length = buf.readUInt32BE(offset)\n const type = buf.toString(\"ascii\", offset + 4, offset + 8)\n if (!/^[A-Za-z]{4}$/.test(type) || /[a-z]/.test(type[2]!)) {\n throw new Error(`PNG has an invalid chunk type ${JSON.stringify(type)}`)\n }\n const end = offset + 12 + length\n if (!Number.isSafeInteger(end) || end > buf.length) {\n throw new Error(`truncated PNG chunk ${type || \"(unknown)\"}`)\n }\n const data = buf.subarray(offset + 8, offset + 8 + length)\n const expectedCrc = buf.readUInt32BE(offset + 8 + length)\n const actualCrc = crc32(buf.subarray(offset + 4, offset + 8 + length)) >>> 0\n if (actualCrc !== expectedCrc) throw new Error(`PNG chunk ${type} has an invalid checksum`)\n\n if (!header && type !== \"IHDR\") throw new Error(\"PNG is missing its leading IHDR chunk\")\n\n if (type === \"IHDR\") {\n if (header) throw new Error(\"PNG has more than one IHDR chunk\")\n if (data.length !== 13) throw new Error(\"PNG has an invalid IHDR chunk\")\n const width = data.readUInt32BE(0)\n const height = data.readUInt32BE(4)\n const bitDepth = data[8]!\n const colorType = data[9]!\n const channels = CHANNELS.get(colorType)\n if (!width || !height) throw new Error(\"PNG dimensions must be positive\")\n if (!channels || !LEGAL_DEPTHS.get(colorType)?.has(bitDepth)) {\n throw new Error(`unsupported PNG: bitDepth=${bitDepth} colorType=${colorType}`)\n }\n if (data[10] !== 0) throw new Error(`unsupported PNG compression method ${data[10]}`)\n if (data[11] !== 0) throw new Error(`unsupported PNG filter method ${data[11]}`)\n if (data[12] !== 0) throw new Error(\"unsupported PNG: interlaced\")\n header = { width, height, bitDepth, colorType, channels }\n } else if (type === \"PLTE\") {\n if (sawImageData) throw new Error(\"PNG palette appears after image data\")\n if (palette) throw new Error(\"PNG has more than one palette\")\n if (!data.length || data.length % 3 !== 0 || data.length > 256 * 3) {\n throw new Error(\"PNG has an invalid palette\")\n }\n palette = Buffer.from(data)\n } else if (type === \"tRNS\") {\n if (sawImageData) throw new Error(\"PNG transparency appears after image data\")\n if (transparency) throw new Error(\"PNG has more than one transparency chunk\")\n transparency = Buffer.from(data)\n } else if (type === \"IDAT\") {\n sawImageData = true\n idat.push(data)\n } else if (type === \"IEND\") {\n if (data.length !== 0) throw new Error(\"PNG has an invalid IEND chunk\")\n sawEnd = true\n break\n } else if (/^[A-Z]/.test(type)) {\n throw new Error(`unsupported critical PNG chunk ${type}`)\n }\n offset = end\n }\n\n if (!header) throw new Error(\"PNG has no image header\")\n if (!sawEnd) throw new Error(\"PNG has no IEND chunk\")\n if (!idat.length) throw new Error(\"PNG has no image data\")\n validatePalette(header, palette)\n validateTransparency(header.colorType, transparency, palette)\n\n const bitsPerPixel = header.channels * header.bitDepth\n const stride = Math.ceil((header.width * bitsPerPixel) / 8)\n const rawLength = (stride + 1) * header.height\n const rgbaLength = header.width * header.height * 4\n if (\n !Number.isSafeInteger(rawLength) ||\n !Number.isSafeInteger(rgbaLength) ||\n rawLength > MAX_DECODED_BYTES ||\n rgbaLength > MAX_DECODED_BYTES\n ) {\n throw new Error(\"PNG dimensions exceed the 256 MiB decoded-image limit\")\n }\n\n let raw: Buffer\n try {\n raw = inflateSync(Buffer.concat(idat), { maxOutputLength: rawLength })\n } catch (err) {\n throw new Error(`invalid PNG image data: ${err instanceof Error ? err.message : String(err)}`)\n }\n if (raw.length !== rawLength) {\n throw new Error(`invalid PNG image data length: expected ${rawLength}, got ${raw.length}`)\n }\n\n const filterBytes = Math.max(1, Math.ceil(bitsPerPixel / 8))\n const samples = unfilter(raw, stride, header.height, filterBytes)\n return {\n width: header.width,\n height: header.height,\n pixels: toRgba(samples, header, stride, palette, transparency),\n }\n}\n\nfunction validatePalette(header: PngHeader, palette: Buffer | null): void {\n if (header.colorType === 3 && !palette) throw new Error(\"indexed PNG has no palette\")\n if ((header.colorType === 0 || header.colorType === 4) && palette) {\n throw new Error(\"greyscale PNG cannot contain a palette\")\n }\n if (header.colorType === 3 && palette && palette.length / 3 > 2 ** header.bitDepth) {\n throw new Error(\"indexed PNG palette has more entries than its bit depth permits\")\n }\n}\n\n/**\n * Reverses PNG's per-scanline filters. Each row is prefixed with a filter byte\n * and predicted from the row above and the pixel to the left.\n */\nfunction unfilter(raw: Buffer, stride: number, height: number, bpp: number): Buffer {\n const out = Buffer.alloc(stride * height)\n\n for (let y = 0; y < height; y++) {\n const filter = raw[y * (stride + 1)]!\n const src = raw.subarray(y * (stride + 1) + 1, y * (stride + 1) + 1 + stride)\n const dst = out.subarray(y * stride, (y + 1) * stride)\n const prev = y > 0 ? out.subarray((y - 1) * stride, y * stride) : null\n\n for (let x = 0; x < stride; x++) {\n const a = x >= bpp ? dst[x - bpp]! : 0 // left\n const b = prev ? prev[x]! : 0 // above\n const c = prev && x >= bpp ? prev[x - bpp]! : 0 // upper-left\n const v = src[x]!\n switch (filter) {\n case 0: dst[x] = v; break\n case 1: dst[x] = (v + a) & 0xff; break\n case 2: dst[x] = (v + b) & 0xff; break\n case 3: dst[x] = (v + ((a + b) >> 1)) & 0xff; break\n case 4: dst[x] = (v + paeth(a, b, c)) & 0xff; break\n default: throw new Error(`unknown PNG filter ${filter} on row ${y}`)\n }\n }\n }\n return out\n}\n\nfunction validateTransparency(\n colorType: number,\n transparency: Buffer | null,\n palette: Buffer | null,\n): void {\n if (!transparency) return\n if (colorType === 0 && transparency.length !== 2) {\n throw new Error(\"greyscale PNG has an invalid transparency chunk\")\n }\n if (colorType === 2 && transparency.length !== 6) {\n throw new Error(\"RGB PNG has an invalid transparency chunk\")\n }\n if (colorType === 3 && transparency.length > (palette?.length ?? 0) / 3) {\n throw new Error(\"indexed PNG transparency exceeds its palette\")\n }\n if (colorType === 4 || colorType === 6) {\n throw new Error(\"PNG with an alpha channel cannot also contain tRNS\")\n }\n}\n\nfunction toRgba(\n samples: Buffer,\n header: PngHeader,\n stride: number,\n palette: Buffer | null,\n transparency: Buffer | null,\n): Buffer {\n const out = Buffer.alloc(header.width * header.height * 4)\n const transparentGrey = header.colorType === 0 && transparency\n ? transparency.readUInt16BE(0)\n : null\n const transparentRgb = header.colorType === 2 && transparency\n ? [\n transparency.readUInt16BE(0),\n transparency.readUInt16BE(2),\n transparency.readUInt16BE(4),\n ]\n : null\n\n for (let y = 0; y < header.height; y++) {\n const row = samples.subarray(y * stride, (y + 1) * stride)\n for (let x = 0; x < header.width; x++) {\n const dst = (y * header.width + x) * 4\n if (header.colorType === 0) {\n const grey = sample(row, x, 0, header.channels, header.bitDepth)\n const byte = sampleToByte(grey, header.bitDepth)\n out[dst] = byte\n out[dst + 1] = byte\n out[dst + 2] = byte\n out[dst + 3] = grey === transparentGrey ? 0 : 255\n } else if (header.colorType === 2) {\n const rgb = [0, 1, 2].map((channel) =>\n sample(row, x, channel, header.channels, header.bitDepth))\n out[dst] = sampleToByte(rgb[0]!, header.bitDepth)\n out[dst + 1] = sampleToByte(rgb[1]!, header.bitDepth)\n out[dst + 2] = sampleToByte(rgb[2]!, header.bitDepth)\n out[dst + 3] = transparentRgb && rgb.every((value, i) => value === transparentRgb[i])\n ? 0\n : 255\n } else if (header.colorType === 3) {\n const index = sample(row, x, 0, 1, header.bitDepth)\n const paletteOffset = index * 3\n if (!palette || paletteOffset + 2 >= palette.length) {\n throw new Error(`indexed PNG pixel references missing palette entry ${index}`)\n }\n out[dst] = palette[paletteOffset]!\n out[dst + 1] = palette[paletteOffset + 1]!\n out[dst + 2] = palette[paletteOffset + 2]!\n out[dst + 3] = transparency?.[index] ?? 255\n } else if (header.colorType === 4) {\n const grey = sampleToByte(sample(row, x, 0, 2, header.bitDepth), header.bitDepth)\n out[dst] = grey\n out[dst + 1] = grey\n out[dst + 2] = grey\n out[dst + 3] = sampleToByte(sample(row, x, 1, 2, header.bitDepth), header.bitDepth)\n } else {\n out[dst] = sampleToByte(sample(row, x, 0, 4, header.bitDepth), header.bitDepth)\n out[dst + 1] = sampleToByte(sample(row, x, 1, 4, header.bitDepth), header.bitDepth)\n out[dst + 2] = sampleToByte(sample(row, x, 2, 4, header.bitDepth), header.bitDepth)\n out[dst + 3] = sampleToByte(sample(row, x, 3, 4, header.bitDepth), header.bitDepth)\n }\n }\n }\n return out\n}\n\nfunction sample(\n row: Buffer,\n x: number,\n channel: number,\n channels: number,\n bitDepth: number,\n): number {\n if (bitDepth === 8) return row[x * channels + channel]!\n if (bitDepth === 16) return row.readUInt16BE((x * channels + channel) * 2)\n const bitOffset = x * bitDepth\n const shift = 8 - bitDepth - (bitOffset % 8)\n return (row[Math.floor(bitOffset / 8)]! >> shift) & ((1 << bitDepth) - 1)\n}\n\nfunction sampleToByte(value: number, bitDepth: number): number {\n if (bitDepth === 8) return value\n if (bitDepth === 16) return Math.round(value / 257)\n return Math.round((value * 255) / ((1 << bitDepth) - 1))\n}\n\nfunction paeth(a: number, b: number, c: number): number {\n const p = a + b - c\n const pa = Math.abs(p - a)\n const pb = Math.abs(p - b)\n const pc = Math.abs(p - c)\n if (pa <= pb && pa <= pc) return a\n return pb <= pc ? b : c\n}\n\nexport interface PaletteEntry {\n r: number\n g: number\n b: number\n /** Share of opaque pixels using this colour, 0-1. */\n weight: number\n}\n\n/**\n * Dominant colours of an image, ignoring transparency.\n *\n * Pixel art uses a small deliberate palette, so exact colour counting works —\n * no clustering needed. Nearly-transparent pixels are excluded because\n * anti-aliased edges would otherwise dominate the histogram of a small sprite.\n */\nexport function extractPalette(png: DecodedPng, topN = 8, alphaThreshold = 128): PaletteEntry[] {\n const counts = new Map<number, number>()\n let opaque = 0\n\n for (let i = 0; i < png.pixels.length; i += 4) {\n const alpha = png.pixels[i + 3]!\n if (alpha < alphaThreshold) continue\n opaque++\n const key = (png.pixels[i]! << 16) | (png.pixels[i + 1]! << 8) | png.pixels[i + 2]!\n counts.set(key, (counts.get(key) ?? 0) + 1)\n }\n if (opaque === 0) return []\n\n return [...counts.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, topN)\n .map(([key, n]) => ({\n r: (key >> 16) & 0xff,\n g: (key >> 8) & 0xff,\n b: key & 0xff,\n weight: n / opaque,\n }))\n}\n\n/** Fraction of pixels that are effectively transparent — a silhouette check. */\nexport function transparencyRatio(png: DecodedPng, alphaThreshold = 128): number {\n let clear = 0\n const total = png.pixels.length / 4\n for (let i = 0; i < png.pixels.length; i += 4) {\n if (png.pixels[i + 3]! < alphaThreshold) clear++\n }\n return total === 0 ? 0 : clear / total\n}\n\n/** CRC-32 as PNG specifies it. Small enough not to warrant a dependency. */\nfunction crc32(buf: Buffer): number {\n let c = ~0\n for (const byte of buf) {\n c ^= byte\n for (let k = 0; k < 8; k++) c = (c >>> 1) ^ (0xedb88320 & -(c & 1))\n }\n return ~c\n}\n\nfunction chunk(type: string, data: Buffer): Buffer {\n const len = Buffer.alloc(4)\n len.writeUInt32BE(data.length)\n const body = Buffer.concat([Buffer.from(type, \"ascii\"), data])\n const crc = Buffer.alloc(4)\n crc.writeUInt32BE(crc32(body) >>> 0)\n return Buffer.concat([len, body, crc])\n}\n\n/**\n * Writes an 8-bit RGB PNG. Used to build the small swatch image that carries a\n * forced palette to the API — not a general encoder.\n */\nexport function encodeRgbPng(width: number, height: number, rgb: Buffer): Buffer {\n if (rgb.length !== width * height * 3) {\n throw new Error(`expected ${width * height * 3} bytes of RGB, got ${rgb.length}`)\n }\n const stride = width * 3\n // Filter byte 0 (none) per scanline.\n const raw = Buffer.alloc((stride + 1) * height)\n for (let y = 0; y < height; y++) {\n raw[y * (stride + 1)] = 0\n rgb.copy(raw, y * (stride + 1) + 1, y * stride, (y + 1) * stride)\n }\n const ihdr = Buffer.alloc(13)\n ihdr.writeUInt32BE(width, 0)\n ihdr.writeUInt32BE(height, 4)\n ihdr[8] = 8 // bit depth\n ihdr[9] = 2 // colour type: RGB\n return Buffer.concat([\n Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),\n chunk(\"IHDR\", ihdr),\n chunk(\"IDAT\", deflateSync(raw)),\n chunk(\"IEND\", Buffer.alloc(0)),\n ])\n}\n\n/**\n * Writes an 8-bit RGBA PNG.\n *\n * Separate from `encodeRgbPng` rather than replacing it: the palette swatch\n * the API accepts is RGB, and sprite sheets must keep their alpha channel —\n * flattening it would fill every sprite's transparent background with black\n * and the sheet would be unusable over anything but that colour.\n */\nexport function encodeRgbaPng(width: number, height: number, rgba: Buffer): Buffer {\n if (rgba.length !== width * height * 4) {\n throw new Error(`expected ${width * height * 4} bytes of RGBA, got ${rgba.length}`)\n }\n const stride = width * 4\n // Filter byte 0 (none) per scanline. Pixel art compresses well enough that\n // the adaptive filters are not worth the complexity here.\n const raw = Buffer.alloc((stride + 1) * height)\n for (let y = 0; y < height; y++) {\n raw[y * (stride + 1)] = 0\n rgba.copy(raw, y * (stride + 1) + 1, y * stride, (y + 1) * stride)\n }\n const ihdr = Buffer.alloc(13)\n ihdr.writeUInt32BE(width, 0)\n ihdr.writeUInt32BE(height, 4)\n ihdr[8] = 8 // bit depth\n ihdr[9] = 6 // colour type: RGBA\n return Buffer.concat([\n Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),\n chunk(\"IHDR\", ihdr),\n chunk(\"IDAT\", deflateSync(raw)),\n chunk(\"IEND\", Buffer.alloc(0)),\n ])\n}\n\n/**\n * Builds the palette swatch the API expects: a block of solid colour per entry.\n *\n * Deliberately chunky rather than one pixel per colour — a 4x1 image was\n * rejected outright with \"cannot identify image file\", while a 64x64 block\n * swatch was accepted.\n */\nexport function paletteSwatch(hexes: string[], size = 64): Buffer {\n const colours = hexes.map(parseHex)\n if (!colours.length) throw new Error(\"palette is empty\")\n const rgb = Buffer.alloc(size * size * 3)\n const band = Math.max(1, Math.floor(size / colours.length))\n for (let y = 0; y < size; y++) {\n for (let x = 0; x < size; x++) {\n const c = colours[Math.min(colours.length - 1, Math.floor(x / band))]!\n const o = (y * size + x) * 3\n rgb[o] = c.r\n rgb[o + 1] = c.g\n rgb[o + 2] = c.b\n }\n }\n return encodeRgbPng(size, size, rgb)\n}\n\nexport function parseHex(hex: string): { r: number; g: number; b: number } {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim())\n if (!m) throw new Error(`invalid hex colour \"${hex}\" — expected #rrggbb`)\n const n = parseInt(m[1]!, 16)\n return { r: (n >> 16) & 0xff, g: (n >> 8) & 0xff, b: n & 0xff }\n}\n","import { decodePng } from \"./png.ts\"\n\nexport const MediaType = {\n PNG: \"image/png\",\n GIF: \"image/gif\",\n} as const\n\nexport type MediaType = (typeof MediaType)[keyof typeof MediaType]\n\nconst PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])\n\nexport function mediaExtension(mediaType: MediaType): \".png\" | \".gif\" {\n return mediaType === MediaType.GIF ? \".gif\" : \".png\"\n}\n\nexport function mediaTypeFromExtension(file: string): MediaType | null {\n const lower = file.toLowerCase()\n if (lower.endsWith(\".png\")) return MediaType.PNG\n if (lower.endsWith(\".gif\")) return MediaType.GIF\n return null\n}\n\nexport function detectMediaType(bytes: Buffer): MediaType | null {\n if (bytes.subarray(0, PNG_SIGNATURE.length).equals(PNG_SIGNATURE)) return MediaType.PNG\n const header = bytes.subarray(0, 6).toString(\"ascii\")\n if (header === \"GIF87a\" || header === \"GIF89a\") return MediaType.GIF\n return null\n}\n\n/** Validate durable provider output before it reaches disk or the recovery cache. */\nexport function validateMedia(bytes: Buffer, expected?: MediaType): MediaType {\n const actual = detectMediaType(bytes)\n if (!actual) throw new Error(`response was not a supported PNG or GIF (${bytes.length} bytes)`)\n if (expected && actual !== expected) {\n throw new Error(`response was ${actual}, expected ${expected}`)\n }\n if (actual === MediaType.PNG) {\n decodePng(bytes)\n } else {\n validateGif(bytes)\n }\n return actual\n}\n\n/** Walk GIF blocks far enough to reject truncated/error-page payloads. */\nfunction validateGif(bytes: Buffer): void {\n if (bytes.length < 14) throw new Error(\"invalid GIF: truncated logical screen descriptor\")\n const width = bytes.readUInt16LE(6)\n const height = bytes.readUInt16LE(8)\n if (!width || !height) throw new Error(\"invalid GIF: zero-sized logical screen\")\n\n const packed = bytes[10]!\n let offset = 13\n if (packed & 0x80) offset += 3 * 2 ** ((packed & 0x07) + 1)\n if (offset > bytes.length) throw new Error(\"invalid GIF: truncated global color table\")\n\n let sawImage = false\n while (offset < bytes.length) {\n const marker = bytes[offset]!\n if (marker === 0x3b) {\n if (!sawImage) throw new Error(\"invalid GIF: contains no image frame\")\n return\n }\n if (marker === 0x2c) {\n if (offset + 10 > bytes.length) throw new Error(\"invalid GIF: truncated image descriptor\")\n const imagePacked = bytes[offset + 9]!\n offset += 10\n if (imagePacked & 0x80) offset += 3 * 2 ** ((imagePacked & 0x07) + 1)\n if (offset >= bytes.length) throw new Error(\"invalid GIF: missing image data\")\n offset++ // LZW minimum code size\n offset = skipSubBlocks(bytes, offset)\n sawImage = true\n continue\n }\n if (marker === 0x21) {\n if (offset + 2 > bytes.length) throw new Error(\"invalid GIF: truncated extension\")\n offset = skipSubBlocks(bytes, offset + 2)\n continue\n }\n throw new Error(`invalid GIF: unexpected block marker 0x${marker.toString(16)}`)\n }\n throw new Error(\"invalid GIF: missing trailer\")\n}\n\nfunction skipSubBlocks(bytes: Buffer, start: number): number {\n let offset = start\n for (;;) {\n if (offset >= bytes.length) throw new Error(\"invalid GIF: truncated data blocks\")\n const size = bytes[offset]!\n offset++\n if (size === 0) return offset\n offset += size\n if (offset > bytes.length) throw new Error(\"invalid GIF: truncated data block\")\n }\n}\n\nexport function cacheFileName(hash: string, mediaType: MediaType = MediaType.PNG): string {\n return `${hash}${mediaExtension(mediaType)}`\n}\n","import { mkdirSync, existsSync, readFileSync, writeFileSync } from \"node:fs\"\nimport { randomUUID } from \"node:crypto\"\nimport os from \"node:os\"\nimport path from \"node:path\"\nimport { PixelLabClient, PixelLabError, clientFromEnv } from \"../client.ts\"\nimport { paletteSwatch } from \"../png.ts\"\nimport {\n candidateCount,\n generationCost,\n type Generator,\n type ResolvedSpec,\n type ResolvedStyleImage,\n} from \"../types.ts\"\nimport type { BalanceInfo, CostEstimate, JobState, PollContext, Provider, RateLimit, RemoteAsset } from \"../provider.ts\"\n\n/**\n * PixelLab, the reference implementation.\n *\n * All PixelLab-specific knowledge lives here: the three generators and their\n * very different pricing, the review/candidate flow, the fact that a map\n * object's job record expires while its image does not, and that pixflux\n * returns bytes inline instead of a job id.\n */\nexport class PixelLabProvider implements Provider {\n readonly id = \"pixellab\"\n\n constructor(private readonly client: PixelLabClient) {}\n\n static fromEnv(): PixelLabProvider {\n return new PixelLabProvider(clientFromEnv())\n }\n\n /** Public storage URLs and the local content cache do not require API auth. */\n static forDownloads(): PixelLabProvider {\n return PixelLabProvider.forOffline()\n }\n\n /** Capability and cost estimation only; makes no network request itself. */\n static forOffline(): PixelLabProvider {\n return new PixelLabProvider(new PixelLabClient(\"download-only\"))\n }\n\n supports(generator: Generator): boolean {\n return (\n generator === \"1dir\" ||\n generator === \"map\" ||\n generator === \"pixflux\" ||\n generator === \"tiles\"\n )\n }\n\n /** PixelLab's own constraints: submissions must be >2s apart, and\n * background jobs in flight are capped by subscription tier (Tier 1=8,\n * Tier 2=10, Tier 3=20) — 8 is the safe floor across every tier. */\n rateLimit(): RateLimit {\n return { spacingMs: 2500, maxInFlight: 8 }\n }\n\n /**\n * Where synchronous pixflux results are parked between `submit` and `fetch`.\n *\n * pixflux returns the PNG inline rather than a job id, but the pipeline is\n * built around submit → poll → fetch running as separate commands. Writing\n * the bytes to a known path keeps that model intact: the \"job id\" is the\n * filename, polling is an existence check, and downloading is a file read.\n */\n private static cacheDir(): string {\n const dir = path.join(os.tmpdir(), \"pixelkiln-pixflux\")\n mkdirSync(dir, { recursive: true })\n return dir\n }\n\n estimate(spec: ResolvedSpec): CostEstimate {\n // `tiles` prices and counts off the whole set, both of which the manifest\n // layer already worked out — see tilesCost / tileVariationCount.\n if (spec.generator === \"tiles\") {\n return { unit: \"generations\", amount: spec.cost, candidates: spec.candidates }\n }\n return {\n unit: \"generations\",\n amount: generationCost(spec.width, spec.height, spec.generator),\n candidates: spec.generator === \"1dir\" ? candidateCount(spec.size) : 1,\n }\n }\n\n validate(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): void {\n if (spec.generator === \"1dir\" && (spec.width < 32 || spec.width > 256)) {\n throw new Error(\"PixelLab 1dir dimensions must be between 32 and 256 pixels\")\n }\n if (\n (spec.generator === \"map\" || spec.generator === \"pixflux\") &&\n (spec.width < 16 || spec.height < 16 || spec.width > 400 || spec.height > 400)\n ) {\n throw new Error(`PixelLab ${spec.generator} dimensions must be between 16 and 400 pixels`)\n }\n if (spec.generator === \"map\") {\n requirePixelLabOption(\"view\", spec.view, [\"low top-down\", \"high top-down\", \"side\"])\n requirePixelLabOption(\"outline\", spec.outline, [\n \"single color outline\", \"selective outline\", \"lineless\",\n ])\n requirePixelLabOption(\"shading\", spec.shading, [\n \"flat shading\", \"basic shading\", \"medium shading\", \"detailed shading\",\n ])\n requirePixelLabOption(\"detail\", spec.detail, [\n \"low detail\", \"medium detail\", \"high detail\",\n ])\n }\n if ((spec.generator === \"map\" || spec.generator === \"pixflux\") && styleImages.length) {\n throw new Error(`PixelLab ${spec.generator} does not support style images`)\n }\n for (const image of styleImages) {\n if (image.width > 256 || image.height > 256) {\n throw new Error(\n `Style image exceeds PixelLab's 256x256 limit (${image.width}x${image.height})`,\n )\n }\n }\n if (spec.tags.length > 20) {\n throw new Error(\n `${spec.styleId}/${spec.assetId} resolves to ${spec.tags.length} tags, ` +\n `but PixelLab allows at most 20`,\n )\n }\n }\n\n async submit(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): Promise<{ jobId: string }> {\n this.validate(spec, styleImages)\n if (spec.generator === \"pixflux\") {\n const swatch = spec.palette.length\n ? paletteSwatch(spec.palette).toString(\"base64\")\n : undefined\n const { png } = await this.client.createImagePixflux({\n description: spec.prompt,\n width: spec.width,\n height: spec.height,\n noBackground: spec.noBackground,\n paletteSwatchBase64: swatch,\n seed: spec.seed,\n })\n const jobId = randomUUID()\n writeFileSync(path.join(PixelLabProvider.cacheDir(), `${jobId}.png`), png)\n return { jobId }\n }\n\n if (spec.generator === \"tiles\") {\n const res = await this.client.createTilesPro({\n description: spec.prompt,\n tileSize: spec.tileSize,\n tileType: spec.tileType,\n tileView: spec.tileView,\n tileFeature: spec.tileFeature,\n outlineMode: spec.outlineMode,\n seed: spec.seed,\n // TilesProStyleImage is flat and wants the reference's real dimensions,\n // unlike 1dir's {type, base64, format} payload.\n styleImages: styleImages.map(({ base64, width, height }) => ({ base64, width, height })),\n })\n return { jobId: res.tile_id }\n }\n\n if (spec.generator === \"1dir\") {\n const res = await this.client.create1Direction({\n description: spec.prompt,\n size: spec.size,\n view: spec.view === \"sidescroller\" ? \"sidescroller\" : \"top-down\",\n styleImages,\n })\n return { jobId: res.object_id }\n }\n const res = await this.client.createMapObject({\n description: spec.prompt,\n width: spec.width,\n height: spec.height,\n view: spec.view,\n outline: spec.outline,\n shading: spec.shading,\n detail: spec.detail,\n seed: spec.seed,\n })\n return { jobId: res.object_id }\n }\n\n async poll(jobId: string, generator: Generator, context?: PollContext): Promise<JobState> {\n if (generator === \"pixflux\") {\n const file = path.join(PixelLabProvider.cacheDir(), `${jobId}.png`)\n if (existsSync(file)) {\n const sourceUrl = `file://${file}`\n return { status: \"ready\", objectId: jobId, sourceUrl, sources: [{ url: sourceUrl }] }\n }\n // The bytes only ever lived here, so a missing file means the temp dir\n // was cleared. Nothing to recover from upstream — say so plainly.\n return {\n status: \"failed\",\n error: \"pixflux result is no longer cached locally; re-run submit for this asset\",\n }\n }\n if (generator === \"map\") return this.pollMap(jobId)\n if (generator === \"tiles\") return this.pollTiles(jobId, Boolean(context?.tileFeature))\n\n const obj = await this.client.getObject(jobId)\n if (obj.status === \"review\") {\n return { status: \"review\", candidateUrls: obj.frame_urls ?? [] }\n }\n if (obj.status === \"completed\") {\n const url = firstUrl(obj.rotation_urls) ?? obj.preview_url ?? null\n return { status: \"ready\", objectId: obj.id, sourceUrl: url, sources: url ? [{ url }] : [] }\n }\n if (obj.status === \"failed\") return { status: \"failed\", error: \"generation failed upstream\" }\n return {\n status: \"processing\",\n progressPercent: obj.progress_percent ?? null,\n etaSeconds: obj.eta_seconds ?? null,\n }\n }\n\n /**\n * Map objects need their own path because the `/map-objects/{id}` record is\n * deleted upstream roughly 8 hours after creation while the image survives in\n * the objects collection. Verified: a March 2026 sprite still resolves from\n * `/objects` four months on, with `/map-objects` returning 404 for the same\n * id. So a 404 here is not evidence the work is lost.\n */\n private async pollMap(jobId: string): Promise<JobState> {\n try {\n const obj = await this.client.getMapObject(jobId)\n if (obj.status === \"completed\" && obj.download_url) {\n return {\n status: \"ready\",\n objectId: jobId,\n sourceUrl: obj.download_url,\n sources: [{ url: obj.download_url }],\n }\n }\n if (obj.status === \"failed\") return { status: \"failed\", error: \"generation failed upstream\" }\n return { status: \"processing\" }\n } catch (err) {\n if (!(err instanceof PixelLabError) || err.status !== 404) throw err\n const survivor = await this.client.getObject(jobId).catch(() => null)\n const url = firstUrl(survivor?.rotation_urls) ?? survivor?.preview_url ?? null\n if (survivor?.status === \"completed\" && url) {\n return { status: \"ready\", objectId: survivor.id, sourceUrl: url, sources: [{ url }] }\n }\n return {\n status: \"failed\",\n error: \"map object record deleted upstream and no surviving image found\",\n }\n }\n }\n\n /**\n * Tiles report progress through the HTTP status: 423 while drawing, 200 with\n * `storage_urls` once finished. There is no `status` field to read and no\n * progress percentage on offer, so \"processing\" here carries no ETA.\n */\n private async pollTiles(tileId: string, connectable: boolean): Promise<JobState> {\n try {\n const set = await this.client.getTilesPro(tileId)\n const tiles = tilesInIndexOrder(set.storage_urls)\n if (!tiles.length) return { status: \"failed\", error: \"tiles job returned no storage urls\" }\n if (!connectable) return { status: \"review\", candidateUrls: tiles.map((tile) => tile.url) }\n return {\n status: \"ready\",\n objectId: tileId,\n sourceUrl: tiles[0]?.url ?? null,\n sources: tiles.map((tile) => ({\n url: tile.url,\n role: `tile-${String(tile.index).padStart(2, \"0\")}`,\n })),\n metadata: {\n tileKind: set.kind,\n ...(set.tile_rules ? { tileRules: set.tile_rules } : {}),\n },\n }\n } catch (err) {\n if (err instanceof PixelLabError && err.status === 423) return { status: \"processing\" }\n throw err\n }\n }\n\n async selectCandidate(\n jobId: string,\n index: number,\n commonTag?: string,\n generator?: Generator,\n ): Promise<{ objectId: string; sourceUrl: string | null }> {\n // A tiles variation is already a finished image at a stable URL — there is\n // no frame to promote and no new account object to create. The identity we\n // record is the job plus the index, which is what actually reproduces it.\n if (generator === \"tiles\") {\n const set = await this.client.getTilesPro(jobId)\n const url = tilesInIndexOrder(set.storage_urls)[index]?.url\n if (!url) throw new Error(`tiles job ${jobId} has no variation at index ${index}`)\n return { objectId: `${jobId}#${index}`, sourceUrl: url }\n }\n const promoted = await this.client.selectFrames(jobId, [index], commonTag)\n const objectId = promoted.created_object_ids?.[0]\n if (!objectId) {\n // The review parent is transient; recording its id would leave a mapping\n // that breaks once the parent is emptied. Fail loudly instead.\n throw new Error(`select-frames returned no created_object_ids for job ${jobId}`)\n }\n const obj = await this.client.getObject(objectId).catch(() => null)\n return { objectId, sourceUrl: firstUrl(obj?.rotation_urls) ?? obj?.preview_url ?? null }\n }\n\n async download(url: string): Promise<Buffer> {\n if (url.startsWith(\"file://\")) return readFileSync(url.slice(\"file://\".length))\n return this.client.download(url)\n }\n\n async balance(): Promise<BalanceInfo> {\n const b = await this.client.balance()\n return { unit: \"generations\", remaining: b.generations, total: b.total, plan: b.plan }\n }\n\n async setTags(objectId: string, tags: string[]): Promise<void> {\n await this.client.setTags(objectId, tags.slice(0, 20))\n }\n\n async *list(): AsyncGenerator<RemoteAsset> {\n for await (const obj of this.client.iterateObjects(100)) {\n yield {\n id: obj.id,\n prompt: obj.prompt ?? \"\",\n width: obj.size.width,\n height: obj.size.height,\n createdAt: obj.created_at,\n previewUrl: obj.preview_url ?? null,\n tags: obj.tags ?? [],\n status: obj.status ?? \"unknown\",\n }\n }\n }\n\n async delete(assetId: string): Promise<void> {\n await this.client.deleteObject(assetId)\n }\n}\n\nfunction requirePixelLabOption(\n name: string,\n value: string | undefined,\n allowed: readonly string[],\n): void {\n if (value != null && !allowed.includes(value)) {\n throw new Error(`PixelLab map ${name} must be one of: ${allowed.join(\", \")}`)\n }\n}\n\n/**\n * `storage_urls` is an object keyed `tile_0`, `tile_1`, ... — JSON object order\n * is not something to rely on, and a connectable set is sliced by index, so\n * sort numerically rather than taking Object.values() as it comes.\n */\nfunction tilesInIndexOrder(urls: Record<string, string>): Array<{ index: number; url: string }> {\n return Object.entries(urls)\n .map(([key, url]) => ({ index: Number(key.replace(/^tile_/, \"\")), url }))\n .filter((tile) => Number.isFinite(tile.index))\n .sort((a, b) => a.index - b.index)\n}\n\nfunction firstUrl(urls: Record<string, string | null> | null | undefined): string | null {\n if (!urls) return null\n return Object.values(urls).find((u): u is string => typeof u === \"string\") ?? null\n}\n","import type { ResolvedStyleImage } from \"./types.ts\"\nimport { z } from \"zod\"\n\n/**\n * PixelLab REST client.\n *\n * Verified against https://api.pixellab.ai/v2/openapi.json. Every endpoint used\n * here was exercised against a live account before being written, so the shapes\n * are observed rather than assumed.\n *\n * Notably this needs no LLM and no MCP client — it is ordinary HTTP.\n */\n\nconst BASE = process.env.PIXELLAB_API_BASE ?? \"https://api.pixellab.ai/v2\"\n\nexport const MAX_RETRIES = 4\nexport const MAX_DOWNLOAD_BYTES = 64 * 1024 * 1024\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))\n\nexport function shouldRetry(status: number): boolean {\n return status === 429 || status === 408 || status >= 500\n}\n\n/** Exponential backoff with jitter, so parallel workers don't retry in lockstep. */\nexport function backoffMs(attempt: number): number {\n const base = Math.min(1000 * 2 ** attempt, 16_000)\n return base + Math.floor(Math.random() * 400)\n}\n\n/** Supports both Retry-After forms: seconds and an HTTP date. */\nexport function retryAfterMs(value: string | null, now = Date.now()): number | null {\n if (!value) return null\n const seconds = Number(value)\n if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000\n const date = Date.parse(value)\n if (!Number.isFinite(date)) return null\n return Math.max(0, date - now)\n}\n\nexport interface Balance {\n usd: number\n generations: number\n total: number\n plan: string\n}\n\nexport interface PixelLabObject {\n id: string\n name: string | null\n prompt: string\n size: { width: number; height: number }\n directions: number\n created_at: string\n view: string | null\n preview_url?: string | null\n rotation_urls?: Record<string, string | null> | null\n /** Populated only while status === \"review\". Index order is what select-frames expects. */\n frame_urls?: string[] | null\n tags: string[]\n status: string | null\n progress_percent?: number | null\n eta_seconds?: number | null\n}\n\n/**\n * A tiles-pro job. Unlike an object or a map object there is no `status`\n * field: GET /tiles-pro/{id} answers 423 while the set is still drawing and\n * 200 with `storage_urls` once it is done, so the HTTP code IS the status.\n */\nexport interface TilesPro {\n /** Keyed `tile_0`, `tile_1`, ... Index order is load-bearing for a\n * connectable set (`tile_feature`), where a consumer slices by index. */\n storage_urls: Record<string, string>\n kind: string | null\n tile_rules?: Record<string, unknown> | null\n}\n\nexport interface MapObject {\n object_id: string\n status: string\n description: string | null\n width: number | null\n height: number | null\n download_url: string | null\n}\n\nconst BalanceResponseSchema = z\n .object({\n credits: z.object({ usd: z.number() }).passthrough(),\n subscription: z\n .object({\n generations: z.number(),\n total: z.number(),\n plan: z.string().nullable().optional(),\n })\n .passthrough(),\n })\n .passthrough()\n\nconst ObjectSubmitSchema = z\n .object({\n background_job_id: z.string().min(1),\n object_id: z.string().min(1),\n status: z.string().default(\"queued\"),\n n_frames: z.number().int().min(0),\n })\n .passthrough()\nconst MapSubmitSchema = z\n .object({\n background_job_id: z.string().min(1),\n object_id: z.string().min(1),\n status: z.string().default(\"processing\"),\n })\n .passthrough()\nconst TilesSubmitSchema = z\n .object({\n tile_id: z.string().min(1),\n background_job_id: z.string().min(1),\n status: z.literal(\"processing\").default(\"processing\"),\n })\n .passthrough()\nconst TilesProSchema = z\n .object({\n storage_urls: z.record(z.string()),\n kind: z.string().nullable().default(null),\n tile_rules: z.record(z.unknown()).nullable().optional(),\n })\n .passthrough()\nconst PixelLabObjectSchema = z\n .object({\n id: z.string().min(1),\n name: z.string().nullable().default(null),\n prompt: z.string().default(\"\"),\n size: z.object({ width: z.number().int().positive(), height: z.number().int().positive() }),\n directions: z.number().default(0),\n created_at: z.string(),\n view: z.string().nullable().default(null),\n preview_url: z.string().nullable().optional(),\n rotation_urls: z.record(z.string().nullable()).nullable().optional(),\n frame_urls: z.array(z.string()).nullable().optional(),\n tags: z.array(z.string()).default([]),\n status: z.string().nullable().default(null),\n progress_percent: z.number().nullable().optional(),\n eta_seconds: z.number().nullable().optional(),\n })\n .passthrough()\nconst MapObjectSchema = z\n .object({\n object_id: z.string().min(1),\n status: z.string(),\n description: z.string().nullable().default(null),\n width: z.number().nullable().default(null),\n height: z.number().nullable().default(null),\n download_url: z.string().nullable().default(null),\n })\n .passthrough()\nconst ObjectListSchema = z\n .object({ objects: z.array(PixelLabObjectSchema), total: z.number().int().min(0) })\n .passthrough()\nconst PixfluxResponseSchema = z\n .object({ image: z.object({ base64: z.string().min(1) }).passthrough(), usage: z.unknown().optional() })\n .passthrough()\nconst SelectFramesSchema = z.object({ created_object_ids: z.array(z.string()) }).passthrough()\n\nfunction validateResponse<S extends z.ZodTypeAny>(\n schema: S,\n raw: unknown,\n operation: string,\n): z.output<S> {\n const parsed = schema.safeParse(raw)\n if (parsed.success) return parsed.data\n const issues = parsed.error.issues\n .slice(0, 4)\n .map((i) => `${i.path.join(\".\") || \"response\"}: ${i.message}`)\n .join(\"; \")\n throw new Error(`Invalid PixelLab response for ${operation}: ${issues}`)\n}\n\nexport class PixelLabError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly body: string,\n ) {\n super(message)\n this.name = \"PixelLabError\"\n }\n}\n\nexport class PixelLabClient {\n constructor(\n private readonly apiKey: string,\n private readonly timeoutMs = 120_000,\n ) {\n if (!apiKey) throw new Error(\"PIXELLAB_API_KEY is required\")\n }\n\n /**\n * Retries only what is safe to retry: transport failures, 429, and 5xx.\n * A 4xx other than 429 is a bad request and retrying it just wastes time.\n *\n * POSTs that create objects are included, which is a deliberate trade: the\n * failure mode of not retrying (a dropped asset in a 65-item run) is more\n * common than the failure mode of retrying (a duplicate object), and a\n * duplicate is visible and free to delete whereas a silent gap is neither.\n */\n private async request<T>(path: string, init?: RequestInit, attempt = 0): Promise<T> {\n const auth = this.apiKey.startsWith(\"Bearer \") ? this.apiKey : `Bearer ${this.apiKey}`\n let res: Response\n try {\n res = await fetch(`${BASE}${path}`, {\n ...init,\n signal: init?.signal ?? AbortSignal.timeout(this.timeoutMs),\n headers: {\n Authorization: auth,\n \"Content-Type\": \"application/json\",\n ...(init?.headers ?? {}),\n },\n })\n } catch (err) {\n if (attempt < MAX_RETRIES) {\n await sleep(backoffMs(attempt))\n return this.request<T>(path, init, attempt + 1)\n }\n throw err\n }\n\n if (!res.ok && shouldRetry(res.status) && attempt < MAX_RETRIES) {\n // Honour Retry-After when the server sends one; it knows better than we do.\n const waitMs = retryAfterMs(res.headers.get(\"retry-after\")) ?? backoffMs(attempt)\n await sleep(waitMs)\n return this.request<T>(path, init, attempt + 1)\n }\n\n const text = await res.text()\n if (!res.ok) {\n throw new PixelLabError(`${init?.method ?? \"GET\"} ${path} → ${res.status}`, res.status, text)\n }\n if (!text) return {} as T\n try {\n return JSON.parse(text) as T\n } catch {\n throw new Error(`${init?.method ?? \"GET\"} ${path} returned invalid JSON`)\n }\n }\n\n async balance(): Promise<Balance> {\n const raw = validateResponse(BalanceResponseSchema, await this.request<unknown>(\"/balance\"), \"balance\")\n return {\n usd: raw.credits?.usd ?? 0,\n generations: raw.subscription?.generations ?? 0,\n total: raw.subscription?.total ?? 0,\n plan: raw.subscription?.plan ?? \"unknown\",\n }\n }\n\n /**\n * Square objects that persist indefinitely.\n *\n * `size` and `styleImages` are mutually exclusive at the API level: when style\n * images are supplied the largest one dictates the output size. So style\n * references must already be at the target resolution — a 128px reference\n * silently produces 128px output and a different candidate count.\n */\n async create1Direction(args: {\n description: string\n size?: number\n view?: string\n styleImages?: ResolvedStyleImage[]\n itemDescriptions?: string[]\n }): Promise<{ object_id: string; status: string; n_frames: number }> {\n const body: Record<string, unknown> = { description: args.description }\n if (args.styleImages?.length) {\n body.style_images = args.styleImages.map(({ base64, format }) => ({\n type: \"base64\",\n base64,\n format,\n }))\n } else if (args.size != null) {\n body.size = args.size\n }\n if (args.view) body.view = args.view\n if (args.itemDescriptions?.length) body.item_descriptions = args.itemDescriptions\n const raw = await this.request<unknown>(\"/create-1-direction-object\", {\n method: \"POST\",\n body: JSON.stringify(body),\n })\n const parsed = validateResponse(ObjectSubmitSchema, raw, \"create-1-direction-object\")\n return parsed\n }\n\n /**\n * Arbitrary width x height. Returns a single result — no selection step.\n *\n * These AUTO-DELETE AFTER 8 HOURS, so `fetch` must run in the same session as\n * `submit`. The pipeline warns when a map-object entry is older than that.\n */\n async createMapObject(args: {\n description: string\n width: number\n height: number\n view?: string\n outline?: string\n shading?: string\n detail?: string\n seed?: number\n }): Promise<{ object_id: string; status: string }> {\n const body: Record<string, unknown> = {\n description: args.description,\n image_size: { width: args.width, height: args.height },\n }\n if (args.view) body.view = args.view\n if (args.outline) body.outline = args.outline\n if (args.shading) body.shading = args.shading\n if (args.detail) body.detail = args.detail\n if (args.seed != null) body.seed = args.seed\n return validateResponse(\n MapSubmitSchema,\n await this.request<unknown>(\"/map-objects\", { method: \"POST\", body: JSON.stringify(body) }),\n \"create map object\",\n )\n }\n\n /**\n * Draws a whole tile set in one call — many variations, or a connectable\n * set when `tileFeature` is given.\n *\n * `styleImages` here is NOT the shape `create-1-direction-object` uses.\n * TilesProStyleImage is flat — `{base64, width, height}`, all three\n * required — where 1dir wants `{type, base64, format}`. Confirmed against\n * the OpenAPI schema; sending 1dir's shape is rejected as an extra field.\n *\n * Passing style images also makes the API ignore `tileType` and `tileView`\n * and copy the reference's tile geometry instead.\n */\n async createTilesPro(args: {\n description: string\n tileSize?: number\n tileType?: string\n tileView?: string\n tileFeature?: string\n outlineMode?: string\n seed?: number\n styleImages?: { base64: string; width: number; height: number }[]\n }): Promise<{ tile_id: string; background_job_id: string; status: string }> {\n const body: Record<string, unknown> = { description: args.description }\n if (args.tileSize != null) body.tile_size = args.tileSize\n if (args.tileType) body.tile_type = args.tileType\n if (args.tileView) body.tile_view = args.tileView\n if (args.tileFeature) body.tile_feature = args.tileFeature\n if (args.outlineMode) body.outline_mode = args.outlineMode\n if (args.seed != null) body.seed = args.seed\n if (args.styleImages?.length) body.style_images = args.styleImages\n return validateResponse(\n TilesSubmitSchema,\n await this.request<unknown>(\"/create-tiles-pro\", { method: \"POST\", body: JSON.stringify(body) }),\n \"create tiles\",\n )\n }\n\n /** Throws PixelLabError(423) while the set is still drawing — see TilesPro. */\n async getTilesPro(tileId: string): Promise<TilesPro> {\n return validateResponse(\n TilesProSchema,\n await this.request<unknown>(`/tiles-pro/${tileId}`),\n \"get tiles\",\n )\n }\n\n /**\n * Synchronous single-image generation. Returns the PNG inline rather than a\n * job id, and is the only endpoint that honours a forced palette —\n * `color_image` on /map-objects returns a 500 whatever the payload shape.\n */\n async createImagePixflux(args: {\n description: string\n width: number\n height: number\n noBackground?: boolean\n paletteSwatchBase64?: string\n seed?: number\n }): Promise<{ png: Buffer; usage: unknown }> {\n const body: Record<string, unknown> = {\n description: args.description,\n image_size: { width: args.width, height: args.height },\n no_background: args.noBackground ?? true,\n }\n if (args.paletteSwatchBase64) {\n body.color_image = { type: \"base64\", base64: args.paletteSwatchBase64, format: \"png\" }\n }\n if (args.seed != null) body.seed = args.seed\n\n const res = validateResponse(\n PixfluxResponseSchema,\n await this.request<unknown>(\"/create-image-pixflux\", {\n method: \"POST\",\n body: JSON.stringify(body),\n }),\n \"create pixflux image\",\n )\n const b64 = res.image.base64\n return { png: Buffer.from(b64, \"base64\"), usage: res.usage }\n }\n\n async getObject(objectId: string): Promise<PixelLabObject> {\n return validateResponse(\n PixelLabObjectSchema,\n await this.request<unknown>(`/objects/${objectId}`),\n \"get object\",\n )\n }\n\n async getMapObject(objectId: string): Promise<MapObject> {\n return validateResponse(\n MapObjectSchema,\n await this.request<unknown>(`/map-objects/${objectId}`),\n \"get map object\",\n )\n }\n\n async listObjects(limit = 50, offset = 0): Promise<{ objects: PixelLabObject[]; total: number }> {\n return validateResponse(\n ObjectListSchema,\n await this.request<unknown>(`/objects?limit=${limit}&offset=${offset}`),\n \"list objects\",\n )\n }\n\n /** Walks the whole account. Used by `adopt` to reconcile orphaned objects. */\n async *iterateObjects(pageSize = 100): AsyncGenerator<PixelLabObject> {\n let offset = 0\n for (;;) {\n const page = await this.listObjects(pageSize, offset)\n for (const obj of page.objects) yield obj\n offset += page.objects.length\n if (page.objects.length === 0 || offset >= page.total) return\n }\n }\n\n /**\n * Promotes chosen candidates to standalone objects, each with its own id.\n * The review parent survives until nothing is left in it, so the returned\n * `created_object_ids` — not the parent id — is what should be recorded.\n */\n async selectFrames(\n objectId: string,\n indices: number[],\n commonTag?: string,\n ): Promise<{ created_object_ids?: string[] }> {\n const raw = await this.request<unknown>(`/objects/${objectId}/select-frames`, {\n method: \"POST\",\n body: JSON.stringify(commonTag ? { indices, common_tag: commonTag } : { indices }),\n })\n return validateResponse(SelectFramesSchema, raw, \"select frames\")\n }\n\n /** Irreversible. Only reached via `purge`, behind an explicit confirmation. */\n deleteObject(objectId: string): Promise<unknown> {\n return this.request(`/objects/${objectId}`, { method: \"DELETE\" })\n }\n\n dismissReview(objectId: string): Promise<unknown> {\n return this.request(`/objects/${objectId}/dismiss-review`, { method: \"POST\" })\n }\n\n /** Free and synchronous. Replaces the full tag set — include tags you want to keep. */\n setTags(objectId: string, tags: string[]): Promise<unknown> {\n return this.request(`/objects/${objectId}/tags`, { method: \"PATCH\", body: JSON.stringify({ tags }) })\n }\n\n /** Storage URLs are public; no auth header, and sending one can break the CDN request. */\n async download(url: string): Promise<Buffer> {\n const res = await fetch(url, { signal: AbortSignal.timeout(this.timeoutMs) })\n if (!res.ok) throw new PixelLabError(`download ${url} → ${res.status}`, res.status, \"\")\n const declared = Number(res.headers.get(\"content-length\"))\n if (Number.isFinite(declared) && declared > MAX_DOWNLOAD_BYTES) {\n throw new Error(`download ${url} exceeds the ${MAX_DOWNLOAD_BYTES}-byte safety limit`)\n }\n const buf = Buffer.from(await res.arrayBuffer())\n if (buf.length > MAX_DOWNLOAD_BYTES) {\n throw new Error(`download ${url} exceeds the ${MAX_DOWNLOAD_BYTES}-byte safety limit`)\n }\n return buf\n }\n}\n\nexport function clientFromEnv(): PixelLabClient {\n const key = process.env.PIXELLAB_API_KEY\n if (!key) {\n throw new Error(\n \"PIXELLAB_API_KEY is not set.\\n\" +\n \"Looked in the environment, and in .env.local / .env beside the manifest and in the current directory.\",\n )\n }\n return new PixelLabClient(key)\n}\n","import { z } from \"zod\"\n\nconst MediaTypeSchema = z.enum([\"image/png\", \"image/gif\"])\n\n/**\n * Which provider capability produces the asset. The choice is mostly about cost,\n * and the gap is enormous — all figures measured against a live account.\n *\n * map POST /map-objects — THE DEFAULT.\n * A flat 1 generation at any size. Purpose-built for standalone props\n * with transparent backgrounds, which is what an icon or a prop is.\n * Arbitrary width x height. Returns exactly one result, so there is no\n * selection step: if you dislike it, re-roll for 1 more.\n *\n * 1dir POST /create-1-direction-object — 20-40 generations.\n * The single-facing sibling of create-8-direction-object, meant for\n * objects you may later want rotations or animations of. Square only.\n * Returns 4-64 candidates for its one fixed price, which is genuinely\n * useful when you want to compare options side by side — but at 40x the\n * cost of a map object, re-rolling a map object forty times is the same\n * money. Reach for this when you need rotations, or when the extra\n * rendering detail is worth 40x.\n *\n * Rule of thumb: if the asset is a standalone image and you are not going to\n * animate or rotate it, `map` is the right call. Generating 65 icons costs 65\n * generations that way and 2,600 the other.\n *\n * Not yet implemented, but measured and worth knowing (see README):\n * POST /create-image-pixflux also costs 1 generation, returns the image\n * INLINE with no polling, and accepts `color_image` — a forced palette that\n * constrains output to exact hex values. Verified: a four-colour Game Boy\n * swatch produced output containing precisely those four colours. The same\n * parameter on /map-objects returns a 500, so the palette lock is\n * pixflux-only. Its rendering is flatter than 1dir's.\n */\nexport const GeneratorSchema = z.enum([\"1dir\", \"map\", \"pixflux\", \"tiles\", \"animation\", \"frames\"])\nexport type Generator = z.infer<typeof GeneratorSchema>\n\nexport const GridConfidenceSchema = z.enum([\"low\", \"medium\", \"high\"])\nexport type GridConfidence = z.infer<typeof GridConfidenceSchema>\n\nexport const RevisionModeSchema = z.enum([\"image-to-image\", \"inpaint\", \"outpaint\"])\nexport type RevisionMode = z.infer<typeof RevisionModeSchema>\n\n/** A decoded style reference ready for a provider-specific request body. */\nexport interface ResolvedStyleImage {\n base64: string\n width: number\n height: number\n format: \"png\" | \"jpeg\"\n}\n\n/**\n * `tiles` is the odd one out: the unit of work is a *set*, not a sprite.\n *\n * POST /create-tiles-pro draws tile shape outlines and fills them, returning\n * many variations from one call. Independent variations land in the same\n * review-then-pick flow as `1dir`; connectable features are structural sets\n * and every returned storage URL is retained. There is no select-frames step\n * to run for either form.\n *\n * Two properties make it worth a generator of its own rather than a flag on\n * `1dir`:\n *\n * - **Style mode overrides geometry.** Passing `styleImages` makes the API\n * copy tile shape and dimensions from the reference and ignore\n * `tileType`/`tileView` entirely. For an existing tileset that is the\n * point: it is the only way to land new art on the same ground plane as\n * the tiles already in the sheet.\n * - **`tileFeature` generates connectable sets.** `\"tileset\"` returns a\n * 16-tile Wang corner set for a terrain transition, `\"roads\"` an\n * 18-configuration path set. Those are structural outputs; a consumer\n * slices them by index, not by eye.\n */\n\n/**\n * Variations a `tiles` call returns. The API derives this from the tile size\n * and how many numbered descriptions the prompt contains; observed at 4 per\n * numbered description for 32px isometric tiles. Clamped so a prompt with no\n * numbering still reports at least one.\n */\nexport function tileVariationCount(descriptions: number): number {\n return Math.max(1, descriptions) * 4\n}\n\n/** Known structural output counts for connectable tile features. */\nexport function tileFeatureOutputCount(feature: string | undefined): number | null {\n if (feature === \"roads\") return 18\n if (feature === \"tileset\") return 16\n // PixelLab does not document a stable count for the building kit. Its\n // returned storage URLs remain authoritative at download time.\n return null\n}\n\n/**\n * Numbered items in a `tiles` prompt. The endpoint documents `\"1). grass\n * 2). dirt\"` as the way to control what comes back, and returns a group of\n * variations per number.\n */\nexport function countNumberedDescriptions(prompt: string): number {\n return (prompt.match(/\\d+\\s*\\)\\s*\\./g) ?? []).length\n}\n\n/** Candidate frames returned per call, derived from size. Extra candidates are free. */\nexport function candidateCount(size: number): number {\n if (size <= 42) return 64\n if (size <= 85) return 16\n if (size <= 170) return 4\n return 1\n}\n\n/**\n * Generation cost per call. Measured against a live account, not inferred.\n *\n * The two generators are priced completely differently, and the gap is wide\n * enough to change which one you should reach for:\n *\n * map FLAT 1 generation, any size. Verified: a 32x36 and a 64x96 map object\n * each cost exactly 1 (balance 4751 → 4750 → 4749). Single result.\n *\n * 1dir 20-40 by canvas tier (1K=20, 2K=25, 4K=40), returning 4-64\n * candidates for that one price.\n *\n * tiles 20-40 on the same canvas tiers as `1dir`, but the canvas is picked\n * from tile size x variation count rather than a single sprite, so a\n * small tile in a large set can still reach the top tier. Reported by\n * the API at submit time; estimated here from the widest canvas the\n * request can produce, which is the honest direction to be wrong in\n * for a `--budget` check.\n *\n * So `1dir` buys candidate variety at 20-40x the price, and `map` buys\n * arbitrary (non-square) dimensions nearly free. For a single-result asset,\n * forty re-rolls of a map object cost the same as one 1dir call.\n */\nexport function generationCost(\n width: number,\n height: number,\n generator: Generator = \"map\",\n): number {\n if (generator === \"map\" || generator === \"pixflux\") return 1\n const px = width * height\n if (px <= 1024) return 20\n if (px <= 2048) return 25\n return 40\n}\n\n/**\n * Cost of one `tiles` call. Same canvas tiers as `1dir`, but the canvas is the\n * sheet the API lays the variations out on, not one tile — so tile size alone\n * under-reads it badly (a 32px tile is 1024px on its own and would always\n * price at the floor).\n *\n * Estimated from tileSize^2 x variations, which is the area actually drawn.\n * `plan` prints this before anything is spent and `--budget` refuses on it, so\n * over-reading is the safe direction: a call that comes in cheaper than\n * budgeted is a pleasant surprise, one that comes in dearer is an overspend.\n */\nexport function tilesCost(tileSize: number, variations: number): number {\n const px = tileSize * tileSize * Math.max(1, variations)\n if (px <= 1024) return 20\n if (px <= 2048) return 25\n return 40\n}\n\nconst StyleImageSchema = z.object({\n /** Path to a PNG/JPEG, relative to the manifest; the active provider validates limits. */\n path: z.string(),\n})\n\nconst HexColorSchema = z.string().regex(/^#?[0-9a-f]{6}$/i, \"expected a six-digit hex colour\")\n\n/** Required derived-art policy for one style's single-image outputs. */\nconst QualityProfileObjectSchema = z\n .object({\n /** Output root for approved refined art, relative to the manifest. */\n outDir: z.string().min(1),\n /** Closed final palette applied after native-grid recovery, without dithering. */\n palette: z.array(HexColorSchema).min(2).max(256),\n /** Minimum Pixel Art Fixer detector confidence accepted by the mechanical gate. */\n minGridConfidence: GridConfidenceSchema.default(\"high\"),\n /** Optional alpha requirement for isolated assets. */\n minTransparency: z.number().min(0).max(1).optional(),\n /** Pixel Art Fixer revision written into the quality record. */\n fixerRevision: z.string().min(1).optional(),\n /** Python executable containing Pixel Art Fixer, relative to the manifest unless absolute. */\n fixerPython: z.string().min(1).optional(),\n /** Playback rate recorded for an ordered frame set. */\n fps: z.number().int().min(1).max(60).optional(),\n })\n .strict()\n\nexport const QualityProfileSchema = QualityProfileObjectSchema\n .refine(\n (profile) =>\n new Set(profile.palette.map((color) => color.replace(/^#/, \"\").toLowerCase())).size ===\n profile.palette.length,\n { message: \"quality palette colors must be unique\", path: [\"palette\"] },\n )\n\nexport type QualityProfile = z.infer<typeof QualityProfileSchema>\n\nexport interface ResolvedQualityProfile {\n outFile: string\n palette: string[]\n minGridConfidence: GridConfidence\n minTransparency?: number\n fixerRevision?: string\n /** Absolute local executable path resolved from the manifest. */\n fixerPython?: string\n fps?: number\n}\n\n/** A provider generation whose visual starting point is another manifest asset. */\nexport const RevisionSchema = z\n .object({\n /** What kind of controlled change the provider workflow performs. */\n mode: RevisionModeSchema,\n /** Parent asset id in the same style. */\n from: z.string().min(1),\n /** Manifest-relative black/white PNG. Required only for masked inpainting. */\n mask: z.string().min(1).optional(),\n /** Provider-neutral edit strength. The active adapter must bind it explicitly. */\n strength: z.number().min(0).max(1).optional(),\n })\n .strict()\n .superRefine((revision, context) => {\n if (revision.mode === \"inpaint\" && !revision.mask) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"inpaint revisions require a mask\",\n path: [\"mask\"],\n })\n }\n if (revision.mode !== \"inpaint\" && revision.mask) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${revision.mode} revisions do not accept a mask`,\n path: [\"mask\"],\n })\n }\n })\n\nexport type Revision = z.infer<typeof RevisionSchema>\n\n/** Resolved immutable inputs supplied to a revision-capable provider. */\nexport interface ResolvedRevision {\n mode: RevisionMode\n sourceAssetId: string\n /** Absolute path selected from the parent asset's approved/final output. */\n sourceFile: string\n /** Null keeps planning possible while the parent is not ready. */\n sourceSha256: string | null\n sourceWidth: number | null\n sourceHeight: number | null\n sourceFormat: \"png\" | \"jpeg\" | null\n /** Full parent intent used to prove the dependency is current before spending. */\n sourceSpec: ResolvedSpec\n maskFile?: string\n maskSha256?: string | null\n maskWidth?: number | null\n maskHeight?: number | null\n maskFormat?: \"png\" | \"jpeg\" | null\n strength?: number\n}\n\nconst StyleObjectSchema = z\n .object({\n /** Generation backend for this style. Omit to inherit the manifest default. */\n provider: z.string().min(1).optional(),\n // `map` is the default because it is 20-40x cheaper and correct for any\n // asset that is not going to be rotated or animated.\n generator: GeneratorSchema.default(\"map\"),\n /** Square edge length. The active provider owns its exact limit. */\n size: z.number().int().min(16).max(8192).optional(),\n view: z.string().optional(),\n /** Appended to every asset prompt in this style. Where the look is defined. */\n promptSuffix: z.string().default(\"\"),\n /** Prepended to every asset prompt in this style. */\n promptPrefix: z.string().default(\"\"),\n /** Style reference images. */\n styleImages: z.array(StyleImageSchema).default([]),\n /** Output root for this style, relative to the manifest. */\n outDir: z.string(),\n /** `map` generator only. */\n outline: z.string().optional(),\n shading: z.string().optional(),\n detail: z.string().optional(),\n /**\n * `tiles` generator only. Edge length of one tile, 16-256.\n *\n * Ignored when `styleImages` is set — style mode takes the tile's shape\n * and dimensions from the reference image, which is the whole reason to\n * use it against an existing sheet.\n */\n tileSize: z.number().int().min(16).max(256).optional(),\n /** `tiles` generator only. Defaults to the API's `isometric`. */\n tileType: z\n .enum([\"hex\", \"hex_pointy\", \"isometric\", \"oblique\", \"octagon\", \"square_topdown\"])\n .optional(),\n /** `tiles` generator only. Defaults to the API's `low top-down`. */\n tileView: z.enum([\"top-down\", \"high top-down\", \"low top-down\", \"side\"]).optional(),\n /**\n * `tiles` generator only. Asks for a connectable set instead of\n * independent variations:\n *\n * roads 18-configuration path set\n * tileset 16-tile Wang corner set for a terrain transition — describe\n * the asset as the transition itself (\"fairway grass to rough\n * meadow\"), not as one terrain\n * building floor/wall/doorway construction kit\n *\n * A consumer slices these by index, so the order the API returns them in\n * is load-bearing; do not sort a connectable set by anything else.\n */\n tileFeature: z.enum([\"roads\", \"tileset\", \"building\"]).optional(),\n /**\n * `tiles` generator only. How tile edges are drawn.\n *\n * The API default is `outline`, which draws a dark border around every\n * tile. That is right for tiles meant to read as discrete objects and\n * wrong for ground: laid on a grid, the per-tile borders turn a continuous\n * surface into visible quilting, with a dark seam at every cell edge.\n * `segmentation` omits them and the same set tiles seamlessly.\n *\n * Measured on a fairway-to-rough terrain set — the difference decided\n * whether the art was usable at all, so it is worth setting deliberately\n * rather than inheriting.\n */\n outlineMode: z.enum([\"outline\", \"segmentation\"]).optional(),\n /**\n * `pixflux` only. Whether to strip the generated background.\n *\n * Defaults to true, which is right for the sprites this tool was built\n * for — a prop or an icon wants to sit on whatever is behind it. It is\n * wrong for anything that IS a scene: a cover banner, a splash, a\n * backdrop. The API's own default is false; forcing it true unconditionally\n * meant a full-bleed image came back as a small subject floating in a\n * mostly-empty frame, and prose asking for an \"opaque background\" does not\n * override it.\n */\n noBackground: z.boolean().default(true),\n /** Fixed seed for reproducibility where the endpoint supports it. */\n seed: z.number().int().optional(),\n /**\n * Forced palette, as `#rrggbb` values. `pixflux` only.\n *\n * Unlike prose, this is a hard constraint — the API is handed a swatch\n * image and the output is limited to those colours. Verified: a four-colour\n * Game Boy palette produced output containing exactly those four values.\n * Prose asking for the same thing does not reliably hold, which is why the\n * map-generated monochrome sets came back with a yellow star and a brown\n * chocolate bar.\n */\n palette: z\n .array(HexColorSchema)\n .default([]),\n /** Fail-closed native-grid, palette, and human-approval policy for derived art. */\n quality: QualityProfileSchema.optional(),\n /**\n * Composites this style's assets into declared cells of a sheet, rather\n * than letting `pack` derive a layout. Use it when the atlas coordinates\n * are already load-bearing somewhere else — a tile engine naming tiles by\n * cell, or saved data storing cell indices — since `pack`'s id-sorted grid\n * moves every position when an asset is added or renamed.\n *\n * Assets in a mounted style declare their own `cell`; ones that do not are\n * left out of the sheet.\n */\n mount: z\n .object({\n /**\n * Existing sheet to composite into, relative to the manifest. Every\n * pixel outside a declared cell survives byte-for-byte, so a\n * hand-authored sheet can be part generated and part drawn. Omit to\n * start from transparent.\n */\n base: z.string().optional(),\n cellWidth: z.number().int().positive(),\n cellHeight: z.number().int().positive(),\n /** Where the composited sheet is written, relative to the manifest. */\n out: z.string(),\n })\n .strict()\n .optional(),\n /** Tags applied to every object generated in this style, for server-side filtering. */\n tags: z.array(z.string()).default([]),\n /** Adapter-owned settings, keyed by provider id. */\n providerOptions: z.record(z.record(z.unknown())).default({}),\n })\n .strict()\n\nexport const StyleSchema = StyleObjectSchema\n /**\n * The API rejects a connectable set combined with style tiles:\n * \"Connectable features (roads/tileset/building) cannot be combined with\n * style tiles\". Catching it here means `plan` reports it for free rather\n * than a `submit` discovering it after the run has started — and the two\n * are individually the best reasons to use this generator, so reaching for\n * both at once is an easy mistake to make.\n */\n .refine((s) => !(s.tileFeature && s.styleImages.length), {\n message:\n \"tileFeature and styleImages cannot be combined — a connectable set \" +\n \"derives its own tile geometry, so remove one or the other\",\n path: [\"tileFeature\"],\n })\n .superRefine((style, ctx) => {\n if (style.quality && (style.generator === \"tiles\" || style.generator === \"animation\")) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"quality profiles currently support single-image generators only\",\n path: [\"quality\"],\n })\n }\n })\n\n/**\n * Hand-authored child style before inheritance is resolved. Defaults must not\n * run here: an omitted value means \"inherit\", not \"reset to the default\".\n */\nexport const InheritedStyleSchema = StyleObjectSchema.partial()\n .extend({\n extends: z.string().min(1),\n /** Children own their destination; sharing a parent's output is never implicit. */\n outDir: z.string(),\n /** A child may override only part of the inherited final-art policy. */\n quality: QualityProfileObjectSchema.partial().optional(),\n })\n .strict()\n\nexport const StyleInputSchema = z.union([StyleSchema, InheritedStyleSchema])\nexport type StyleInput = z.infer<typeof StyleInputSchema>\n\nexport const AssetSchema = z\n .object({\n /** The subject. Style wrapping comes from the style's prefix/suffix. */\n prompt: z.string(),\n /** Subdirectory under the style's outDir. Optional. */\n category: z.string().optional(),\n /** Overrides the style default. `map` generator only. */\n width: z.number().int().min(16).max(8192).optional(),\n height: z.number().int().min(16).max(8192).optional(),\n /** Overrides the style default. `1dir` generator only. */\n size: z.number().int().min(32).max(256).optional(),\n /** Explicit output path relative to outDir. Media-aware providers may replace its extension. */\n file: z.string().optional(),\n /**\n * Grid cell this asset owns in a mounted style, as [column, row].\n *\n * Declared rather than derived, which is the point of `mount`: the\n * coordinate is a contract with whatever already reads the sheet, so it\n * must not move when the asset set changes. Assets without one are left\n * out of the mounted sheet.\n */\n cell: z.tuple([z.number().int().min(0), z.number().int().min(0)]).optional(),\n /**\n * Path, relative to the manifest, of the art that goes on a mounted\n * sheet — when that is not the raw generated output.\n *\n * `mount` otherwise takes its pixels from the lockfile, which records\n * what the API returned. That is the wrong file whenever the art needs a\n * step pixelkiln does not perform: a palette reduction onto a sheet's\n * closed palette, a hand touch-up, an alignment shift. Without somewhere\n * to say so, the choice is to mount the unprocessed art or to abandon\n * `mount` and composite by hand — and the hand-composited sheet is\n * exactly the unreproducible artifact `mount` exists to replace.\n *\n * An asset with a `source` needs no lockfile entry at all, so art\n * generated outside pixelkiln can still be placed by cell alongside art\n * that wasn't. `prompt` still records what was asked for.\n */\n source: z.string().optional(),\n /** Controlled generation derived from another asset in the same style. */\n revision: RevisionSchema.optional(),\n /**\n * Generated output role to place in `cell` when this asset expands to\n * several files. Omit for ordinary single-output assets. A structural set\n * is otherwise ambiguous and `mount` refuses to guess by taking index zero.\n */\n outputRole: z.string().min(1).optional(),\n tags: z.array(z.string()).default([]),\n /** Restrict this asset to specific styles. Empty means all styles. */\n styles: z.array(z.string()).default([]),\n /**\n * Per-style replacement for `prompt`, keyed by style id.\n *\n * A style can need different wording rather than different styling. A\n * monochrome style is the clear case: prompts that name colours\n * (\"green purple gold\", \"colorful rainbow\") override the palette\n * instruction and survive into the output, while the same prompt is\n * exactly right for a colour style. Editing the shared prompt to suit one\n * style would invalidate every other style's already-generated art.\n */\n promptByStyle: z.record(z.string()).default({}),\n /**\n * Named per-asset values consumed by the active provider's declared\n * bindings. Values are JSON scalars, or a frame-set sequence of scalars;\n * adapters may interpret a string as a manifest-relative uploaded file.\n */\n providerInputs: z\n .record(z.union([\n z.string(),\n z.number().finite(),\n z.boolean(),\n z.array(z.union([z.string(), z.number().finite(), z.boolean()])).min(2).max(64),\n ]))\n .default({}),\n })\n .strict()\n .superRefine((asset, context) => {\n if (asset.source && asset.revision) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"source and revision are mutually exclusive\",\n path: [\"revision\"],\n })\n }\n })\n\nexport const ManifestSchema = z\n .object({\n $schema: z.string().optional(),\n name: z.string(),\n /** Generation backend. Existing manifests remain PixelLab by default. */\n provider: z.string().min(1).default(\"pixellab\"),\n styles: z.record(StyleSchema),\n assets: z.record(AssetSchema),\n })\n .strict()\n\n/** Manifest contract accepted from disk before style inheritance is resolved. */\nexport const ManifestInputSchema = z\n .object({\n $schema: z.string().optional(),\n name: z.string(),\n provider: z.string().min(1).default(\"pixellab\"),\n styles: z.record(StyleInputSchema),\n assets: z.record(AssetSchema),\n })\n .strict()\n\nexport type Manifest = z.infer<typeof ManifestSchema>\nexport type Style = z.infer<typeof StyleSchema>\nexport type Asset = z.infer<typeof AssetSchema>\n\n/**\n * One line of the lockfile: the mapping from a spec to the provider work that\n * satisfies it and the file on disk that came from it. This is the record that\n * did not exist before — without it, generated objects and downloaded files are\n * two unrelated piles.\n */\nexport const LockEntrySchema = z.object({\n styleId: z.string(),\n assetId: z.string(),\n /** sha256 of the resolved spec. Changing a prompt/size/style invalidates it. */\n specHash: z.string(),\n generator: GeneratorSchema,\n /** Connectable tiles must remain multi-output even when polling is resumed later. */\n tileFeature: z.string().nullable().default(null),\n /** The resolved prompt actually sent, kept for auditing and for adopt matching. */\n prompt: z.string(),\n width: z.number().int(),\n height: z.number().int(),\n /** Explicit parent/input lineage for a revision generation. */\n revision: z\n .object({\n mode: RevisionModeSchema,\n sourceAssetId: z.string().min(1),\n sourceSha256: z.string().regex(/^[0-9a-f]{64}$/),\n maskSha256: z.string().regex(/^[0-9a-f]{64}$/).optional(),\n strength: z.number().min(0).max(1).optional(),\n })\n .strict()\n .nullable()\n .default(null),\n\n /**\n * Output hashes owned by the previous generation while its replacement is\n * pending. They authorize replacing only unchanged PixelKiln-owned files.\n */\n supersededOutputs: z\n .array(\n z.object({\n path: z.string(),\n sha256: z.string(),\n role: z.string().optional(),\n mediaType: MediaTypeSchema.optional(),\n }),\n )\n .optional(),\n\n /** Set at submit time, before the request is awaited, so a crash is recoverable. */\n jobId: z.string().nullable().default(null),\n /** For `1dir`: the multi-candidate parent object awaiting selection. */\n reviewObjectId: z.string().nullable().default(null),\n /** The chosen candidate's own object id, once selected. */\n objectId: z.string().nullable().default(null),\n candidateIndex: z.number().int().nullable().default(null),\n\n status: z\n .enum([\n \"pending\",\n \"processing\",\n \"review\",\n \"selected\",\n \"downloaded\",\n \"download-failed\",\n \"failed\",\n ])\n .default(\"pending\"),\n error: z.string().nullable().default(null),\n\n sourceUrl: z.string().nullable().default(null),\n /** Every source in a structural multi-output result, in provider order. */\n sourceUrls: z\n .array(\n z.object({\n url: z.string(),\n role: z.string().optional(),\n mediaType: MediaTypeSchema.optional(),\n }),\n )\n .default([]),\n\n /**\n * Files this entry produced. A plain object generates one; asset kinds that\n * expand into many — an animated character is ~35 spritesheets plus an engine\n * resource — need the list, which is why v1's single `file` became this.\n *\n * `role` labels non-primary artifacts (e.g. \"portrait\", \"spriteframes\") so a\n * consumer can find the one it wants without pattern-matching on paths.\n */\n outputs: z\n .array(\n z.object({\n path: z.string(),\n sha256: z.string(),\n role: z.string().optional(),\n mediaType: MediaTypeSchema.optional(),\n }),\n )\n .default([]),\n\n /**\n * Provider-owned data retained for downstream consumers, namespaced by\n * provider id. PixelLab connectable sets keep their exact `tileRules` here\n * so exporters can map images to adjacency rules.\n */\n providerMetadata: z.record(z.record(z.unknown())).default({}),\n\n submittedAt: z.string().nullable().default(null),\n downloadedAt: z.string().nullable().default(null),\n /** Successful-submission estimate in `costUnit`; may be fractional USD. */\n cost: z.number().finite().nonnegative().default(0),\n /** Unit for `cost`. Defaults preserve pre-unit PixelLab lockfiles. */\n costUnit: z.string().min(1).default(\"generations\"),\n /** Which provider produced this. Absent on entries written before providers. */\n provider: z.string().default(\"pixellab\"),\n})\n\nexport const LockSchema = z.object({\n version: z.literal(2),\n entries: z.record(LockEntrySchema),\n})\n\nexport type LockEntry = z.infer<typeof LockEntrySchema>\nexport type Lock = z.infer<typeof LockSchema>\nexport type LockOutput = LockEntry[\"outputs\"][number]\n\n/**\n * Parses a lockfile, rejecting anything that is not v2.\n *\n * There is deliberately no migration path. Both consuming projects were\n * onboarded after v2 landed, so a v1 file would be a corruption or a\n * hand-edit rather than a legacy artifact — better to fail loudly than to\n * quietly reinterpret it.\n */\nexport function parseLock(raw: unknown): Lock {\n const parsed = LockSchema.safeParse(raw)\n if (parsed.success) return parsed.data\n throw new Error(\n `Lockfile is not valid v2:\\n${parsed.error.issues\n .slice(0, 5)\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\")}`,\n )\n}\n\n/** The file a consumer means when it says \"the asset\" — the first output. */\nexport function primaryOutput(entry: LockEntry): LockOutput | null {\n return entry.outputs.find((o) => !o.role) ?? entry.outputs[0] ?? null\n}\n\n/** Lock entries are keyed `<styleId>/<assetId>`, which makes styles a namespace. */\nexport function lockKey(styleId: string, assetId: string): string {\n return `${styleId}/${assetId}`\n}\n\n/** A manifest entry resolved against its style — everything needed to generate. */\nexport interface ResolvedSpec {\n /** Absolute directory containing the manifest; excluded from the spec hash. */\n root: string\n styleId: string\n assetId: string\n /** Backend whose request semantics and estimate produced this spec. */\n provider: string\n /** Adapter-owned settings selected from the active provider namespace. */\n providerOptions: Record<string, unknown>\n /** Adapter-resolved per-asset inputs. Their stable identity participates in the spec hash. */\n providerInputs?: Record<string, unknown>\n generator: Generator\n prompt: string\n width: number\n height: number\n view: string\n size: number\n styleImagePaths: string[]\n outFile: string\n /** Derived quality output. Excluded from provider request identity and spend. */\n quality?: ResolvedQualityProfile\n /** Provider generation derived from another current manifest asset. */\n revision?: ResolvedRevision\n /**\n * Manifest-relative path of committed art that stands in for generated\n * output; excluded from the spec hash. Set only when the asset declares\n * `source`, which also means it needs no lock entry.\n */\n source?: string\n tags: string[]\n specHash: string\n cost: number\n costUnit: import(\"./provider.ts\").CostUnit\n candidates: number\n outline?: string\n shading?: string\n detail?: string\n seed?: number\n /** Forced palette hex values; empty unless the style sets one. */\n palette: string[]\n /** `pixflux` only — strip the generated background. Defaults to true. */\n noBackground: boolean\n /** `tiles` generator only — see StyleSchema for what each one means. */\n tileSize?: number\n tileType?: string\n tileView?: string\n tileFeature?: string\n outlineMode?: string\n}\n","import { paletteSwatch } from \"../png.ts\"\nimport type {\n BalanceInfo,\n CostEstimate,\n JobState,\n PollContext,\n Provider,\n} from \"../provider.ts\"\nimport type { Generator, ResolvedSpec, ResolvedStyleImage } from \"../types.ts\"\nimport { MediaType, type MediaType as MediaKind } from \"../media.ts\"\n\nconst DEFAULT_BASE_URL = \"https://api.retrodiffusion.ai/v1\"\nconst SOURCE_PROTOCOL = \"retrodiffusion:\"\n\nexport interface RetroDiffusionOptions {\n /** Live style id returned by GET /styles/selector. */\n promptStyle?: string\n /** Candidate images produced by one request. */\n numImages?: number\n /** Override the style's shared noBackground setting. */\n removeBg?: boolean\n /** Animation frame duration accepted by Retro Diffusion. */\n framesDuration?: 4 | 6 | 8 | 10 | 12 | 16\n /** Return a PNG spritesheet instead of the default animated GIF. */\n returnSpritesheet?: boolean\n /** Outside texture description for rd_tile__tileset_advanced. */\n extraPrompt?: string\n /** Ask a still image to tile seamlessly on each axis. */\n tileX?: boolean\n tileY?: boolean\n}\n\ninterface InferenceResult {\n balance_cost?: number\n remaining_balance?: number\n base64_images?: string[]\n output_urls?: string[]\n}\n\ninterface TaskResponse {\n status: \"pending\" | \"running\" | \"succeeded\" | \"failed\"\n result?: InferenceResult | null\n error?: string | { message?: string } | null\n}\n\nclass RetroDiffusionClient {\n constructor(\n private readonly token: string | undefined,\n private readonly baseUrl = DEFAULT_BASE_URL,\n private readonly request: typeof fetch = fetch,\n ) {}\n\n async submit(body: Record<string, unknown>): Promise<string> {\n const response = await this.call(\"/inferences\", { method: \"POST\", body: JSON.stringify(body) })\n const taskId = (response as { task_id?: unknown }).task_id\n if (typeof taskId !== \"string\" || !taskId) {\n throw new Error(\"Retro Diffusion did not return an async task id\")\n }\n return taskId\n }\n\n async quote(body: Record<string, unknown>): Promise<number> {\n const response = await this.call(\"/inferences\", {\n method: \"POST\",\n body: JSON.stringify({ ...body, check_cost: true }),\n })\n const amount = (response as { balance_cost?: unknown }).balance_cost\n if (typeof amount !== \"number\" || !Number.isFinite(amount) || amount < 0) {\n throw new Error(\"Retro Diffusion returned an invalid cost quote\")\n }\n return amount\n }\n\n async task(id: string): Promise<TaskResponse> {\n return (await this.call(`/inferences/tasks/${encodeURIComponent(id)}`)) as TaskResponse\n }\n\n async balance(): Promise<number> {\n const response = await this.call(\"/inferences/credits\")\n const balance = (response as { balance?: unknown }).balance\n if (typeof balance !== \"number\" || !Number.isFinite(balance)) {\n throw new Error(\"Retro Diffusion returned an invalid balance\")\n }\n return balance\n }\n\n private async call(path: string, init: RequestInit = {}): Promise<unknown> {\n if (!this.token) throw new Error(\"RD_API_KEY is not set\")\n const response = await this.request(`${this.baseUrl}${path}`, {\n ...init,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-RD-Token\": this.token,\n ...init.headers,\n },\n })\n const text = await response.text()\n let value: unknown = null\n try {\n value = text ? JSON.parse(text) : null\n } catch {\n value = text\n }\n if (!response.ok) {\n const retry = response.headers.get(\"retry-after\")\n const detail = retroError(value)\n throw new Error(\n `Retro Diffusion request failed (${response.status}): ${detail}` +\n (retry ? `; retry after ${retry}s` : \"\"),\n )\n }\n return value\n }\n}\n\n/** Experimental native pixel-art still, tileset, and animation adapter. */\nexport class RetroDiffusionProvider implements Provider {\n readonly id = \"retrodiffusion\"\n\n constructor(private readonly client: RetroDiffusionClient) {}\n\n static fromEnv(): RetroDiffusionProvider {\n return new RetroDiffusionProvider(new RetroDiffusionClient(process.env.RD_API_KEY))\n }\n\n static forOffline(): RetroDiffusionProvider {\n return new RetroDiffusionProvider(new RetroDiffusionClient(undefined))\n }\n\n static forDownloads(): RetroDiffusionProvider {\n // Ordinary public URLs and cached bytes need no credential. A durable\n // retrodiffusion:// reference resolves a fresh provider result and the\n // client reports a clear RD_API_KEY error only if that fallback is used.\n return new RetroDiffusionProvider(new RetroDiffusionClient(process.env.RD_API_KEY))\n }\n\n supports(generator: Generator): boolean {\n return generator === \"map\" || generator === \"pixflux\" ||\n generator === \"tiles\" || generator === \"animation\"\n }\n\n estimate(spec: ResolvedSpec): CostEstimate {\n const options = retroOptions(spec)\n const style = resolvedPromptStyle(spec, options)\n const count = options.numImages ?? 1\n const pixels = spec.width * spec.height\n let each: number\n if (style.startsWith(\"rd_advanced_animation__\")) {\n each = /__(?:custom_action|subtle_motion)$/.test(style) ? 0.25 : 0.14\n } else if (style.startsWith(\"rd_animation__\")) {\n each = /__(?:any_animation|8_dir_rotation)$/.test(style) ? 0.25 : 0.07\n } else if (/^rd_tile__tileset(?:_advanced)?$/.test(style)) {\n each = 0.1\n } else if (style.startsWith(\"rd_pro__\")) {\n each = 0.18\n } else if (style.startsWith(\"rd_fast__\")) {\n each = Math.max(0.015, (pixels + 100_000) / 6_000_000)\n } else if (isLowResolutionStyle(style)) {\n each = Math.max(0.02, (pixels + 13_700) / 600_000)\n } else {\n each = Math.max(0.025, (pixels + 50_000) / 2_000_000)\n }\n return { unit: \"usd\", amount: roundUsdEstimate(each * count), candidates: count }\n }\n\n validate(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): void {\n const options = retroOptions(spec)\n const promptStyle = resolvedPromptStyle(spec, options)\n const count = options.numImages ?? 1\n const isAnimation = /^(?:rd_animation__|rd_advanced_animation__)/.test(promptStyle)\n const isTile = promptStyle.startsWith(\"rd_tile__\")\n if (\n !promptStyle ||\n (spec.generator === \"animation\" && !isAnimation) ||\n (spec.generator === \"tiles\" && !isTile) ||\n (spec.generator !== \"animation\" && spec.generator !== \"tiles\" && (isAnimation || isTile))\n ) {\n throw new Error(\n `Retro Diffusion style \"${promptStyle}\" does not match generator \"${spec.generator}\"`,\n )\n }\n if (!Number.isInteger(count) || count < 1 || count > 16) {\n throw new Error(\"Retro Diffusion numImages must be a whole number from 1 to 16\")\n }\n if (spec.width < 16 || spec.height < 16 || spec.width > 512 || spec.height > 512) {\n throw new Error(\"Retro Diffusion output dimensions must be between 16 and 512 pixels\")\n }\n if (styleImages.length > 9) {\n throw new Error(\"Retro Diffusion accepts at most 9 reference images\")\n }\n if (spec.generator === \"animation\") {\n if (count !== 1) throw new Error(\"Retro Diffusion animations currently require numImages: 1\")\n validateAnimation(promptStyle, spec, styleImages, options)\n } else if (spec.generator === \"tiles\") {\n validateTile(promptStyle, spec, styleImages, count, options)\n } else if (styleImages.length && !/^(?:rd_pro__|user__)/.test(promptStyle)) {\n throw new Error(\n `Retro Diffusion style \"${promptStyle}\" does not accept reference_images; ` +\n \"use an RD Pro or user style\",\n )\n }\n }\n\n async submit(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): Promise<{ jobId: string }> {\n this.validate(spec, styleImages)\n const options = retroOptions(spec)\n const promptStyle = resolvedPromptStyle(spec, options)\n const animation = spec.generator === \"animation\"\n const tiles = spec.generator === \"tiles\"\n const body: Record<string, unknown> = {\n prompt: spec.prompt,\n prompt_style: promptStyle,\n width: spec.width,\n height: spec.height,\n num_images: options.numImages ?? 1,\n ...(!animation && !tiles ? { remove_bg: options.removeBg ?? spec.noBackground } : {}),\n ...(spec.seed != null ? { seed: spec.seed } : {}),\n ...(animation || tiles\n ? styleImages[0]\n ? { input_image: styleImages[0].base64 }\n : {}\n : styleImages.length\n ? { reference_images: styleImages.map((image) => image.base64) }\n : {}),\n ...(tiles && styleImages[1] ? { extra_input_image: styleImages[1].base64 } : {}),\n ...(tiles && options.extraPrompt ? { extra_prompt: options.extraPrompt } : {}),\n ...(animation && options.framesDuration ? { frames_duration: options.framesDuration } : {}),\n ...(animation && options.returnSpritesheet ? { return_spritesheet: true } : {}),\n ...(!animation && options.tileX != null ? { tile_x: options.tileX } : {}),\n ...(!animation && options.tileY != null ? { tile_y: options.tileY } : {}),\n ...(spec.palette.length\n ? { input_palette: paletteSwatch(spec.palette).toString(\"base64\") }\n : {}),\n }\n const quoted = await this.client.quote(body)\n const estimated = this.estimate(spec).amount\n if (quoted > estimated + 0.000001) {\n throw new Error(\n `Retro Diffusion quoted $${quoted.toFixed(6)}, above the offline estimate ` +\n `$${estimated.toFixed(6)}; no paid request was sent`,\n )\n }\n return {\n jobId: await this.client.submit({ ...body, async: true, upload_outputs: true }),\n }\n }\n\n async poll(jobId: string, generator: Generator, context?: PollContext): Promise<JobState> {\n const task = await this.client.task(jobId)\n if (task.status === \"pending\" || task.status === \"running\") return { status: \"processing\" }\n if (task.status === \"failed\") return { status: \"failed\", error: retroError(task.error) }\n if (task.status !== \"succeeded\") {\n return { status: \"failed\", error: `Retro Diffusion returned unknown task status \"${String(task.status)}\"` }\n }\n\n const options = context?.spec ? retroOptions(context.spec) : {}\n const mediaType = generator === \"animation\" && !options.returnSpritesheet\n ? MediaType.GIF\n : MediaType.PNG\n const sources = resultSources(task.result, mediaType)\n const urls = sources.map((source) => source.url)\n if (!urls.length) return { status: \"failed\", error: \"Retro Diffusion task returned no images\" }\n if (urls.length > 1) return { status: \"review\", candidateUrls: urls }\n const durableSources = sources.map((source, index) => ({\n ...source,\n url: sourceRef(jobId, index, mediaType),\n }))\n return {\n status: \"ready\",\n objectId: `${jobId}#0`,\n sourceUrl: durableSources[0]!.url,\n sources: durableSources,\n metadata: {\n balanceCost: task.result?.balance_cost ?? null,\n remainingBalance: task.result?.remaining_balance ?? null,\n mediaType,\n kind: generator === \"animation\" ? \"animation\" : generator === \"tiles\" ? \"tileset\" : \"image\",\n ...(context?.spec\n ? {\n promptStyle: resolvedPromptStyle(context.spec, options),\n width: context.spec.width,\n height: context.spec.height,\n }\n : {}),\n },\n }\n }\n\n async selectCandidate(\n jobId: string,\n index: number,\n ): Promise<{ objectId: string; sourceUrl: string | null }> {\n const task = await this.client.task(jobId)\n if (task.status !== \"succeeded\") throw new Error(`Retro Diffusion task ${jobId} is not ready`)\n const url = resultSources(task.result, MediaType.PNG)[index]?.url\n if (!url) throw new Error(`Retro Diffusion task ${jobId} has no candidate at index ${index}`)\n return { objectId: `${jobId}#${index}`, sourceUrl: sourceRef(jobId, index, MediaType.PNG) }\n }\n\n async download(url: string): Promise<Buffer> {\n if (url.startsWith(`${SOURCE_PROTOCOL}//`)) {\n const reference = parseSourceRef(url)\n const task = await this.client.task(reference.jobId)\n if (task.status !== \"succeeded\") {\n throw new Error(`Retro Diffusion task ${reference.jobId} is not ready`)\n }\n const source = resultSources(task.result, reference.mediaType)[reference.index]?.url\n if (!source) {\n throw new Error(\n `Retro Diffusion task ${reference.jobId} has no output at index ${reference.index}`,\n )\n }\n return this.downloadResolved(source)\n }\n return this.downloadResolved(url)\n }\n\n private async downloadResolved(url: string): Promise<Buffer> {\n const data = /^data:[^;]+;base64,(.+)$/.exec(url)?.[1]\n if (data) return Buffer.from(data, \"base64\")\n const response = await fetch(url)\n if (!response.ok) throw new Error(`Retro Diffusion download failed (${response.status})`)\n return Buffer.from(await response.arrayBuffer())\n }\n\n async balance(): Promise<BalanceInfo> {\n return { unit: \"usd\", remaining: await this.client.balance() }\n }\n}\n\nfunction sourceRef(jobId: string, index: number, mediaType: MediaKind): string {\n const url = new URL(\"retrodiffusion://output\")\n url.searchParams.set(\"job\", jobId)\n url.searchParams.set(\"index\", String(index))\n url.searchParams.set(\"mediaType\", mediaType)\n return url.href\n}\n\nfunction parseSourceRef(value: string): { jobId: string; index: number; mediaType: MediaKind } {\n const url = new URL(value)\n const jobId = url.searchParams.get(\"job\")\n const index = Number(url.searchParams.get(\"index\"))\n const rawMediaType = url.searchParams.get(\"mediaType\")\n if (\n url.protocol !== SOURCE_PROTOCOL ||\n url.hostname !== \"output\" ||\n !jobId ||\n !Number.isInteger(index) ||\n index < 0 ||\n (rawMediaType !== MediaType.PNG && rawMediaType !== MediaType.GIF)\n ) {\n throw new Error(\"Invalid durable Retro Diffusion source reference\")\n }\n return { jobId, index, mediaType: rawMediaType }\n}\n\nfunction retroOptions(spec: ResolvedSpec): RetroDiffusionOptions {\n return spec.providerOptions as RetroDiffusionOptions\n}\n\nfunction resultSources(\n result: InferenceResult | null | undefined,\n mediaType: MediaKind,\n): Array<{ url: string; mediaType: MediaKind }> {\n const hosted = (result?.output_urls ?? [])\n .filter((url): url is string => typeof url === \"string\" && url.length > 0)\n .map((url) => ({ url, mediaType }))\n if (hosted.length) return hosted\n return (result?.base64_images ?? [])\n .filter((data): data is string => typeof data === \"string\" && data.length > 0)\n .map((data) => ({\n url: `data:${mediaType};base64,${data}`,\n mediaType,\n }))\n}\n\nfunction resolvedPromptStyle(spec: ResolvedSpec, options: RetroDiffusionOptions): string {\n return options.promptStyle ??\n (spec.generator === \"animation\"\n ? \"rd_animation__any_animation\"\n : spec.generator === \"tiles\"\n ? \"rd_tile__tileset\"\n : \"rd_plus__default\")\n}\n\nfunction validateAnimation(\n style: string,\n spec: ResolvedSpec,\n styleImages: ResolvedStyleImage[],\n options: RetroDiffusionOptions,\n): void {\n if (spec.width !== spec.height) throw new Error(\"Retro Diffusion animations must be square\")\n if (style.startsWith(\"rd_advanced_animation__\")) {\n if (styleImages.length !== 1) {\n throw new Error(`Retro Diffusion advanced animation style \"${style}\" requires one input image`)\n }\n if (spec.width < 32 || spec.width > 256) {\n throw new Error(\"Retro Diffusion advanced animations require dimensions from 32 to 256 pixels\")\n }\n } else if (styleImages.length > 1) {\n throw new Error(\"Retro Diffusion prompt animations accept at most one input image\")\n }\n const exact = style.includes(\"four_angle_walking\") ? 48\n : style.endsWith(\"__small_sprites\") ? 32\n : style.endsWith(\"__any_animation\") ? 64\n : style.endsWith(\"__big_animation\") ? 128\n : style.endsWith(\"__8_dir_rotation\") ? 80\n : null\n if (exact && spec.width !== exact) {\n throw new Error(`Retro Diffusion style \"${style}\" requires ${exact}x${exact} dimensions`)\n }\n if (style.endsWith(\"__vfx\") && (spec.width < 24 || spec.width > 96)) {\n throw new Error(\"Retro Diffusion VFX animations require dimensions from 24 to 96 pixels\")\n }\n if (options.framesDuration != null && ![4, 6, 8, 10, 12, 16].includes(options.framesDuration)) {\n throw new Error(\"Retro Diffusion framesDuration must be 4, 6, 8, 10, 12, or 16\")\n }\n}\n\nfunction validateTile(\n style: string,\n spec: ResolvedSpec,\n styleImages: ResolvedStyleImage[],\n count: number,\n options: RetroDiffusionOptions,\n): void {\n if (spec.width !== spec.height) throw new Error(\"Retro Diffusion tiles must be square\")\n const size = spec.width\n if (/^rd_tile__tileset(?:_advanced)?$/.test(style)) {\n if (size < 16 || size > 32) throw new Error(\"Retro Diffusion tilesets require 16–32px tiles\")\n if (count !== 1) throw new Error(\"Retro Diffusion tilesets require numImages: 1\")\n } else if (style === \"rd_tile__single_tile\" && (size < 16 || size > 64)) {\n throw new Error(\"Retro Diffusion single tiles require dimensions from 16 to 64 pixels\")\n } else if (style === \"rd_tile__tile_variation\") {\n if (size < 16 || size > 128) throw new Error(\"Retro Diffusion tile variations require 16–128px tiles\")\n if (styleImages.length !== 1) throw new Error(\"Retro Diffusion tile variations require one input image\")\n } else if (style === \"rd_tile__tile_object\" && (size < 16 || size > 96)) {\n throw new Error(\"Retro Diffusion tile objects require dimensions from 16 to 96 pixels\")\n } else if (style === \"rd_tile__scene_object\" && (size < 64 || size > 384)) {\n throw new Error(\"Retro Diffusion tile scene objects require dimensions from 64 to 384 pixels\")\n }\n if (style === \"rd_tile__tileset\" && styleImages.length > 1) {\n throw new Error(\"Retro Diffusion basic tilesets accept at most one input image\")\n }\n if (style === \"rd_tile__tileset_advanced\") {\n if (styleImages.length > 2) throw new Error(\"Retro Diffusion advanced tilesets accept at most two input images\")\n if (!options.extraPrompt && styleImages.length < 2) {\n throw new Error(\"Retro Diffusion advanced tilesets require extraPrompt or a second input image\")\n }\n }\n}\n\nfunction isLowResolutionStyle(style: string): boolean {\n return /(?:^|__)(?:mc_|low_res|classic|skill_icon|topdown_item)/.test(style)\n}\n\nfunction roundUsdEstimate(value: number): number {\n // Live quotes may round a formula result up to the nearest $0.001. Planning\n // must be conservative or submit() will correctly reject that rounded quote\n // as higher than the offline estimate.\n return Math.ceil((value - 1e-9) * 1_000) / 1_000\n}\n\nfunction retroError(value: unknown): string {\n if (typeof value === \"string\") return value || \"unknown error\"\n if (!value || typeof value !== \"object\") return \"unknown error\"\n const record = value as Record<string, unknown>\n if (typeof record.message === \"string\") return record.message\n if (typeof record.detail === \"string\") return record.detail\n if (Array.isArray(record.detail)) {\n const details = record.detail\n .map((item) => {\n if (!item || typeof item !== \"object\") return String(item)\n const detail = item as Record<string, unknown>\n return typeof detail.msg === \"string\" ? detail.msg : JSON.stringify(item)\n })\n .filter(Boolean)\n if (details.length) return details.join(\"; \")\n }\n if (record.detail && typeof record.detail === \"object\") {\n const message = (record.detail as Record<string, unknown>).message\n if (typeof message === \"string\") return message\n }\n return JSON.stringify(value)\n}\n","import { MAX_DOWNLOAD_BYTES } from \"../client.ts\"\nimport { MediaType } from \"../media.ts\"\nimport type {\n CandidateSelection,\n CostEstimate,\n JobState,\n PollContext,\n Provider,\n ProviderMetadata,\n ProviderSubmission,\n RateLimit,\n} from \"../provider.ts\"\nimport type { Generator, ResolvedSpec, ResolvedStyleImage } from \"../types.ts\"\n\nconst DEFAULT_BASE_URL = \"https://api.cloud.scenario.com/v1\"\nconst SOURCE_PROTOCOL = \"scenario:\"\nconst PROTECTED_PARAMETERS = new Set([\n \"dryRun\",\n \"height\",\n \"maxComputeUnits\",\n \"numOutputs\",\n \"projectId\",\n \"prompt\",\n \"seed\",\n \"width\",\n])\n\nexport interface ScenarioOptions {\n /** Scenario model passed to POST /generate/custom/{modelId}. */\n modelId: string\n /** Conservative per-asset ceiling used by offline planning and live preflight. */\n maxComputeUnits: number\n /** Number of images requested. More than one enters PixelKiln review. */\n numOutputs?: number\n /** Optional Scenario project ownership/routing id. */\n projectId?: string\n /** Additional model-specific JSON inputs that cannot replace PixelKiln-owned intent. */\n parameters?: Record<string, unknown>\n}\n\ninterface ScenarioQuote {\n total: number\n creativeUnitsCost: number\n costDetails: Record<string, number>\n ipDetectionCost: number\n}\n\ninterface ScenarioJob {\n jobId: string\n status: string\n progress?: number\n metadata?: {\n assetIds?: unknown\n error?: unknown\n }\n billing?: {\n cuCost?: unknown\n cuDiscount?: unknown\n cuCostDetails?: unknown\n }\n}\n\ninterface ScenarioAsset {\n id: string\n url: string\n originalFileUrl?: string\n originalMimeType?: string\n outputIndex: number\n}\n\nclass ScenarioClient {\n constructor(\n private readonly apiKey: string | undefined,\n private readonly apiSecret: string | undefined,\n private readonly baseUrl = DEFAULT_BASE_URL,\n private readonly request: typeof fetch = fetch,\n ) {}\n\n async quote(modelId: string, body: Record<string, unknown>, projectId?: string): Promise<ScenarioQuote> {\n const response = await this.call(\n `/generate/custom/${encodeURIComponent(modelId)}`,\n { method: \"POST\", body: JSON.stringify(body) },\n { dryRun: \"true\", projectId },\n )\n const creativeUnitsCost = finiteNonnegative(\n (response as { creativeUnitsCost?: unknown })?.creativeUnitsCost,\n \"Scenario dry run returned an invalid creativeUnitsCost\",\n )\n const costDetails = numericRecord((response as { costDetails?: unknown })?.costDetails)\n const ipDetectionCost = optionalFiniteNonnegative(\n (response as { ipDetection?: { creativeUnitsCharged?: unknown } })?.ipDetection\n ?.creativeUnitsCharged,\n \"Scenario dry run returned an invalid IP-detection cost\",\n )\n return {\n total: creativeUnitsCost + ipDetectionCost,\n creativeUnitsCost,\n costDetails,\n ipDetectionCost,\n }\n }\n\n async submit(\n modelId: string,\n body: Record<string, unknown>,\n projectId?: string,\n ): Promise<string> {\n const response = await this.call(\n `/generate/custom/${encodeURIComponent(modelId)}`,\n { method: \"POST\", body: JSON.stringify(body) },\n { projectId },\n )\n const job = (response as { job?: unknown })?.job\n const jobId = readJobId(job)\n if (!jobId) throw new Error(\"Scenario did not return an async job id\")\n return jobId\n }\n\n async job(id: string, projectId?: string): Promise<ScenarioJob> {\n const response = await this.call(`/jobs/${encodeURIComponent(id)}`, {}, { projectId })\n const raw = (response as { job?: unknown })?.job\n if (!raw || typeof raw !== \"object\") throw new Error(\"Scenario returned an invalid job\")\n const record = raw as Record<string, unknown>\n const jobId = readJobId(raw)\n if (!jobId || typeof record.status !== \"string\") {\n throw new Error(\"Scenario returned an invalid job\")\n }\n return {\n jobId,\n status: record.status,\n ...(typeof record.progress === \"number\" ? { progress: record.progress } : {}),\n ...(record.metadata && typeof record.metadata === \"object\"\n ? { metadata: record.metadata as ScenarioJob[\"metadata\"] }\n : {}),\n ...(record.billing && typeof record.billing === \"object\"\n ? { billing: record.billing as ScenarioJob[\"billing\"] }\n : {}),\n }\n }\n\n async asset(id: string, projectId?: string): Promise<ScenarioAsset> {\n const response = await this.call(\n `/assets/${encodeURIComponent(id)}`,\n {},\n { originalAssets: \"true\", projectId },\n )\n const raw = (response as { asset?: unknown })?.asset\n if (!raw || typeof raw !== \"object\") throw new Error(`Scenario returned an invalid asset ${id}`)\n const asset = raw as Record<string, unknown>\n const assetId = typeof asset.id === \"string\" && asset.id ? asset.id : id\n const url = typeof asset.url === \"string\" ? asset.url : \"\"\n const originalFileUrl = typeof asset.originalFileUrl === \"string\"\n ? asset.originalFileUrl\n : undefined\n if (!originalFileUrl && !url) throw new Error(`Scenario asset ${assetId} has no download URL`)\n const metadata = isRecord(asset.metadata) ? asset.metadata : {}\n const rawOutputIndex = asset.outputIndex ?? metadata.outputIndex\n const outputIndex = Number.isInteger(rawOutputIndex) && Number(rawOutputIndex) >= 0\n ? Number(rawOutputIndex)\n : Number.MAX_SAFE_INTEGER\n const originalMimeType = typeof asset.originalMimeType === \"string\"\n ? asset.originalMimeType\n : typeof asset.mimeType === \"string\"\n ? asset.mimeType\n : undefined\n return {\n id: assetId,\n url,\n ...(originalFileUrl ? { originalFileUrl } : {}),\n ...(originalMimeType ? { originalMimeType } : {}),\n outputIndex,\n }\n }\n\n async download(url: string): Promise<Buffer> {\n const parsed = new URL(url)\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new Error(\"Scenario downloads must use HTTP or HTTPS\")\n }\n const response = await this.request(parsed)\n if (!response.ok) throw new Error(`Scenario download failed (${response.status})`)\n const declared = Number(response.headers.get(\"content-length\"))\n if (Number.isFinite(declared) && declared > MAX_DOWNLOAD_BYTES) {\n throw new Error(`Scenario download exceeds the ${MAX_DOWNLOAD_BYTES}-byte safety limit`)\n }\n const bytes = Buffer.from(await response.arrayBuffer())\n if (bytes.length > MAX_DOWNLOAD_BYTES) {\n throw new Error(`Scenario download exceeds the ${MAX_DOWNLOAD_BYTES}-byte safety limit`)\n }\n return bytes\n }\n\n async checkConnection(): Promise<void> {\n await this.call(\"/models\", {}, { pageSize: \"1\" })\n }\n\n private async call(\n pathname: string,\n init: RequestInit = {},\n query: Record<string, string | undefined> = {},\n ): Promise<unknown> {\n if (!this.apiKey || !this.apiSecret) {\n const missing = [\n !this.apiKey ? \"SCENARIO_SDK_API_KEY\" : null,\n !this.apiSecret ? \"SCENARIO_SDK_API_SECRET\" : null,\n ].filter(Boolean)\n throw new Error(`${missing.join(\" and \")} ${missing.length > 1 ? \"are\" : \"is\"} not set`)\n }\n const url = new URL(`${this.baseUrl.replace(/\\/$/, \"\")}${pathname}`)\n for (const [key, value] of Object.entries(query)) {\n if (value != null) url.searchParams.set(key, value)\n }\n const auth = Buffer.from(`${this.apiKey}:${this.apiSecret}`).toString(\"base64\")\n const response = await this.request(url, {\n ...init,\n headers: {\n Accept: \"application/json\",\n Authorization: `Basic ${auth}`,\n ...(init.body ? { \"Content-Type\": \"application/json\" } : {}),\n ...init.headers,\n },\n })\n const text = await response.text()\n let value: unknown = null\n try {\n value = text ? JSON.parse(text) : null\n } catch {\n value = text\n }\n if (!response.ok) {\n const retry = response.headers.get(\"retry-after\")\n const detail = redactScenarioError(value, [this.apiKey, this.apiSecret, auth])\n throw new Error(\n `Scenario request failed (${response.status}): ${detail}` +\n (retry ? `; retry after ${retry}s` : \"\"),\n )\n }\n return value\n }\n}\n\n/** Experimental Scenario still-image adapter with mandatory CU preflight. */\nexport class ScenarioProvider implements Provider {\n readonly id = \"scenario\"\n\n constructor(private readonly client: ScenarioClient) {}\n\n static fromEnv(): ScenarioProvider {\n return new ScenarioProvider(new ScenarioClient(\n process.env.SCENARIO_SDK_API_KEY,\n process.env.SCENARIO_SDK_API_SECRET,\n scenarioBaseUrl(process.env.SCENARIO_API_BASE_URL ?? DEFAULT_BASE_URL),\n ))\n }\n\n static forOffline(): ScenarioProvider {\n return new ScenarioProvider(new ScenarioClient(undefined, undefined))\n }\n\n static forDownloads(): ScenarioProvider {\n return ScenarioProvider.fromEnv()\n }\n\n supports(generator: Generator): boolean {\n return generator === \"map\"\n }\n\n estimate(spec: ResolvedSpec): CostEstimate {\n const options = scenarioOptions(spec)\n return {\n unit: \"compute-units\",\n amount: options.maxComputeUnits,\n candidates: options.numOutputs ?? 1,\n }\n }\n\n validate(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): void {\n const options = scenarioOptions(spec)\n if (typeof options.modelId !== \"string\" || !options.modelId.trim()) {\n throw new Error(\"Scenario modelId is required\")\n }\n if (!Number.isFinite(options.maxComputeUnits) || options.maxComputeUnits <= 0) {\n throw new Error(\"Scenario maxComputeUnits must be a positive number\")\n }\n const count = options.numOutputs ?? 1\n if (!Number.isInteger(count) || count < 1 || count > 4) {\n throw new Error(\"Scenario numOutputs must be a whole number from 1 to 4\")\n }\n if (\n spec.width < 128 || spec.width > 2048 || spec.width % 16 !== 0 ||\n spec.height < 128 || spec.height > 2048 || spec.height % 16 !== 0\n ) {\n throw new Error(\"Scenario width and height must be multiples of 16 from 128 to 2048\")\n }\n if (styleImages.length) {\n throw new Error(\"Scenario styleImages are not supported yet; use a reusable Scenario model\")\n }\n if (options.projectId != null && (typeof options.projectId !== \"string\" || !options.projectId.trim())) {\n throw new Error(\"Scenario projectId must be a non-empty string\")\n }\n validateParameters(options.parameters ?? {})\n }\n\n rateLimit(): RateLimit {\n return { spacingMs: 1000, maxInFlight: 4 }\n }\n\n async submit(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): Promise<ProviderSubmission> {\n this.validate(spec, styleImages)\n const options = scenarioOptions(spec)\n const body = requestBody(spec, options)\n const quote = await this.client.quote(options.modelId, body, options.projectId)\n if (quote.total > options.maxComputeUnits + Number.EPSILON) {\n throw new Error(\n `Scenario quoted ${quote.total} compute-units, above maxComputeUnits ` +\n `${options.maxComputeUnits}; no paid request was sent`,\n )\n }\n const apiJobId = await this.client.submit(options.modelId, body, options.projectId)\n return {\n jobId: jobRef(apiJobId, options.projectId),\n metadata: {\n modelId: options.modelId,\n projectId: options.projectId ?? null,\n maxComputeUnits: options.maxComputeUnits,\n quotedComputeUnits: quote.total,\n creativeUnitsCost: quote.creativeUnitsCost,\n costDetails: quote.costDetails,\n ipDetectionCost: quote.ipDetectionCost,\n },\n }\n }\n\n async poll(jobReference: string, _generator: Generator, context?: PollContext): Promise<JobState> {\n const reference = parseJobRef(jobReference)\n const job = await this.client.job(reference.jobId, reference.projectId)\n const metadata = jobMetadata(job, context?.spec ? scenarioOptions(context.spec) : undefined)\n if ([\"pending\", \"queued\", \"warming-up\", \"in-progress\", \"finalizing\", \"processing\"].includes(job.status)) {\n return {\n status: \"processing\",\n progressPercent: validProgress(job.progress),\n }\n }\n if ([\"failure\", \"failed\", \"canceled\"].includes(job.status)) {\n return { status: \"failed\", error: scenarioJobError(job) }\n }\n if (job.status !== \"success\") {\n return { status: \"failed\", error: `Scenario returned unknown job status \"${job.status}\"` }\n }\n const assetIds = scenarioAssetIds(job)\n if (!assetIds.length) return { status: \"failed\", error: \"Scenario job returned no asset IDs\" }\n const assets = await this.assets(assetIds, reference.projectId)\n if (assets.length > 1) {\n return {\n status: \"review\",\n candidateUrls: assets.map(assetDownloadUrl),\n metadata: { ...metadata, assetIds: assets.map((asset) => asset.id) },\n }\n }\n const asset = assets[0]!\n return {\n status: \"ready\",\n objectId: asset.id,\n sourceUrl: assetRef(asset.id, reference.projectId),\n sources: [{ url: assetRef(asset.id, reference.projectId), mediaType: MediaType.PNG }],\n metadata: {\n ...metadata,\n assetId: asset.id,\n outputIndex: asset.outputIndex === Number.MAX_SAFE_INTEGER ? null : asset.outputIndex,\n },\n }\n }\n\n async selectCandidate(jobReference: string, index: number): Promise<CandidateSelection> {\n const reference = parseJobRef(jobReference)\n const job = await this.client.job(reference.jobId, reference.projectId)\n if (job.status !== \"success\") throw new Error(`Scenario job ${reference.jobId} is not ready`)\n const assets = await this.assets(scenarioAssetIds(job), reference.projectId)\n const asset = assets[index]\n if (!asset) throw new Error(`Scenario job ${reference.jobId} has no candidate at index ${index}`)\n return {\n objectId: asset.id,\n sourceUrl: assetRef(asset.id, reference.projectId),\n metadata: {\n ...jobMetadata(job),\n assetId: asset.id,\n outputIndex: asset.outputIndex === Number.MAX_SAFE_INTEGER ? null : asset.outputIndex,\n },\n }\n }\n\n async download(source: string): Promise<Buffer> {\n if (!source.startsWith(`${SOURCE_PROTOCOL}//`)) return this.client.download(source)\n const reference = parseAssetRef(source)\n const asset = await this.client.asset(reference.assetId, reference.projectId)\n assertPngAsset(asset)\n return this.client.download(assetDownloadUrl(asset))\n }\n\n async checkConnection(): Promise<void> {\n await this.client.checkConnection()\n }\n\n private async assets(ids: string[], projectId?: string): Promise<ScenarioAsset[]> {\n const assets = await Promise.all(ids.map((id) => this.client.asset(id, projectId)))\n const jobOrder = new Map(ids.map((id, index) => [id, index]))\n for (const asset of assets) assertPngAsset(asset)\n return assets.sort((left, right) =>\n left.outputIndex - right.outputIndex ||\n (jobOrder.get(left.id) ?? Number.MAX_SAFE_INTEGER) -\n (jobOrder.get(right.id) ?? Number.MAX_SAFE_INTEGER) ||\n left.id.localeCompare(right.id))\n }\n}\n\nfunction scenarioOptions(spec: ResolvedSpec): ScenarioOptions {\n return spec.providerOptions as unknown as ScenarioOptions\n}\n\nfunction scenarioBaseUrl(value: string): string {\n let url: URL\n try {\n url = new URL(value)\n } catch {\n throw new Error(\"SCENARIO_API_BASE_URL must be an absolute HTTP(S) URL\")\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"SCENARIO_API_BASE_URL must use HTTP or HTTPS\")\n }\n return url.href.replace(/\\/$/, \"\")\n}\n\nfunction requestBody(spec: ResolvedSpec, options: ScenarioOptions): Record<string, unknown> {\n return {\n ...(options.parameters ?? {}),\n prompt: spec.prompt,\n width: spec.width,\n height: spec.height,\n numOutputs: options.numOutputs ?? 1,\n ...(spec.seed != null ? { seed: spec.seed } : {}),\n }\n}\n\nfunction validateParameters(parameters: Record<string, unknown>): void {\n if (!parameters || typeof parameters !== \"object\" || Array.isArray(parameters)) {\n throw new Error(\"Scenario parameters must be a JSON object\")\n }\n for (const key of Object.keys(parameters)) {\n if (PROTECTED_PARAMETERS.has(key)) {\n throw new Error(`Scenario parameters.${key} is managed by PixelKiln and cannot be overridden`)\n }\n }\n assertJsonValue(parameters, \"Scenario parameters\")\n}\n\nfunction assertJsonValue(value: unknown, label: string, seen = new Set<object>()): void {\n if (value == null || typeof value === \"string\" || typeof value === \"boolean\") return\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) throw new Error(`${label} contains a non-finite number`)\n return\n }\n if (typeof value !== \"object\") throw new Error(`${label} must contain only JSON values`)\n if (!Array.isArray(value)) {\n const prototype = Object.getPrototypeOf(value)\n if (prototype !== Object.prototype && prototype !== null) {\n throw new Error(`${label} must contain only plain JSON objects`)\n }\n }\n if (seen.has(value)) throw new Error(`${label} contains a circular value`)\n seen.add(value)\n if (Array.isArray(value)) {\n value.forEach((item, index) => assertJsonValue(item, `${label}[${index}]`, seen))\n } else {\n for (const [key, item] of Object.entries(value)) {\n assertJsonValue(item, `${label}.${key}`, seen)\n }\n }\n seen.delete(value)\n}\n\nfunction jobRef(jobId: string, projectId?: string): string {\n const url = new URL(\"scenario://job\")\n url.searchParams.set(\"id\", jobId)\n if (projectId) url.searchParams.set(\"projectId\", projectId)\n return url.href\n}\n\nfunction parseJobRef(value: string): { jobId: string; projectId?: string } {\n if (!value.startsWith(`${SOURCE_PROTOCOL}//`)) return { jobId: value }\n const url = new URL(value)\n const jobId = url.searchParams.get(\"id\")\n if (url.protocol !== SOURCE_PROTOCOL || url.hostname !== \"job\" || !jobId) {\n throw new Error(\"Invalid durable Scenario job reference\")\n }\n const projectId = url.searchParams.get(\"projectId\") || undefined\n return { jobId, ...(projectId ? { projectId } : {}) }\n}\n\nfunction assetRef(assetId: string, projectId?: string): string {\n const url = new URL(\"scenario://asset\")\n url.searchParams.set(\"id\", assetId)\n if (projectId) url.searchParams.set(\"projectId\", projectId)\n return url.href\n}\n\nfunction parseAssetRef(value: string): { assetId: string; projectId?: string } {\n const url = new URL(value)\n const assetId = url.searchParams.get(\"id\")\n if (url.protocol !== SOURCE_PROTOCOL || url.hostname !== \"asset\" || !assetId) {\n throw new Error(\"Invalid durable Scenario asset reference\")\n }\n const projectId = url.searchParams.get(\"projectId\") || undefined\n return { assetId, ...(projectId ? { projectId } : {}) }\n}\n\nfunction readJobId(value: unknown): string | null {\n if (!value || typeof value !== \"object\") return null\n const job = value as Record<string, unknown>\n const id = job.jobId ?? job.id\n return typeof id === \"string\" && id ? id : null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value)\n}\n\nfunction scenarioAssetIds(job: ScenarioJob): string[] {\n const ids = job.metadata?.assetIds\n return Array.isArray(ids)\n ? [...new Set(ids.filter((id): id is string => typeof id === \"string\" && id.length > 0))]\n : []\n}\n\nfunction assetDownloadUrl(asset: ScenarioAsset): string {\n return asset.originalFileUrl || asset.url\n}\n\nfunction assertPngAsset(asset: ScenarioAsset): void {\n if (asset.originalMimeType && asset.originalMimeType !== MediaType.PNG) {\n throw new Error(\n `Scenario asset ${asset.id} is ${asset.originalMimeType}; PixelKiln's Scenario MVP requires PNG output`,\n )\n }\n}\n\nfunction jobMetadata(job: ScenarioJob, options?: ScenarioOptions): ProviderMetadata {\n const billing = job.billing\n const billedMain = optionalFiniteNonnegative(billing?.cuCost, \"Scenario job returned invalid CU billing\")\n const billedAddons = Object.values(numericRecord(billing?.cuCostDetails))\n .reduce((sum, amount) => sum + amount, 0)\n return {\n ...(options\n ? {\n modelId: options.modelId,\n projectId: options.projectId ?? null,\n maxComputeUnits: options.maxComputeUnits,\n }\n : {}),\n apiJobId: job.jobId,\n billedComputeUnits: billedMain + billedAddons,\n billing: billing ?? null,\n }\n}\n\nfunction scenarioJobError(job: ScenarioJob): string {\n const raw = job.metadata?.error\n const detail = typeof raw === \"string\"\n ? raw\n : raw && typeof raw === \"object\" && typeof (raw as { message?: unknown }).message === \"string\"\n ? String((raw as { message: string }).message)\n : \"job did not complete\"\n return `Scenario job ${job.status}: ${detail.slice(0, 500)}`\n}\n\nfunction validProgress(progress: number | undefined): number | null {\n if (typeof progress !== \"number\" || !Number.isFinite(progress) || progress < 0 || progress > 1) {\n return null\n }\n return Math.round(progress * 100)\n}\n\nfunction finiteNonnegative(value: unknown, message: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) throw new Error(message)\n return value\n}\n\nfunction optionalFiniteNonnegative(value: unknown, message: string): number {\n if (value == null) return 0\n return finiteNonnegative(value, message)\n}\n\nfunction numericRecord(value: unknown): Record<string, number> {\n if (value == null) return {}\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\"Scenario returned invalid cost details\")\n }\n const out: Record<string, number> = {}\n for (const [key, amount] of Object.entries(value)) {\n out[key] = finiteNonnegative(amount, `Scenario returned invalid cost detail \"${key}\"`)\n }\n return out\n}\n\nfunction redactScenarioError(value: unknown, secrets: string[]): string {\n let detail: string\n if (typeof value === \"string\") detail = value\n else if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>\n const nested = record.error && typeof record.error === \"object\"\n ? (record.error as Record<string, unknown>).message\n : null\n detail = typeof record.message === \"string\"\n ? record.message\n : typeof nested === \"string\"\n ? nested\n : typeof record.detail === \"string\"\n ? record.detail\n : \"request failed\"\n } else detail = \"request failed\"\n for (const secret of secrets) {\n if (secret) detail = detail.split(secret).join(\"[redacted]\")\n }\n return detail.slice(0, 500)\n}\n","import type { Provider } from \"../provider.ts\"\nimport { ComfyUIProvider } from \"./comfyui.ts\"\nimport { PixelLabProvider } from \"./pixellab.ts\"\nimport { RetroDiffusionProvider } from \"./retrodiffusion.ts\"\nimport { ScenarioProvider } from \"./scenario.ts\"\n\nexport type ProviderMode = \"online\" | \"offline\" | \"downloads\"\n\n/** Construction metadata kept outside adapters so the CLI stays generic. */\nexport interface ProviderFactory {\n readonly id: string\n /** Environment variable expected for authenticated operations, if any. */\n readonly credentialEnv?: string\n /** All environment variables required by providers with compound credentials. */\n readonly credentialEnvs?: readonly string[]\n create(mode: ProviderMode): Provider\n}\n\nexport function providerCredentialEnvs(factory: ProviderFactory): readonly string[] {\n return factory.credentialEnvs ?? (factory.credentialEnv ? [factory.credentialEnv] : [])\n}\n\nconst factories = new Map<string, ProviderFactory>()\n\n/** Register a provider without allowing import order to replace an existing id. */\nexport function registerProvider(factory: ProviderFactory): void {\n const id = factory.id.trim()\n if (!id) throw new Error(\"Provider id cannot be empty\")\n if (factories.has(id)) throw new Error(`Provider \"${id}\" is already registered`)\n factories.set(id, factory)\n}\n\nexport function providerFactory(id: string): ProviderFactory {\n const factory = factories.get(id)\n if (!factory) {\n const available = [...factories.keys()].sort().join(\", \") || \"(none)\"\n throw new Error(`Unknown provider \"${id}\". Available providers: ${available}`)\n }\n return factory\n}\n\nexport function createProvider(id: string, mode: ProviderMode): Provider {\n return providerFactory(id).create(mode)\n}\n\nexport function availableProviders(): string[] {\n return [...factories.keys()].sort()\n}\n\nregisterProvider({\n id: \"pixellab\",\n credentialEnv: \"PIXELLAB_API_KEY\",\n create(mode) {\n if (mode === \"online\") return PixelLabProvider.fromEnv()\n if (mode === \"downloads\") return PixelLabProvider.forDownloads()\n return PixelLabProvider.forOffline()\n },\n})\n\nregisterProvider({\n id: \"retrodiffusion\",\n credentialEnv: \"RD_API_KEY\",\n create(mode) {\n if (mode === \"online\") return RetroDiffusionProvider.fromEnv()\n if (mode === \"downloads\") return RetroDiffusionProvider.forDownloads()\n return RetroDiffusionProvider.forOffline()\n },\n})\n\nregisterProvider({\n id: \"comfyui\",\n create(mode) {\n if (mode === \"online\") return ComfyUIProvider.fromEnv()\n if (mode === \"downloads\") return ComfyUIProvider.forDownloads()\n return ComfyUIProvider.forOffline()\n },\n})\n\nregisterProvider({\n id: \"scenario\",\n credentialEnvs: [\"SCENARIO_SDK_API_KEY\", \"SCENARIO_SDK_API_SECRET\"],\n create(mode) {\n if (mode === \"online\") return ScenarioProvider.fromEnv()\n if (mode === \"downloads\") return ScenarioProvider.forDownloads()\n return ScenarioProvider.forOffline()\n },\n})\n","import { readFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport type { ZodIssue } from \"zod\"\nimport {\n ManifestInputSchema,\n ManifestSchema,\n StyleSchema,\n candidateCount,\n countNumberedDescriptions,\n generationCost,\n tileVariationCount,\n tileFeatureOutputCount,\n tilesCost,\n type Manifest,\n type ResolvedSpec,\n type ResolvedStyleImage,\n type Style,\n type StyleInput,\n} from \"./types.ts\"\nimport { sha256, specHash } from \"./hash.ts\"\nimport { MediaType } from \"./media.ts\"\nimport { expectedOutputPath } from \"./outputs.ts\"\nimport { validateCostEstimate, type Provider } from \"./provider.ts\"\nimport { createProvider } from \"./providers/registry.ts\"\n\nexport interface LoadedManifest {\n manifest: Manifest\n /** Directory the manifest lives in. All relative paths resolve against it. */\n root: string\n path: string\n}\n\nexport async function loadManifest(manifestPath: string): Promise<LoadedManifest> {\n const abs = path.resolve(manifestPath)\n if (!existsSync(abs)) throw new Error(`No manifest at ${abs}`)\n const input = ManifestInputSchema.safeParse(JSON.parse(await readFile(abs, \"utf8\")))\n if (!input.success) {\n const issues = formatManifestIssues(input.error.issues)\n throw new Error(`Manifest at ${abs} is invalid:\\n${issues}`)\n }\n let styles: Record<string, Style>\n try {\n styles = resolveStyleInheritance(input.data.styles)\n } catch (error) {\n throw new Error(\n `Manifest at ${abs} is invalid:\\n ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n const parsed = ManifestSchema.safeParse({ ...input.data, styles })\n if (!parsed.success) {\n const issues = formatManifestIssues(parsed.error.issues)\n throw new Error(`Manifest at ${abs} is invalid:\\n${issues}`)\n }\n const styleIds = new Set(Object.keys(parsed.data.styles))\n const unknownReferences: string[] = []\n for (const [assetId, asset] of Object.entries(parsed.data.assets)) {\n for (const styleId of asset.styles) {\n if (!styleIds.has(styleId)) unknownReferences.push(`assets.${assetId}.styles: unknown style \"${styleId}\"`)\n }\n for (const styleId of Object.keys(asset.promptByStyle)) {\n if (!styleIds.has(styleId)) {\n unknownReferences.push(`assets.${assetId}.promptByStyle: unknown style \"${styleId}\"`)\n }\n }\n if (asset.revision) {\n if (!parsed.data.assets[asset.revision.from]) {\n unknownReferences.push(\n `assets.${assetId}.revision.from: unknown asset \"${asset.revision.from}\"`,\n )\n } else if (asset.revision.from === assetId) {\n unknownReferences.push(`assets.${assetId}.revision.from: an asset cannot revise itself`)\n }\n }\n }\n const visiting = new Set<string>()\n const visited = new Set<string>()\n const visitRevision = (assetId: string, chain: string[]) => {\n if (visited.has(assetId)) return\n if (visiting.has(assetId)) {\n const start = chain.indexOf(assetId)\n unknownReferences.push(\n `assets.${assetId}.revision.from: revision cycle ${[...chain.slice(start), assetId].join(\" -> \")}`,\n )\n return\n }\n visiting.add(assetId)\n const parent = parsed.data.assets[assetId]?.revision?.from\n if (parent && parent !== assetId && parsed.data.assets[parent]) {\n visitRevision(parent, [...chain, assetId])\n }\n visiting.delete(assetId)\n visited.add(assetId)\n }\n for (const assetId of Object.keys(parsed.data.assets)) visitRevision(assetId, [])\n if (unknownReferences.length) {\n throw new Error(`Manifest at ${abs} is invalid:\\n${unknownReferences.map((i) => ` ${i}`).join(\"\\n\")}`)\n }\n return { manifest: parsed.data, root: path.dirname(abs), path: abs }\n}\n\nfunction formatManifestIssues(issues: ZodIssue[]): string {\n return issues.flatMap((issue): string[] => {\n if (issue.code === \"invalid_union\") {\n return issue.unionErrors.flatMap((error) => formatManifestIssues(error.issues).split(\"\\n\"))\n }\n return [` ${issue.path.join(\".\")}: ${issue.message}`]\n }).join(\"\\n\")\n}\n\n/** Resolve child styles without carrying the inheritance marker into runtime state. */\nfunction resolveStyleInheritance(styles: Record<string, StyleInput>): Record<string, Style> {\n const resolved = new Map<string, Style>()\n\n const visit = (styleId: string, chain: string[]): Style => {\n const cached = resolved.get(styleId)\n if (cached) return cached\n const cycleStart = chain.indexOf(styleId)\n if (cycleStart >= 0) {\n throw new Error(\n `styles.${styleId}.extends: inheritance cycle ` +\n `${[...chain.slice(cycleStart), styleId].join(\" -> \")}`,\n )\n }\n const style = styles[styleId]\n if (!style) throw new Error(`styles.${styleId}: unknown style`)\n if (!(\"extends\" in style)) {\n resolved.set(styleId, style)\n return style\n }\n\n const parentId = style.extends\n if (!Object.hasOwn(styles, parentId)) {\n throw new Error(`styles.${styleId}.extends: unknown style \"${parentId}\"`)\n }\n const parent = visit(parentId, [...chain, styleId])\n const { extends: _parent, ...child } = style\n const merged = {\n ...parent,\n ...child,\n quality:\n child.quality == null\n ? parent.quality\n : { ...(parent.quality ?? {}), ...child.quality },\n providerOptions: mergeProviderOptions(parent.providerOptions, child.providerOptions),\n }\n const parsed = StyleSchema.safeParse(merged)\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((issue) => `styles.${styleId}.${issue.path.join(\".\")}: ${issue.message}`)\n .join(\"; \")\n throw new Error(issues)\n }\n resolved.set(styleId, parsed.data)\n return parsed.data\n }\n\n return Object.fromEntries(Object.keys(styles).map((styleId) => [styleId, visit(styleId, [])]))\n}\n\nfunction mergeProviderOptions(\n parent: Record<string, Record<string, unknown>>,\n child: Record<string, Record<string, unknown>> | undefined,\n): Record<string, Record<string, unknown>> {\n if (!child) return parent\n const merged = { ...parent }\n for (const [provider, options] of Object.entries(child)) {\n merged[provider] = { ...(parent[provider] ?? {}), ...options }\n }\n return merged\n}\n\n/**\n * Expands the manifest into one concrete spec per (style, asset) pair. This is\n * where a style becomes a namespace: adding a style re-derives the entire asset\n * set under a separate output root and separate lock keys, which is what makes\n * a whole-collection restyle a one-flag operation.\n */\nexport async function resolveSpecs(\n loaded: LoadedManifest,\n filter?: {\n styles?: string[]\n assets?: string[]\n /** Optional provider makes offline plan cost/candidate estimates adapter-owned. */\n provider?: Pick<\n Provider,\n | \"supports\"\n | \"supportsRevision\"\n | \"estimate\"\n | \"validate\"\n | \"resolveOptions\"\n | \"resolveInputs\"\n | \"id\"\n >\n },\n): Promise<ResolvedSpec[]> {\n const { manifest, root } = loaded\n // The explicit provider remains a whole-resolution override for existing\n // library callers and diagnostics. Normal manifest resolution constructs\n // one offline adapter per effective style provider.\n const providerOverride = filter?.provider\n const providers = new Map<string, Pick<\n Provider,\n | \"supports\"\n | \"supportsRevision\"\n | \"estimate\"\n | \"validate\"\n | \"resolveOptions\"\n | \"resolveInputs\"\n | \"id\"\n >>()\n const providerFor = (id: string) => {\n if (providerOverride) return providerOverride\n let provider = providers.get(id)\n if (!provider) {\n provider = createProvider(id, \"offline\")\n providers.set(id, provider)\n }\n return provider\n }\n const specs: ResolvedSpec[] = []\n\n const styleIds = Object.keys(manifest.styles).filter(\n (id) => !filter?.styles?.length || filter.styles.includes(id),\n )\n for (const unknownStyle of filter?.styles ?? []) {\n if (!manifest.styles[unknownStyle]) {\n throw new Error(\n `Unknown style \"${unknownStyle}\". Defined: ${Object.keys(manifest.styles).join(\", \") || \"(none)\"}`,\n )\n }\n }\n for (const unknownAsset of filter?.assets ?? []) {\n if (!manifest.assets[unknownAsset]) {\n throw new Error(`Unknown asset \"${unknownAsset}\".`)\n }\n }\n\n const requestedAssetIds = new Set(filter?.assets?.length\n ? filter.assets\n : Object.keys(manifest.assets))\n const resolutionAssetIds = new Set(requestedAssetIds)\n for (const assetId of [...requestedAssetIds]) {\n let current = manifest.assets[assetId]?.revision?.from\n while (current && !resolutionAssetIds.has(current)) {\n resolutionAssetIds.add(current)\n current = manifest.assets[current]?.revision?.from\n }\n }\n\n // Style images are hashed, not just named: editing a reference image must\n // invalidate every spec that depends on it.\n const styleImageCache = new Map<\n string,\n { base64: string; hash: string; width: number; height: number; format: \"png\" | \"jpeg\" }\n >()\n async function loadStyleImage(rel: string) {\n const abs = path.resolve(root, rel)\n let hit = styleImageCache.get(abs)\n if (!hit) {\n if (!existsSync(abs)) throw new Error(`Style image not found: ${abs}`)\n const buf = await readFile(abs)\n const metadata = imageMetadata(buf)\n if (!metadata) throw new Error(`Style image is not a readable PNG or JPEG: ${abs}`)\n if (metadata.width < 1 || metadata.height < 1) {\n throw new Error(`Style image has invalid dimensions: ${abs}`)\n }\n hit = { base64: buf.toString(\"base64\"), hash: sha256(buf), ...metadata }\n styleImageCache.set(abs, hit)\n }\n return hit\n }\n\n for (const styleId of styleIds) {\n const style = manifest.styles[styleId]!\n const activeProvider = providerFor(style.provider ?? manifest.provider)\n const rawProviderOptions = style.providerOptions[activeProvider.id] ?? {}\n const optionResolution = activeProvider.resolveOptions\n ? await activeProvider.resolveOptions(rawProviderOptions, { root, styleId })\n : { options: rawProviderOptions }\n const providerOptions = optionResolution.options\n const providerOptionIdentity = optionResolution.identity ?? providerOptions\n const styleImageHashes: string[] = []\n const styleImageDimensions: { width: number; height: number }[] = []\n for (const img of style.styleImages) {\n const loadedImage = await loadStyleImage(img.path)\n styleImageHashes.push(loadedImage.hash)\n styleImageDimensions.push(loadedImage)\n }\n\n const resolvedImages = style.styleImages.map((image) => {\n const hit = styleImageCache.get(path.resolve(root, image.path))!\n return { base64: hit.base64, width: hit.width, height: hit.height, format: hit.format }\n })\n const styleSpecs = new Map<string, ResolvedSpec>()\n const providerInputIdentities = new Map<string, unknown>()\n\n for (const [assetId, asset] of Object.entries(manifest.assets)) {\n if (!resolutionAssetIds.has(assetId)) continue\n if (asset.styles.length && !asset.styles.includes(styleId)) continue\n\n const generator = style.generator\n if (!activeProvider.supports(generator)) {\n throw new Error(`Provider \"${activeProvider.id}\" does not support generator \"${generator}\"`)\n }\n if (Object.keys(asset.providerInputs).length && !activeProvider.resolveInputs) {\n throw new Error(\n `Provider \"${activeProvider.id}\" does not support asset providerInputs ` +\n `(${styleId}/${assetId})`,\n )\n }\n const inputResolution = activeProvider.resolveInputs\n ? await activeProvider.resolveInputs(asset.providerInputs, {\n root,\n styleId,\n assetId,\n generator,\n providerOptions,\n })\n : { inputs: {} }\n const providerInputs = inputResolution.inputs\n const providerInputIdentity = inputResolution.identity ?? providerInputs\n providerInputIdentities.set(assetId, providerInputIdentity)\n let width: number\n let height: number\n let size: number\n\n if (generator === \"1dir\") {\n // Square only. When style images are in play the API derives the size\n // from the largest reference, so the manifest's `size` is advisory.\n size = styleImageDimensions.length\n ? Math.max(...styleImageDimensions.flatMap((img) => [img.width, img.height]))\n : (asset.size ?? style.size ?? 64)\n width = size\n height = size\n } else if (generator === \"tiles\") {\n // Style mode copies the reference geometry; otherwise the endpoint\n // uses tileSize. Asset-level map dimensions do not apply to tiles.\n width = styleImageDimensions.length\n ? Math.max(...styleImageDimensions.map((img) => img.width))\n : (style.tileSize ?? 32)\n height = styleImageDimensions.length\n ? Math.max(...styleImageDimensions.map((img) => img.height))\n : (style.tileSize ?? 32)\n size = Math.max(width, height)\n } else {\n width = asset.width ?? style.size ?? 64\n height = asset.height ?? style.size ?? 64\n size = Math.max(width, height)\n }\n\n // A per-style override replaces the subject wording, not the style\n // wrapping — prefix and suffix still apply.\n const subject = asset.promptByStyle[styleId] ?? asset.prompt\n const prompt = [style.promptPrefix, subject, style.promptSuffix]\n .map((p) => p.trim())\n .filter(Boolean)\n .join(\", \")\n\n const relFile = asset.file ?? path.join(asset.category ?? \"\", `${assetId}.png`)\n const outFile = path.resolve(root, style.outDir, relFile)\n const qualityOutFile = style.quality\n ? path.resolve(root, style.quality.outDir, pngPath(relFile))\n : undefined\n\n // One `tiles` call draws a whole set, so its price and its candidate\n // count both come off the set rather than off a single sprite.\n const tileSize = generator === \"tiles\" ? size : (style.tileSize ?? 32)\n const tileVariations =\n tileFeatureOutputCount(generator === \"tiles\" ? style.tileFeature : undefined) ??\n tileVariationCount(countNumberedDescriptions(prompt))\n\n const base = {\n styleId,\n assetId,\n provider: activeProvider.id,\n providerOptions,\n providerInputs,\n generator,\n prompt,\n width,\n height,\n size,\n view: style.view ?? (generator === \"1dir\" ? \"top-down\" : \"high top-down\"),\n styleImagePaths: style.styleImages.map((s) => s.path),\n outline: style.outline,\n shading: style.shading,\n detail: style.detail,\n seed: style.seed,\n palette: style.palette,\n noBackground: style.noBackground,\n tileSize: generator === \"tiles\" ? tileSize : undefined,\n tileType: generator === \"tiles\" ? style.tileType : undefined,\n tileView: generator === \"tiles\" ? style.tileView : undefined,\n tileFeature: generator === \"tiles\" ? style.tileFeature : undefined,\n outlineMode: generator === \"tiles\" ? style.outlineMode : undefined,\n cost:\n generator === \"tiles\"\n ? tilesCost(tileSize, tileVariations)\n : generationCost(width, height, generator),\n costUnit: \"generations\" as const,\n candidates:\n generator === \"tiles\"\n ? tileVariations\n : generator === \"1dir\"\n ? candidateCount(size)\n : 1,\n }\n\n const tags = [\n ...new Set([\n ...style.tags,\n ...asset.tags,\n `pixelkiln:${manifest.name}`,\n `asset:${assetId}`,\n `style:${styleId}`,\n ]),\n ]\n const resolved: ResolvedSpec = {\n ...base,\n root,\n outFile,\n ...(style.quality && qualityOutFile\n ? {\n quality: {\n outFile: qualityOutFile,\n palette: style.quality.palette,\n minGridConfidence: style.quality.minGridConfidence,\n ...(style.quality.minTransparency == null\n ? {}\n : { minTransparency: style.quality.minTransparency }),\n ...(style.quality.fixerRevision\n ? { fixerRevision: style.quality.fixerRevision }\n : {}),\n ...(style.quality.fixerPython\n ? { fixerPython: path.resolve(root, style.quality.fixerPython) }\n : {}),\n ...(style.quality.fps == null ? {} : { fps: style.quality.fps }),\n },\n }\n : {}),\n tags,\n source: asset.source,\n // Revision identity is attached after every dependency in this style\n // has a concrete output target. Finalization below computes the hash.\n specHash: \"\",\n }\n styleSpecs.set(assetId, resolved)\n }\n\n const finalized = new Set<string>()\n const finalize = async (assetId: string): Promise<ResolvedSpec> => {\n const resolved = styleSpecs.get(assetId)\n if (!resolved) {\n throw new Error(\n `Asset \"${assetId}\" is not available in style \"${styleId}\"; ` +\n \"revision parents must participate in the same style.\",\n )\n }\n if (finalized.has(assetId)) return resolved\n const asset = manifest.assets[assetId]!\n if (asset.revision) {\n if (!activeProvider.supportsRevision?.(asset.revision.mode)) {\n throw new Error(\n `Provider \"${activeProvider.id}\" does not support ${asset.revision.mode} revisions`,\n )\n }\n const sourceSpec = await finalize(asset.revision.from)\n const sourceFile = sourceSpec.quality?.outFile ??\n (sourceSpec.source ? path.resolve(root, sourceSpec.source) : sourceSpec.outFile)\n const sourceImage = await optionalRevisionImage(sourceFile, \"revision source\")\n const maskFile = asset.revision.mask\n ? path.resolve(root, asset.revision.mask)\n : undefined\n const maskImage = maskFile\n ? await optionalRevisionImage(maskFile, \"revision mask\", \"png\")\n : null\n if (\n sourceImage && maskImage &&\n (sourceImage.width !== maskImage.width || sourceImage.height !== maskImage.height)\n ) {\n throw new Error(\n `Revision mask for ${styleId}/${assetId} is ${maskImage.width}x${maskImage.height}; ` +\n `source ${asset.revision.from} is ${sourceImage.width}x${sourceImage.height}`,\n )\n }\n resolved.revision = {\n mode: asset.revision.mode,\n sourceAssetId: asset.revision.from,\n sourceFile,\n sourceSha256: sourceImage?.hash ?? null,\n sourceWidth: sourceImage?.width ?? null,\n sourceHeight: sourceImage?.height ?? null,\n sourceFormat: sourceImage?.format ?? null,\n sourceSpec,\n ...(maskFile\n ? {\n maskFile,\n maskSha256: maskImage?.hash ?? null,\n maskWidth: maskImage?.width ?? null,\n maskHeight: maskImage?.height ?? null,\n maskFormat: maskImage?.format ?? null,\n }\n : {}),\n ...(asset.revision.strength == null ? {} : { strength: asset.revision.strength }),\n }\n }\n resolved.specHash = specHash(\n resolved,\n styleImageHashes,\n providerOptionIdentity,\n providerInputIdentities.get(assetId),\n )\n activeProvider.validate?.(resolved, resolvedImages)\n const estimate = validateCostEstimate(activeProvider.id, activeProvider.estimate(resolved))\n resolved.cost = estimate.amount\n resolved.costUnit = estimate.unit\n resolved.candidates = estimate.candidates\n finalized.add(assetId)\n return resolved\n }\n\n for (const assetId of Object.keys(manifest.assets)) {\n if (!requestedAssetIds.has(assetId) || !styleSpecs.has(assetId)) continue\n specs.push(await finalize(assetId))\n }\n }\n\n const byOutput = new Map<string, string>()\n const claimOutput = (file: string, owner: string) => {\n const existing = byOutput.get(file)\n if (existing) {\n throw new Error(`Output collision: ${existing} and ${owner} both resolve to ${file}`)\n }\n byOutput.set(file, owner)\n }\n for (const spec of specs) {\n const key = `${spec.styleId}/${spec.assetId}`\n claimOutput(spec.outFile, key)\n if (spec.quality) {\n if (spec.generator === \"frames\") {\n const frameInputs = Object.values(spec.providerInputs ?? {}).find(Array.isArray)\n const count = frameInputs?.length ?? 0\n for (let index = 0; index < count; index++) {\n const role = `frame-${String(index).padStart(2, \"0\")}`\n claimOutput(\n expectedOutputPath(\n { ...spec, outFile: spec.quality.outFile },\n role,\n index,\n count,\n MediaType.PNG,\n ),\n `${key} quality ${role}`,\n )\n }\n } else {\n claimOutput(spec.quality.outFile, `${key} quality output`)\n }\n }\n }\n\n return specs\n}\n\nfunction pngPath(file: string): string {\n const extension = path.extname(file)\n return extension ? `${file.slice(0, -extension.length)}.png` : `${file}.png`\n}\n\nasync function optionalRevisionImage(\n file: string,\n label: string,\n requiredFormat?: \"png\" | \"jpeg\",\n): Promise<{ hash: string; width: number; height: number; format: \"png\" | \"jpeg\" } | null> {\n if (!existsSync(file)) return null\n const bytes = await readFile(file)\n const metadata = imageMetadata(bytes)\n if (!metadata) throw new Error(`${label} is not a readable PNG or JPEG: ${file}`)\n if (requiredFormat && metadata.format !== requiredFormat) {\n throw new Error(`${label} must be ${requiredFormat.toUpperCase()}: ${file}`)\n }\n return { hash: sha256(bytes), ...metadata }\n}\n\n/** Reference image bytes and measured dimensions, in manifest order. */\nexport async function resolveStyleImages(\n loaded: LoadedManifest,\n styleId: string,\n): Promise<ResolvedStyleImage[]> {\n const style = loaded.manifest.styles[styleId]\n if (!style) throw new Error(`Unknown style \"${styleId}\"`)\n const out: ResolvedStyleImage[] = []\n for (const img of style.styleImages) {\n const file = path.resolve(loaded.root, img.path)\n const buf = await readFile(file)\n const metadata = imageMetadata(buf)\n if (!metadata) throw new Error(`Style image is not a readable PNG or JPEG: ${file}`)\n if (metadata.width < 1 || metadata.height < 1) {\n throw new Error(`Style image has invalid dimensions: ${file}`)\n }\n out.push({ base64: buf.toString(\"base64\"), ...metadata })\n }\n return out\n}\n\n/** Retained for callers that only need the encoded bytes. */\nexport async function styleImagesBase64(loaded: LoadedManifest, styleId: string): Promise<string[]> {\n return (await resolveStyleImages(loaded, styleId)).map((img) => img.base64)\n}\n\n/** Reads dimensions without decoding pixel data. */\nexport function imageMetadata(\n buf: Buffer,\n): Pick<ResolvedStyleImage, \"width\" | \"height\" | \"format\"> | null {\n if (\n buf.length >= 24 &&\n buf.readUInt32BE(0) === 0x89504e47 &&\n buf.readUInt32BE(4) === 0x0d0a1a0a &&\n buf.toString(\"ascii\", 12, 16) === \"IHDR\"\n ) {\n return { width: buf.readUInt32BE(16), height: buf.readUInt32BE(20), format: \"png\" }\n }\n\n if (buf.length < 4 || buf[0] !== 0xff || buf[1] !== 0xd8) return null\n let offset = 2\n while (offset + 3 < buf.length) {\n if (buf[offset] !== 0xff) return null\n while (buf[offset] === 0xff) offset++\n const marker = buf[offset++]\n if (marker == null || marker === 0xd9 || marker === 0xda) break\n if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) continue\n if (offset + 2 > buf.length) return null\n const length = buf.readUInt16BE(offset)\n if (length < 2 || offset + length > buf.length) return null\n const isStartOfFrame =\n marker >= 0xc0 &&\n marker <= 0xcf &&\n ![0xc4, 0xc8, 0xcc].includes(marker)\n if (isStartOfFrame) {\n if (length < 7) return null\n return {\n width: buf.readUInt16BE(offset + 5),\n height: buf.readUInt16BE(offset + 3),\n format: \"jpeg\",\n }\n }\n offset += length\n }\n return null\n}\n","import path from \"node:path\"\nimport { upsert } from \"./lock.ts\"\nimport { mediaExtension, type MediaType } from \"./media.ts\"\nimport { lockKey, type Lock, type LockEntry, type LockOutput, type ResolvedSpec } from \"./types.ts\"\n\n/** One lockfile output with the identity consumers should expose publicly. */\nexport interface ResolvedOutput extends LockOutput {\n assetId: string\n /** Stable within a style's atlas or report. Single-output assets keep their old id. */\n id: string\n index: number\n absolutePath: string\n}\n\n/** Store generated paths relative to the manifest so committed locks survive a clone/move. */\nexport function portableOutputPath(file: string, manifestDir: string): string {\n const root = path.resolve(manifestDir)\n const absolute = path.isAbsolute(file) ? path.normalize(file) : path.resolve(root, file)\n const relative = path.relative(root, absolute)\n // Different Windows drives cannot be expressed as a relative path. This is\n // the one case where retaining an absolute path is more honest than writing\n // a value that resolves somewhere else.\n const value = path.isAbsolute(relative) ? absolute : relative\n return value.split(path.sep).join(\"/\")\n}\n\n/** Resolve a portable lock path against the manifest, never the process cwd. */\nexport function resolveOutputPath(recordedPath: string, manifestDir: string): string {\n if (path.isAbsolute(recordedPath)) return path.normalize(recordedPath)\n // A lock committed by Windows before paths became portable cannot be opened\n // directly on POSIX. `normalizeLockOutputPaths` rebases it from the spec.\n if (path.win32.isAbsolute(recordedPath)) return recordedPath\n return path.resolve(manifestDir, recordedPath.split(/[\\\\/]/).join(path.sep))\n}\n\n/** Deterministic current destination for one provider output. */\nexport function expectedOutputPath(\n spec: ResolvedSpec,\n role: string | undefined,\n index: number,\n total: number,\n mediaType?: MediaType,\n): string {\n const originalExt = path.extname(spec.outFile)\n const ext = mediaType ? mediaExtension(mediaType) : (originalExt || \".png\")\n const stem = originalExt ? spec.outFile.slice(0, -originalExt.length) : spec.outFile\n if (total === 1) return `${stem}${ext}`\n const safeRole = (role ?? fallbackOutputRole(index)).replace(/[^a-zA-Z0-9_-]+/g, \"-\")\n return `${stem}-${safeRole}${ext}`\n}\n\n/** Resolve one recorded output from the current manifest-owned destination. */\nexport function currentOutputPath(\n output: Pick<LockOutput, \"path\" | \"role\" | \"mediaType\">,\n spec: ResolvedSpec,\n index: number,\n total: number,\n): string {\n // The lock records where bytes were written; the manifest owns where they\n // belong now. Always deriving from the current spec both rebases a clone and\n // prevents a hand-edited lock path from redirecting restore into an unrelated\n // project file. Output roles preserve structural-set identity.\n return expectedOutputPath(spec, output.role, index, total, output.mediaType)\n}\n\n/** Resolve an entry member using the complete source-set order when available. */\nexport function currentEntryOutputPath(\n entry: LockEntry,\n spec: ResolvedSpec,\n index: number,\n): string {\n const output = entry.outputs[index]!\n const sourceIndex = output.role\n ? (entry.sourceUrls ?? []).findIndex((source) => source.role === output.role)\n : -1\n const position = sourceIndex >= 0 ? sourceIndex : index\n const total = Math.max(entry.outputs.length, entry.sourceUrls?.length ?? 0)\n return currentOutputPath(output, spec, position, total)\n}\n\n/**\n * Rebase legacy absolute output paths onto this checkout and canonicalize all\n * selected entries in memory. Persistence remains the caller's decision.\n */\nexport function normalizeLockOutputPaths(lock: Lock, specs: ResolvedSpec[]): number {\n const byKey = new Map(specs.map((spec) => [lockKey(spec.styleId, spec.assetId), spec]))\n let changed = 0\n for (const [key, entry] of Object.entries(lock.entries)) {\n const spec = byKey.get(key)\n if (!spec) continue\n let entryChanged = false\n const outputs = entry.outputs.map((output, index) => {\n const absolute = currentEntryOutputPath(entry, spec, index)\n const portable = portableOutputPath(absolute, spec.root)\n if (portable === output.path) return output\n changed++\n entryChanged = true\n return { ...output, path: portable }\n })\n if (entryChanged) upsert(lock, key, { outputs })\n }\n return changed\n}\n\n/** The fallback role used when a provider returns several unnamed outputs. */\nexport function fallbackOutputRole(index: number): string {\n return `output-${String(index).padStart(2, \"0\")}`\n}\n\n/**\n * Gives every output a stable, collision-resistant consumer id.\n *\n * A conventional one-file asset remains `grass`, preserving existing atlas\n * lookups. A structural set becomes `grass/tile-00`, `grass/tile-01`, … so no\n * downstream command has to silently pretend its first file is the whole set.\n */\nexport function outputId(\n assetId: string,\n output: Pick<LockOutput, \"role\">,\n index: number,\n total: number,\n): string {\n if (total === 1) return assetId\n return `${assetId}/${output.role ?? fallbackOutputRole(index)}`\n}\n\n/** Resolve every output recorded for one manifest asset, preserving lock order. */\nexport function resolveEntryOutputs(\n entry: LockEntry,\n assetId: string,\n manifestDir: string,\n): ResolvedOutput[] {\n return entry.outputs.map((output, index) => ({\n ...output,\n assetId,\n id: outputId(assetId, output, index, entry.outputs.length),\n index,\n absolutePath: resolveOutputPath(output.path, manifestDir),\n }))\n}\n\n/** Resolve an entry using its current spec, including cross-checkout v2 migration. */\nexport function resolveSpecEntryOutputs(\n entry: LockEntry,\n spec: ResolvedSpec,\n): ResolvedOutput[] {\n return entry.outputs.map((output, index) => ({\n ...output,\n assetId: spec.assetId,\n id: outputId(spec.assetId, output, index, entry.outputs.length),\n index,\n absolutePath: currentEntryOutputPath(entry, spec, index),\n }))\n}\n\n/** Resolve all outputs for a style in deterministic asset-id order. */\nexport function resolveStyleOutputs(\n lock: Lock,\n styleId: string,\n manifestDir: string,\n): ResolvedOutput[] {\n const prefix = `${styleId}/`\n return Object.entries(lock.entries)\n .filter(([key]) => key.startsWith(prefix))\n .sort(([a], [b]) => a.localeCompare(b))\n .flatMap(([key, entry]) =>\n resolveEntryOutputs(entry, key.slice(prefix.length), manifestDir),\n )\n}\n\nexport type OutputSelection =\n | { ok: true; output: LockOutput }\n | { ok: false; reason: string }\n\n/**\n * Select the one output needed by a single-cell consumer such as `mount`.\n * Multi-output sets are deliberately ambiguous unless the manifest names a\n * role; choosing index zero is silent data loss disguised as convenience.\n */\nexport function selectEntryOutput(entry: LockEntry, role?: string): OutputSelection {\n if (role) {\n const output = entry.outputs.find((candidate) => candidate.role === role)\n return output\n ? { ok: true, output }\n : { ok: false, reason: `output role \"${role}\" is not recorded` }\n }\n if (entry.outputs.length === 0) return { ok: false, reason: \"no output recorded in the lockfile\" }\n if (entry.outputs.length === 1) return { ok: true, output: entry.outputs[0]! }\n\n const primary = entry.outputs.filter((output) => !output.role)\n if (primary.length === 1) return { ok: true, output: primary[0]! }\n return {\n ok: false,\n reason: `${entry.outputs.length} outputs are recorded; set \\`outputRole\\` to choose one`,\n }\n}\n\n/** Lock outputs for a resolved spec, or its conventional path before adoption. */\nexport function resolveSpecOutputs(\n spec: ResolvedSpec,\n lock: Lock | undefined,\n manifestDir: string,\n): ResolvedOutput[] {\n const entry = lock?.entries[lockKey(spec.styleId, spec.assetId)]\n if (entry?.outputs.length) return resolveSpecEntryOutputs(entry, spec)\n return [{\n assetId: spec.assetId,\n id: spec.assetId,\n index: 0,\n path: spec.outFile,\n absolutePath: path.resolve(spec.outFile),\n sha256: \"\",\n }]\n}\n","import { readFile, writeFile, rename, mkdir, rmdir, rm, stat } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { parseLock, type Lock, type LockEntry } from \"./types.ts\"\nimport type { CostUnit } from \"./provider.ts\"\n\n/**\n * The lockfile is the record that maps a spec to the provider work that\n * satisfies it and the file on disk that came from it. It is written after\n * every state transition — including immediately after submitting, before the\n * job is awaited — so an interrupted run never loses track of paid-for work.\n */\nexport async function loadLock(lockPath: string): Promise<Lock> {\n if (!existsSync(lockPath)) return { version: 2, entries: {} }\n try {\n return parseLock(JSON.parse(await readFile(lockPath, \"utf8\")))\n } catch (err) {\n throw new Error(\n `Lockfile at ${lockPath} is malformed:\\n${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n\n/**\n * Serializes saves per path.\n *\n * Concurrent stages (parallel downloads in `fetch`) each save after their own\n * upsert. Without this they race on the shared `<path>.tmp`: one worker's\n * rename moves the file out from under another's, which fails with ENOENT and\n * loses that write. Queuing keeps the atomic write-then-rename intact and\n * guarantees the last save reflects the latest in-memory state.\n */\nconst saveQueues = new Map<string, Promise<void>>()\nconst dirtyPatches = new WeakMap<Lock, Map<string, Partial<LockEntry>>>()\nconst dirtyDeletes = new WeakMap<Lock, Set<string>>()\n\n/** Atomic write — a crash mid-save must not leave a truncated lockfile. */\nexport function saveLock(lockPath: string, lock: Lock): Promise<void> {\n const queueKey = path.resolve(lockPath)\n const previous = saveQueues.get(queueKey) ?? Promise.resolve()\n const next = previous\n .catch(() => {}) // one failed save must not poison every later one\n .then(() => writeLockNow(lockPath, lock))\n saveQueues.set(queueKey, next)\n // Drop the queue entry once drained so long-lived processes don't retain it.\n const cleanup = () => {\n if (saveQueues.get(queueKey) === next) saveQueues.delete(queueKey)\n }\n // Using `finally()` here would create a second rejected promise when a save\n // fails. If nobody observes that derived promise Node reports an unhandled\n // rejection even when the caller correctly handles `next`.\n void next.then(cleanup, cleanup)\n return next\n}\n\nasync function writeLockNow(lockPath: string, lock: Lock): Promise<void> {\n await mkdir(path.dirname(path.resolve(lockPath)), { recursive: true })\n const release = await acquireFileLock(lockPath)\n try {\n await writeLockWhileHeld(lockPath, lock)\n } finally {\n await release()\n }\n}\n\nasync function writeLockWhileHeld(file: string, lock: Lock): Promise<void> {\n let disk: Lock = { version: 2, entries: {} }\n if (existsSync(file)) {\n try {\n disk = parseLock(JSON.parse(await readFile(file, \"utf8\")))\n } catch (err) {\n throw new Error(\n `Refusing to overwrite malformed lockfile at ${file}: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n\n const dirty = dirtyPatches.get(lock) ?? new Map<string, Partial<LockEntry>>()\n const snapshot = new Map<string, Partial<LockEntry>>()\n for (const [key, patch] of dirty) snapshot.set(key, { ...patch })\n\n const merged: Lock[\"entries\"] = { ...disk.entries }\n for (const [key, patch] of snapshot) {\n const local = lock.entries[key]\n if (!local) continue\n merged[key] = merged[key] ? ({ ...merged[key], ...patch } as LockEntry) : local\n }\n // Preserve entries inserted directly by library callers. Production code\n // uses `upsert`, which additionally gives us field-level merge precision.\n for (const [key, entry] of Object.entries(lock.entries)) {\n if (!merged[key]) merged[key] = entry\n }\n\n // Removals are intents, recorded by `remove`, and are applied last. Merging\n // starts from the disk view so a concurrent writer's entries survive, which\n // means a key deleted only from `lock.entries` is read straight back off\n // disk and silently resurrected. Applying deletions after both merge passes\n // is what makes a removal actually stick.\n const deletes = dirtyDeletes.get(lock)\n const deleteSnapshot = deletes ? new Set(deletes) : new Set<string>()\n for (const key of deleteSnapshot) delete merged[key]\n\n const sorted: Lock[\"entries\"] = {}\n for (const key of Object.keys(merged).sort()) {\n sorted[key] = merged[key]!\n }\n const tmp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`\n try {\n await writeFile(tmp, JSON.stringify({ version: 2, entries: sorted }, null, 2) + \"\\n\")\n await rename(tmp, file)\n } finally {\n await rm(tmp, { force: true })\n }\n\n // Clear only fields included in this snapshot. Mutations made while the\n // write awaited I/O remain dirty and are reapplied to the merged disk view.\n const currentDirty = dirtyPatches.get(lock)\n if (currentDirty) {\n for (const [key, patch] of snapshot) {\n const current = currentDirty.get(key)\n if (!current) continue\n for (const [field, value] of Object.entries(patch)) {\n if (Object.is(current[field as keyof LockEntry], value)) {\n delete current[field as keyof LockEntry]\n }\n }\n if (Object.keys(current).length === 0) currentDirty.delete(key)\n }\n }\n\n const stillDirty = dirtyDeletes.get(lock)\n if (stillDirty) {\n for (const key of deleteSnapshot) stillDirty.delete(key)\n if (stillDirty.size === 0) dirtyDeletes.delete(lock)\n }\n\n const localAfterWrite = lock.entries\n lock.entries = { ...merged }\n for (const [key, patch] of currentDirty ?? []) {\n const base = lock.entries[key] ?? localAfterWrite[key]\n if (base) lock.entries[key] = { ...base, ...patch } as LockEntry\n }\n}\n\nexport function upsert(lock: Lock, key: string, patch: Partial<LockEntry>): LockEntry {\n // Re-adding a key cancels any pending removal, or the save would delete the\n // entry that was just written.\n dirtyDeletes.get(lock)?.delete(key)\n const existing = lock.entries[key]\n const next = { ...existing, ...patch } as LockEntry\n lock.entries[key] = next\n let dirty = dirtyPatches.get(lock)\n if (!dirty) {\n dirty = new Map()\n dirtyPatches.set(lock, dirty)\n }\n dirty.set(key, { ...(dirty.get(key) ?? {}), ...patch })\n return next\n}\n\n/**\n * Drop a lock entry, and record the removal so the next save honours it.\n *\n * Deleting from `lock.entries` alone does nothing: `writeLockWhileHeld` merges\n * onto whatever is on disk, so the entry is read back and restored. Callers\n * that need an entry gone must come through here. Returns false when the key\n * was not present, so a caller can tell a no-op from a removal.\n */\nexport function remove(lock: Lock, key: string): boolean {\n if (!lock.entries[key]) return false\n delete lock.entries[key]\n const patches = dirtyPatches.get(lock)\n if (patches) {\n patches.delete(key)\n if (patches.size === 0) dirtyPatches.delete(lock)\n }\n let deletes = dirtyDeletes.get(lock)\n if (!deletes) {\n deletes = new Set()\n dirtyDeletes.set(lock, deletes)\n }\n deletes.add(key)\n return true\n}\n\nconst FILE_LOCK_TIMEOUT_MS = 10_000\nconst STALE_FILE_LOCK_MS = 2 * 60 * 1000\n\nasync function acquireFileLock(file: string): Promise<() => Promise<void>> {\n const lockDir = `${file}.lock`\n const deadline = Date.now() + FILE_LOCK_TIMEOUT_MS\n for (;;) {\n try {\n await mkdir(lockDir)\n return async () => {\n await rmdir(lockDir).catch(() => {})\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code\n if (code !== \"EEXIST\") throw err\n try {\n const age = Date.now() - (await stat(lockDir)).mtimeMs\n if (age > STALE_FILE_LOCK_MS) {\n await rmdir(lockDir)\n continue\n }\n } catch (lockErr) {\n if ((lockErr as NodeJS.ErrnoException).code === \"ENOENT\") continue\n }\n if (Date.now() >= deadline) {\n throw new Error(`Timed out waiting for lockfile writer ${lockDir}`)\n }\n await new Promise((resolve) => setTimeout(resolve, 25 + Math.floor(Math.random() * 25)))\n }\n }\n}\n\n/** Recorded successful-submission estimates, kept separate by provider unit. */\nexport function spendByUnit(lock: Lock): Record<CostUnit, number> {\n const totals: Record<CostUnit, number> = { generations: 0, usd: 0, free: 0 }\n for (const entry of Object.values(lock.entries)) {\n const unit = entry.costUnit ?? \"generations\"\n totals[unit] = (totals[unit] ?? 0) + (entry.cost ?? 0)\n }\n return totals\n}\n\n/** @deprecated Prefer spendByUnit; summing unlike provider units is unsafe. */\nexport function totalSpend(lock: Lock, unit: CostUnit = \"generations\"): number {\n return spendByUnit(lock)[unit] ?? 0\n}\n","import { readFileSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { decodePng, encodeRgbaPng } from \"../png.ts\"\nimport type { Lock } from \"../types.ts\"\nimport { resolveEntryOutputs, resolveOutputPath, selectEntryOutput } from \"../outputs.ts\"\nimport { sha256 } from \"../hash.ts\"\n\nexport interface PackedSource {\n id: string\n /** Absolute source path. Artifact manifests make it relative to themselves. */\n path: string\n /** Null when the source could not be read. */\n sha256: string | null\n /** False when the source was present but could not be decoded or selected. */\n included: boolean\n}\n\nexport interface PackedFrame {\n /** Asset id, so a consumer can look a sprite up by name rather than index. */\n id: string\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface PackedSheet {\n png: Buffer\n atlas: {\n style: string\n sheet: { width: number; height: number }\n /** Uniform cell the grid was laid out on. Frames may be smaller. */\n cell: { width: number; height: number }\n columns: number\n frames: PackedFrame[]\n }\n /** Assets skipped because their file was missing or unreadable. */\n skipped: { id: string; reason: string }[]\n /** Inputs and their exact bytes, for deterministic derived-artifact provenance. */\n sources: PackedSource[]\n}\n\n/**\n * Composites one style's sprites into a single sheet plus a frame atlas.\n *\n * A grid rather than a bin-packer. Every sprite in a style shares a generator\n * and a size, so rectangles are near-uniform and the gain from tight packing\n * is a few percent of area — not worth the loss of a stable, predictable\n * layout. A grid also means a frame's position is derivable from its index,\n * which matters when someone is reading the sheet by eye to debug it.\n *\n * The cell is the largest sprite in the set. Assets can override width/height\n * individually, so assuming uniformity would silently clip the odd one out.\n * Smaller sprites are placed at the cell's top-left and their real dimensions\n * recorded, rather than being centred: centring would bake half-pixel offsets\n * into odd-sized differences, and a consumer that ignores the atlas and slices\n * on the cell grid still gets a correct — if padded — sprite.\n */\nexport interface SpriteInput {\n /** The name this sprite is looked up by in the atlas. */\n id: string\n /** Absolute path to the PNG. */\n path: string\n}\n\n/**\n * Validates and resolves the JSON contract behind `pack --inputs`.\n *\n * A plain function rather than inline in the CLI so it is testable without\n * spawning the binary: `main()` in cli.ts runs at module load and is not\n * exported, so anything left inline there has no seam a test can reach. This\n * is also the only place that needs to know the file is JSON at all — once it\n * returns, everything downstream just deals in `SpriteInput[]`.\n *\n * `entry.path` resolves relative to `inputsFilePath`'s directory, not the\n * process's cwd, so a caller can write the JSON into a scratch directory\n * without rewriting every entry to be absolute. An already-absolute\n * `entry.path` passes through unchanged, since `path.resolve` discards\n * earlier segments once it hits one.\n */\nexport function resolvePackInputs(raw: unknown, inputsFilePath: string): SpriteInput[] {\n if (!Array.isArray(raw) || !raw.length) {\n throw new Error(\"--inputs must be a non-empty JSON array of { id, path }\")\n }\n const baseDir = path.dirname(path.resolve(inputsFilePath))\n return raw.map((entry, i) => {\n const e = entry as { id?: unknown; path?: unknown }\n if (typeof e.id !== \"string\" || typeof e.path !== \"string\") {\n throw new Error(`--inputs[${i}] needs string \"id\" and \"path\"`)\n }\n return { id: e.id, path: path.resolve(baseDir, e.path) }\n })\n}\n\n/**\n * The packing primitive: an explicit list of sprites in, one sheet out.\n *\n * Separate from `packStyle` because the lockfile is not the only way to decide\n * what belongs on a sheet. A consumer may draw from several manifests, or key\n * frames by its own vocabulary rather than by pixelkiln asset ids — heybud's\n * review-form icons do both. Keeping the pixel work here and the \"which files,\n * called what\" decision at the call site avoids teaching this module about\n * anyone else's naming.\n */\nexport function packSprites(\n inputs: SpriteInput[],\n options: { columns?: number; order?: \"id\" | \"input\" } = {},\n): PackedSheet {\n if (!inputs.length) throw new Error(\"packSprites: no sprites given\")\n\n // Two inputs sharing an id would silently produce two frames under the same\n // key, and a consumer doing `frames.find(f => f.id === x)` gets whichever\n // came first with no signal that the other was dropped. Caught here, before\n // any file I/O, rather than left for the next caller to discover the hard\n // way — heybud's own sync script has to dedupe upstream today for exactly\n // this reason (its archetype sources deliberately overlap).\n const seen = new Set<string>()\n const dupes = new Set<string>()\n for (const input of inputs) {\n if (seen.has(input.id)) dupes.add(input.id)\n seen.add(input.id)\n }\n if (dupes.size) {\n throw new Error(`packSprites: duplicate sprite id(s): ${[...dupes].join(\", \")}`)\n }\n\n // Ordinary sprite atlases sort by id so they are byte-identical across\n // runs. Structural sets opt into provider order because their index is part\n // of the format, not presentation.\n const ordered = options.order === \"input\"\n ? [...inputs]\n : [...inputs].sort((a, b) => a.id.localeCompare(b.id))\n\n const sprites: { id: string; width: number; height: number; pixels: Buffer }[] = []\n const skipped: { id: string; reason: string }[] = []\n const sources: PackedSource[] = []\n\n for (const input of ordered) {\n let sourceHash: string | null = null\n try {\n const bytes = readFileSync(input.path)\n sourceHash = sha256(bytes)\n const png = decodePng(bytes)\n sprites.push({ id: input.id, width: png.width, height: png.height, pixels: png.pixels })\n sources.push({ ...input, sha256: sourceHash, included: true })\n } catch (err) {\n skipped.push({ id: input.id, reason: err instanceof Error ? err.message : String(err) })\n sources.push({ ...input, sha256: sourceHash, included: false })\n }\n }\n\n if (!sprites.length) {\n throw new Error(`packSprites: nothing readable — ${skipped.length} skipped.`)\n }\n\n const cellW = Math.max(...sprites.map((s) => s.width))\n const cellH = Math.max(...sprites.map((s) => s.height))\n const columns = options.columns ?? Math.ceil(Math.sqrt(sprites.length))\n const rows = Math.ceil(sprites.length / columns)\n\n const sheetW = columns * cellW\n const sheetH = rows * cellH\n // Zero-filled means fully transparent, which is what the gaps should be.\n const rgba = Buffer.alloc(sheetW * sheetH * 4)\n const frames: PackedFrame[] = []\n\n sprites.forEach((sprite, i) => {\n const ox = (i % columns) * cellW\n const oy = Math.floor(i / columns) * cellH\n for (let y = 0; y < sprite.height; y++) {\n const src = y * sprite.width * 4\n const dst = ((oy + y) * sheetW + ox) * 4\n sprite.pixels.copy(rgba, dst, src, src + sprite.width * 4)\n }\n frames.push({ id: sprite.id, x: ox, y: oy, width: sprite.width, height: sprite.height })\n })\n\n return {\n png: encodeRgbaPng(sheetW, sheetH, rgba),\n atlas: {\n style: \"\",\n sheet: { width: sheetW, height: sheetH },\n cell: { width: cellW, height: cellH },\n columns,\n frames,\n },\n skipped,\n sources,\n }\n}\n\nexport function packStyle(\n lock: Lock,\n styleId: string,\n manifestDir: string,\n options: {\n columns?: number\n outputRoles?: string[]\n primaryOnly?: boolean\n /** Approved manifest quality outputs keyed by asset id or role-qualified frame id. */\n sourceOverrides?: Record<string, string>\n } = {},\n): PackedSheet {\n if (options.sourceOverrides) {\n if (options.outputRoles?.length) {\n throw new Error(\"Quality-profile packing does not accept --output-role; profiles own final output selection.\")\n }\n const inputs = Object.entries(options.sourceOverrides).map(([id, source]) => ({\n id,\n path: path.resolve(source),\n }))\n if (!inputs.length) throw new Error(`No approved quality outputs for style \"${styleId}\".`)\n const packed = packSprites(inputs, options)\n return { ...packed, atlas: { ...packed.atlas, style: styleId } }\n }\n\n // Lock keys are `<styleId>/<assetId>`.\n const prefix = `${styleId}/`\n const entries = Object.entries(lock.entries).filter(([key]) => key.startsWith(prefix))\n\n if (!entries.length) {\n throw new Error(\n `No locked assets for style \"${styleId}\". Run \\`pixelkiln gen --style ${styleId}\\` first.`,\n )\n }\n\n const inputs: SpriteInput[] = []\n const noOutput: { id: string; reason: string }[] = []\n\n for (const [key, entry] of entries) {\n const id = key.slice(prefix.length)\n const outputs = resolveEntryOutputs(entry, id, manifestDir)\n let selected = outputs\n if (options.outputRoles?.length) {\n selected = outputs.filter(\n (output) => output.role && options.outputRoles!.includes(output.role),\n )\n } else if (options.primaryOnly) {\n const selection = selectEntryOutput(entry)\n selected = selection.ok\n ? outputs.filter((output) => output.path === selection.output.path)\n : []\n }\n if (!selected.length) {\n const reason = options.outputRoles?.length\n ? `no output matches role(s): ${options.outputRoles.join(\", \")}`\n : options.primaryOnly && outputs.length > 1\n ? \"no unambiguous primary output; use --output-role\"\n : \"no output recorded in the lockfile\"\n noOutput.push({ id, reason })\n continue\n }\n for (const output of selected) inputs.push({ id: output.id, path: output.absolutePath })\n }\n\n if (!inputs.length) {\n throw new Error(`No readable sprites for style \"${styleId}\" — ${noOutput.length} skipped.`)\n }\n\n const packed = packSprites(inputs, options)\n return {\n ...packed,\n atlas: { ...packed.atlas, style: styleId },\n skipped: [...noOutput, ...packed.skipped],\n }\n}\n\nexport interface MountPlacement extends SpriteInput {\n /** Grid cell this sprite owns, as [column, row]. */\n cell: [number, number]\n}\n\nexport interface MountedSheet {\n png: Buffer\n atlas: {\n style: string\n sheet: { width: number; height: number }\n cell: { width: number; height: number }\n frames: PackedFrame[]\n }\n skipped: { id: string; reason: string }[]\n /** Inputs and their exact bytes, for deterministic derived-artifact provenance. */\n sources: PackedSource[]\n /** True when an existing sheet was composited into rather than replaced. */\n overBase: boolean\n}\n\n/**\n * Places sprites at *declared* grid cells, optionally into an existing sheet.\n *\n * The sibling of `packSprites`, for the case its layout rules cannot serve.\n * `packSprites` derives position from index and sorts by asset id so the sheet\n * is byte-stable — excellent when pixelkiln owns the whole sheet, and fatal\n * when it does not. A consumer whose atlas coordinates are already load-bearing\n * (a tile engine naming tiles by cell, a scene file storing cell indices in\n * saved data) cannot accept a layout that moves when an asset is added or\n * renamed: every existing reference would silently point at different art.\n *\n * So here the caller declares the cell and pixelkiln honours it. Two\n * consequences worth stating:\n *\n * - **Only declared cells are touched.** With a `base` sheet, every other\n * pixel survives byte-for-byte, so a hand-authored sheet can be part\n * generated and part drawn without the generated half claiming the file.\n * - **A cell is replaced, not blended.** The sprite owns its cell, so the\n * cell is cleared first. Compositing instead would make a regenerated\n * tile show through to whatever it replaced, and the residue would be\n * invisible until it shipped.\n *\n * Sprites larger than the cell are a declaration error, not something to crop\n * silently — cropping would produce a sheet that looks right in isolation and\n * is wrong at every seam.\n */\nexport function mountSprites(\n placements: MountPlacement[],\n options: { cellWidth: number; cellHeight: number; basePng?: Buffer },\n): MountedSheet {\n if (!placements.length) throw new Error(\"mountSprites: no sprites given\")\n const { cellWidth, cellHeight } = options\n if (cellWidth <= 0 || cellHeight <= 0) {\n throw new Error(\"mountSprites: cell dimensions must be positive\")\n }\n\n const byCell = new Map<string, string>()\n for (const p of placements) {\n const key = `${p.cell[0]},${p.cell[1]}`\n const owner = byCell.get(key)\n if (owner) {\n throw new Error(\n `mountSprites: \"${p.id}\" and \"${owner}\" both claim cell ${key} — ` +\n `a cell has exactly one owner`,\n )\n }\n byCell.set(key, p.id)\n }\n\n const loaded: { p: MountPlacement; width: number; height: number; pixels: Buffer }[] = []\n const skipped: { id: string; reason: string }[] = []\n const sources: PackedSource[] = []\n for (const p of placements) {\n let sourceHash: string | null = null\n try {\n const bytes = readFileSync(p.path)\n sourceHash = sha256(bytes)\n const png = decodePng(bytes)\n if (png.width > cellWidth || png.height > cellHeight) {\n throw new Error(\n `is ${png.width}x${png.height}, larger than the ${cellWidth}x${cellHeight} cell`,\n )\n }\n loaded.push({ p, width: png.width, height: png.height, pixels: png.pixels })\n sources.push({ id: p.id, path: p.path, sha256: sourceHash, included: true })\n } catch (err) {\n skipped.push({ id: p.id, reason: err instanceof Error ? err.message : String(err) })\n sources.push({ id: p.id, path: p.path, sha256: sourceHash, included: false })\n }\n }\n if (!loaded.length) {\n throw new Error(`mountSprites: nothing readable — ${skipped.length} skipped.`)\n }\n\n // The sheet must cover the base if there is one, and every declared cell\n // either way — a cell past the base's edge grows it rather than failing,\n // so adding a row of tiles does not need the base redrawn first.\n const maxCol = Math.max(...loaded.map((l) => l.p.cell[0]))\n const maxRow = Math.max(...loaded.map((l) => l.p.cell[1]))\n const base = options.basePng ? decodePng(options.basePng) : null\n const sheetW = Math.max((maxCol + 1) * cellWidth, base?.width ?? 0)\n const sheetH = Math.max((maxRow + 1) * cellHeight, base?.height ?? 0)\n\n const rgba = Buffer.alloc(sheetW * sheetH * 4)\n if (base) {\n for (let y = 0; y < base.height; y++) {\n const src = y * base.width * 4\n base.pixels.copy(rgba, y * sheetW * 4, src, src + base.width * 4)\n }\n }\n\n const frames: PackedFrame[] = []\n for (const { p, width, height, pixels } of loaded) {\n const ox = p.cell[0] * cellWidth\n const oy = p.cell[1] * cellHeight\n // Clear the whole cell before writing: the sprite owns it, and leaving the\n // base showing around a smaller sprite is the \"invisible until it ships\"\n // failure this function exists to avoid.\n for (let y = 0; y < cellHeight; y++) {\n rgba.fill(0, ((oy + y) * sheetW + ox) * 4, ((oy + y) * sheetW + ox + cellWidth) * 4)\n }\n for (let y = 0; y < height; y++) {\n const src = y * width * 4\n pixels.copy(rgba, ((oy + y) * sheetW + ox) * 4, src, src + width * 4)\n }\n frames.push({ id: p.id, x: ox, y: oy, width, height })\n }\n\n frames.sort((a, b) => a.y - b.y || a.x - b.x)\n return {\n png: encodeRgbaPng(sheetW, sheetH, rgba),\n atlas: {\n style: \"\",\n sheet: { width: sheetW, height: sheetH },\n cell: { width: cellWidth, height: cellHeight },\n frames,\n },\n skipped,\n sources,\n overBase: base !== null,\n }\n}\n\n/**\n * `mountSprites` driven by the lockfile and the manifest's `mount` block.\n *\n * The manifest is the source of cells rather than the lockfile: a cell is a\n * declaration about where art belongs, not a record of what was generated, and\n * it has to be readable and editable before anything has been generated at all.\n */\nexport function mountStyle(\n lock: Lock,\n styleId: string,\n manifestDir: string,\n mount: { base?: string; cellWidth: number; cellHeight: number },\n cells: Record<string, [number, number]>,\n sources: Record<string, string> = {},\n outputRoles: Record<string, string> = {},\n): MountedSheet {\n // Driven by the declared cells, not by the lockfile. The cell is what says\n // \"this belongs on the sheet\"; whether pixelkiln generated the pixels is a\n // separate question, and `source` assets answer it with a file on disk.\n const ids = Object.keys(cells)\n if (!ids.length) {\n throw new Error(\n `No assets in style \"${styleId}\" declare a \\`cell\\`. Add one to each asset ` +\n `that belongs on the sheet.`,\n )\n }\n\n const placements: MountPlacement[] = []\n const skipped: { id: string; reason: string }[] = []\n for (const id of ids) {\n const cell = cells[id]!\n const source = sources[id]\n if (source) {\n placements.push({ id, path: path.resolve(manifestDir, source), cell })\n continue\n }\n const entry = lock.entries[`${styleId}/${id}`]\n if (!entry) {\n skipped.push({\n id,\n reason: `not generated in style \"${styleId}\", and no \\`source\\` declared`,\n })\n continue\n }\n const selection = selectEntryOutput(entry, outputRoles[id])\n if (!selection.ok) {\n skipped.push({ id, reason: selection.reason })\n continue\n }\n placements.push({ id, path: resolveOutputPath(selection.output.path, manifestDir), cell })\n }\n\n if (!placements.length) {\n const detail = skipped.length\n ? ` (${skipped.map((item) => `${item.id}: ${item.reason}`).join(\"; \")})`\n : \"\"\n throw new Error(\n `Nothing to mount for style \"${styleId}\": ${ids.length} asset(s) declare a ` +\n `cell, but none has generated output or a \\`source\\`. Run ` +\n `\\`pixelkiln gen --style ${styleId}\\`, or point each at a file.${detail}`,\n )\n }\n\n const basePng = mount.base ? readFileSync(path.resolve(manifestDir, mount.base)) : undefined\n const mounted = mountSprites(placements, {\n cellWidth: mount.cellWidth,\n cellHeight: mount.cellHeight,\n basePng,\n })\n return {\n ...mounted,\n sources: mount.base\n ? [{\n id: \"$base\",\n path: path.resolve(manifestDir, mount.base),\n sha256: sha256(basePng!),\n included: true,\n }, ...mounted.sources]\n : mounted.sources,\n atlas: { ...mounted.atlas, style: styleId },\n skipped: [...skipped, ...mounted.skipped],\n }\n}\n","import { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { sha256File } from \"../hash.ts\"\nimport { currentEntryOutputPath } from \"../outputs.ts\"\nimport { lockKey, type Lock, type LockEntry, type ResolvedSpec } from \"../types.ts\"\nimport type { CostUnit } from \"../provider.ts\"\nimport { inspectQualityProfile, type QualityProfileInspection } from \"./quality-profile.ts\"\nimport { inspectRevisionReadiness } from \"./revision.ts\"\n\nexport type PlanState =\n | \"ok\" // spec unchanged, file present and matching — nothing to do\n | \"missing\" // no lock entry and no file — genuinely needs generating\n | \"untracked\" // file exists but has no lock entry; the art is fine, provenance is not known\n | \"stale\" // prompt/style/size changed since the file was made\n | \"orphaned\" // the bytes that should be on disk are gone or altered\n | \"in-flight\" // submitted, not yet downloaded\n | \"recoverable\" // generation succeeded; download can be retried without spending\n | \"blocked\" // a declared revision input is missing, stale, or not approved\n | \"failed\"\n\n/**\n * True if any recorded output no longer hashes to what was written.\n *\n * Checked across every output, not just the primary: a character's engine\n * resource being hand-edited matters as much as its spritesheets changing.\n */\nasync function anyOutputModified(entry: LockEntry, spec: ResolvedSpec): Promise<boolean> {\n for (let index = 0; index < entry.outputs.length; index++) {\n const output = entry.outputs[index]!\n if (\n (await sha256File(currentEntryOutputPath(entry, spec, index))) !== output.sha256\n ) return true\n }\n return false\n}\n\nexport interface PlanItem {\n spec: ResolvedSpec\n key: string\n state: PlanState\n reason: string\n /** Derived-art state. It never changes provider cost or generation actionability. */\n quality?: QualityProfileInspection\n}\n\nexport interface Plan {\n items: PlanItem[]\n /** Items that would incur provider cost if the plan were executed. */\n actionable: PlanItem[]\n /** Provider-scoped totals. Unlike units and accounts are never combined. */\n groups: PlanGroup[]\n /** Compatibility projection for a single provider group; null for mixed plans. */\n cost: number | null\n /** Compatibility projection for a single provider group; null for mixed plans. */\n costUnit: CostUnit | null\n candidates: number\n}\n\nexport interface PlanGroup {\n provider: string\n costUnit: CostUnit\n cost: number\n candidates: number\n actionable: PlanItem[]\n}\n\nexport type ResumeCommand = \"poll\" | \"pick\" | \"fetch\"\n\nexport interface ResumeAction {\n command: ResumeCommand\n keys: string[]\n}\n\n/** The zero-cost command that advances one settled lock state. */\nexport function resumeCommandForStatus(\n status: LockEntry[\"status\"],\n): ResumeCommand | null {\n if (status === \"pending\" || status === \"processing\") return \"poll\"\n if (status === \"review\") return \"pick\"\n if (status === \"selected\" || status === \"download-failed\") return \"fetch\"\n return null\n}\n\n/** Group current selected specs by the command that can resume them safely. */\nexport function resumeActions(specs: ResolvedSpec[], lock: Lock): ResumeAction[] {\n const grouped = new Map<ResumeCommand, string[]>()\n for (const spec of specs) {\n const key = lockKey(spec.styleId, spec.assetId)\n const entry = lock.entries[key]\n if (!entry || entry.specHash !== spec.specHash) continue\n const command = resumeCommandForStatus(entry.status)\n if (!command) continue\n if (command === \"poll\" && !entry.jobId) continue\n if (command === \"pick\" && !entry.reviewObjectId) continue\n grouped.set(command, [...(grouped.get(command) ?? []), key])\n }\n return ([\"poll\", \"pick\", \"fetch\"] as const).flatMap((command) => {\n const keys = grouped.get(command)\n return keys?.length ? [{ command, keys }] : []\n })\n}\n\n/**\n * Diffs the manifest against the lockfile and the files on disk. Nothing here\n * touches the network, so it is safe to run constantly — it is the cheap\n * \"what would this cost me?\" question that should precede every real run.\n */\nexport async function buildPlan(\n specs: ResolvedSpec[],\n lock: Lock,\n opts: { force?: boolean } = {},\n): Promise<Plan> {\n const items: PlanItem[] = []\n\n for (const spec of specs) {\n const key = lockKey(spec.styleId, spec.assetId)\n const entry = lock.entries[key]\n\n let state: PlanState\n let reason: string\n\n const revision = await inspectRevisionReadiness(spec, lock)\n if (revision && !revision.ready) {\n state = \"blocked\"\n reason = revision.reason\n } else if (opts.force) {\n state = \"missing\"\n reason = \"--force\"\n } else if (!entry && spec.source) {\n // An asset with a `source` is placed from committed art by `mount`, and\n // AssetSchema.source says it needs no lock entry at all. Treating it as\n // `missing` puts art pixelkiln did not make and will never generate into\n // the actionable list, and bills a generation cost for each one.\n if (existsSync(path.resolve(spec.root, spec.source))) {\n state = \"ok\"\n reason = `placed from ${spec.source}; not generated`\n } else {\n state = \"orphaned\"\n reason = `declared source is missing: ${spec.source}`\n }\n } else if (!entry) {\n // Distinguish \"no art\" from \"art exists but unmatched upstream\". Calling\n // the latter `missing` invites regenerating perfectly good files — which\n // is exactly what happens to assets that were retouched by hand after\n // download, since their bytes no longer match any remote object.\n if (existsSync(spec.outFile)) {\n state = \"untracked\"\n reason = \"file on disk, no provenance recorded\"\n } else {\n state = \"missing\"\n reason = \"not in lockfile\"\n }\n } else if (entry.specHash !== spec.specHash) {\n state = \"stale\"\n reason = \"prompt, size, or style changed\"\n } else if (entry.status === \"download-failed\") {\n state = \"recoverable\"\n const force = entry.error?.includes(\"pass --force\") ? \" --force\" : \"\"\n reason =\n `${entry.error ?? \"download failed\"}; run pixelkiln fetch${force} ` +\n \"(no generation cost)\"\n } else if (entry.status === \"failed\") {\n state = \"failed\"\n reason = entry.error ?? \"previous attempt failed\"\n } else if (entry.status === \"selected\") {\n state = \"recoverable\"\n reason = \"provider output is selected; run pixelkiln fetch (no generation cost)\"\n } else if (entry.status === \"pending\" || entry.status === \"processing\") {\n state = \"in-flight\"\n reason = entry.jobId\n ? \"awaiting processing; run pixelkiln poll\"\n : \"submission state has no job id; run pixelkiln doctor before retrying\"\n } else if (entry.status === \"review\") {\n state = \"in-flight\"\n reason = entry.reviewObjectId\n ? \"awaiting review; run pixelkiln pick\"\n : \"review state has no review object id; run pixelkiln doctor\"\n } else if (entry.status !== \"downloaded\") {\n state = \"in-flight\"\n reason = `awaiting ${entry.status}`\n } else if (\n entry.outputs.length === 0 ||\n entry.outputs.some((_output, index) =>\n !existsSync(currentEntryOutputPath(entry, spec, index)))\n ) {\n state = \"orphaned\"\n reason =\n entry.outputs.length === 0\n ? \"no recorded output files\"\n : `missing on disk: ${entry.outputs\n .filter((_output, index) =>\n !existsSync(currentEntryOutputPath(entry, spec, index)))\n .map((o) => o.role ?? \"asset\")\n .join(\", \")}`\n } else if (await anyOutputModified(entry, spec)) {\n // The file was edited by hand. That is a legitimate thing to do, so this\n // is reported rather than silently overwritten.\n state = \"orphaned\"\n reason = \"output modified since download\"\n } else {\n state = \"ok\"\n reason = \"up to date\"\n }\n\n const quality = await inspectQualityProfile(spec, lock)\n items.push({ spec, key, state, reason, ...(quality ? { quality } : {}) })\n }\n\n // \"orphaned\" entries may be re-downloadable from a persisted object without\n // paying again; only genuinely new work is counted toward cost.\n const actionable = items.filter((i) => i.state === \"missing\" || i.state === \"stale\" || i.state === \"failed\")\n const groupsByProvider = new Map<string, PlanGroup>()\n for (const item of actionable) {\n const provider = item.spec.provider\n const costUnit = item.spec.costUnit ?? \"generations\"\n const group = groupsByProvider.get(provider)\n if (group && group.costUnit !== costUnit) {\n throw new Error(\n `Provider \"${provider}\" returned mixed cost units (${group.costUnit}, ${costUnit})`,\n )\n }\n if (group) {\n group.actionable.push(item)\n group.cost += item.spec.cost\n group.candidates += item.spec.candidates\n } else {\n groupsByProvider.set(provider, {\n provider,\n costUnit,\n cost: item.spec.cost,\n candidates: item.spec.candidates,\n actionable: [item],\n })\n }\n }\n const groups = [...groupsByProvider.values()].sort((a, b) => a.provider.localeCompare(b.provider))\n const fallbackUnits = new Set(specs.map((spec) => spec.costUnit))\n const single = groups.length === 1 ? groups[0]! : null\n\n return {\n items,\n actionable,\n groups,\n cost: single?.cost ?? (groups.length ? null : 0),\n costUnit: single?.costUnit ?? (groups.length || fallbackUnits.size > 1\n ? null\n : fallbackUnits.values().next().value ?? (specs.length ? \"generations\" : \"free\")),\n candidates: actionable.reduce((sum, i) => sum + i.spec.candidates, 0),\n }\n}\n\nexport function summarize(plan: Plan): Record<PlanState, number> {\n const counts = {\n ok: 0, missing: 0, untracked: 0, stale: 0, orphaned: 0, \"in-flight\": 0,\n recoverable: 0, blocked: 0, failed: 0,\n } as Record<PlanState, number>\n for (const item of plan.items) counts[item.state]++\n return counts\n}\n","import { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { sha256File } from \"../hash.ts\"\nimport { MediaType } from \"../media.ts\"\nimport { currentEntryOutputPath } from \"../outputs.ts\"\nimport { lockKey, type Lock, type ResolvedSpec } from \"../types.ts\"\nimport {\n PIXEL_ART_FIXER_REVISION,\n checkQualityRecord,\n normalizeRefinementPalette,\n qualityFrameOutputPath,\n qualityRecordPath,\n refineAsset,\n refineFrameSet,\n} from \"./refine.ts\"\n\nexport type QualityProfileState =\n | \"blocked\"\n | \"needs-refinement\"\n | \"needs-approval\"\n | \"approved\"\n\nexport interface QualityProfileInspection {\n key: string\n state: QualityProfileState\n reason: string\n source: string | null\n sources?: string[]\n output: string\n outputs?: string[]\n record: string\n}\n\nexport interface RefineQualityProfilesOptions {\n fixerPython?: string\n force?: boolean\n /** @internal Alternate fixer command used by compatibility tests. */\n fixerCommand?: string\n /** @internal Prefix arguments for the alternate fixer command. */\n fixerArgsPrefix?: string[]\n}\n\nexport interface RefineQualityProfilesResult {\n processed: number\n skipped: number\n failed: number\n items: QualityProfileInspection[]\n}\n\ninterface QualitySource {\n items: Array<{ role: string; path: string }> | null\n reason?: string\n}\n\nasync function qualitySource(spec: ResolvedSpec, lock: Lock): Promise<QualitySource> {\n if (spec.source) {\n if (spec.generator === \"frames\") {\n return { items: null, reason: \"frame-set quality requires ordered downloaded provider outputs\" }\n }\n const source = path.resolve(spec.root, spec.source)\n return existsSync(source)\n ? { items: [{ role: \"source\", path: source }] }\n : { items: null, reason: `declared source is missing: ${spec.source}` }\n }\n\n const entry = lock.entries[lockKey(spec.styleId, spec.assetId)]\n if (!entry) return { items: null, reason: \"raw provider output is not in the lockfile\" }\n if (entry.specHash !== spec.specHash) {\n return { items: null, reason: \"raw provider output does not match the current generation spec\" }\n }\n if (entry.status !== \"downloaded\") {\n return { items: null, reason: `raw provider output is ${entry.status}, not downloaded` }\n }\n const frameSet = spec.generator === \"frames\"\n if ((!frameSet && entry.outputs.length !== 1) || (frameSet && entry.outputs.length < 2)) {\n return {\n items: null,\n reason: frameSet\n ? `frame-set quality requires at least two PNG outputs; lock entry has ${entry.outputs.length}`\n : `quality profiles require one PNG output; lock entry has ${entry.outputs.length}`,\n }\n }\n const roles = new Set<string>()\n const items: Array<{ role: string; path: string }> = []\n for (const [index, output] of entry.outputs.entries()) {\n if (output.mediaType && output.mediaType !== MediaType.PNG) {\n return { items: null, reason: `quality profiles require PNG input; lock entry is ${output.mediaType}` }\n }\n const role = frameSet ? output.role : \"source\"\n if (frameSet && (!role || roles.has(role))) {\n return { items: null, reason: \"frame-set quality requires a unique role for every ordered output\" }\n }\n if (role) roles.add(role)\n const source = currentEntryOutputPath(entry, spec, index)\n if (!existsSync(source)) return { items: null, reason: `raw provider output is missing: ${source}` }\n if ((await sha256File(source)) !== output.sha256) {\n return { items: null, reason: \"raw provider output was modified after download\" }\n }\n items.push({ role: role!, path: source })\n }\n return { items }\n}\n\n/** Inspect one configured quality output without changing files or contacting a provider. */\nexport async function inspectQualityProfile(\n spec: ResolvedSpec,\n lock: Lock,\n): Promise<QualityProfileInspection | null> {\n if (!spec.quality) return null\n const key = lockKey(spec.styleId, spec.assetId)\n const output = spec.quality.outFile\n const record = qualityRecordPath(output)\n const source = await qualitySource(spec, lock)\n if (!source.items) {\n return { key, state: \"blocked\", reason: source.reason!, source: null, output, record }\n }\n const sourcePaths = source.items.map((item) => item.path)\n const expectedOutputs = spec.generator === \"frames\"\n ? source.items.map((item, index) => qualityFrameOutputPath(output, item.role, index))\n : [output]\n if (!existsSync(record)) {\n return {\n key,\n state: \"needs-refinement\",\n reason: \"no refinement record\",\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n }\n\n try {\n const check = await checkQualityRecord(record)\n const expectedPalette = normalizeRefinementPalette(spec.quality.palette)\n const expectedRevision = spec.quality.fixerRevision ?? PIXEL_ART_FIXER_REVISION\n const expectedTransparency = spec.quality.minTransparency ?? null\n const expectedFrameSet = spec.generator === \"frames\"\n ? { fps: spec.quality.fps ?? 12, count: source.items.length, roles: source.items.map((item) => item.role) }\n : null\n const contractChanged =\n JSON.stringify(check.sources.map((item) => path.resolve(item))) !==\n JSON.stringify(sourcePaths.map((item) => path.resolve(item))) ||\n JSON.stringify(check.outputs.map((item) => path.resolve(item))) !==\n JSON.stringify(expectedOutputs.map((item) => path.resolve(item))) ||\n JSON.stringify(check.options.palette.colors) !== JSON.stringify(expectedPalette) ||\n check.options.nativeGrid.revision !== expectedRevision ||\n check.options.audit.thresholds.minGridConfidence !== spec.quality.minGridConfidence ||\n check.options.audit.thresholds.minTransparency !== expectedTransparency ||\n (expectedFrameSet\n ? !check.options.frameSet ||\n check.options.frameSet.fps !== expectedFrameSet.fps ||\n check.options.frameSet.count !== expectedFrameSet.count ||\n JSON.stringify(check.options.frameSet.roles) !== JSON.stringify(expectedFrameSet.roles)\n : check.options.frameSet !== undefined)\n\n if (contractChanged) {\n return {\n key,\n state: \"needs-refinement\",\n reason: \"quality profile changed\",\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n }\n if (!check.current || !check.auditSafe) {\n return {\n key,\n state: \"needs-refinement\",\n reason: check.reasons.filter((reason) => reason !== \"human 1× review is pending\").join(\"; \") ||\n \"refinement record is stale\",\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n }\n if (!check.approved) {\n return {\n key,\n state: \"needs-approval\",\n reason: \"automated checks passed; human 1× review is pending\",\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n }\n return {\n key,\n state: \"approved\",\n reason: \"refined output and human approval are current\",\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n } catch (error) {\n return {\n key,\n state: \"needs-refinement\",\n reason: `invalid refinement record: ${error instanceof Error ? error.message : String(error)}`,\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n }\n}\n\n/** Refine every configured, selected asset while preserving current approvals. */\nexport async function refineQualityProfiles(\n specs: ResolvedSpec[],\n lock: Lock,\n options: RefineQualityProfilesOptions = {},\n): Promise<RefineQualityProfilesResult> {\n const configured = specs.filter((spec) => spec.quality)\n if (!configured.length) {\n throw new Error(\"No selected style has a quality profile.\")\n }\n\n const result: RefineQualityProfilesResult = { processed: 0, skipped: 0, failed: 0, items: [] }\n for (const spec of configured) {\n const inspection = (await inspectQualityProfile(spec, lock))!\n if (!options.force && (inspection.state === \"approved\" || inspection.state === \"needs-approval\")) {\n result.skipped++\n result.items.push(inspection)\n continue\n }\n if (inspection.state === \"blocked\") {\n result.failed++\n result.items.push(inspection)\n continue\n }\n try {\n const common = {\n output: inspection.output,\n palette: spec.quality!.palette,\n minGridConfidence: spec.quality!.minGridConfidence,\n ...(spec.quality!.minTransparency == null\n ? {}\n : { minTransparency: spec.quality!.minTransparency }),\n fixerRevision: spec.quality!.fixerRevision ?? PIXEL_ART_FIXER_REVISION,\n // A one-off CLI/library override wins; otherwise each style can carry\n // the stable project-local interpreter that provides its pinned fixer.\n fixerPython: options.fixerPython ?? spec.quality!.fixerPython,\n fixerCommand: options.fixerCommand,\n fixerArgsPrefix: options.fixerArgsPrefix,\n force: options.force,\n }\n if (spec.generator === \"frames\") {\n const frameSources = await qualitySource(spec, lock)\n if (!frameSources.items) throw new Error(frameSources.reason)\n await refineFrameSet({\n ...common,\n sources: frameSources.items,\n fps: spec.quality!.fps ?? 12,\n })\n } else {\n await refineAsset({ ...common, source: inspection.source! })\n }\n result.processed++\n result.items.push((await inspectQualityProfile(spec, lock))!)\n } catch (error) {\n result.failed++\n result.items.push({\n ...inspection,\n state: \"needs-refinement\",\n reason: error instanceof Error ? error.message : String(error),\n })\n }\n }\n return result\n}\n\n/** Return approved derived files for a packaging command, or fail closed. */\nexport async function requireApprovedQualitySources(\n specs: ResolvedSpec[],\n lock: Lock,\n assetIds?: ReadonlySet<string>,\n outputRoles?: Readonly<Record<string, string>>,\n): Promise<Record<string, string> | undefined> {\n const configured = specs.filter(\n (spec) => spec.quality && (!assetIds || assetIds.has(spec.assetId)),\n )\n if (!configured.length) return undefined\n\n const sources: Record<string, string> = {}\n const rejected: QualityProfileInspection[] = []\n for (const spec of configured) {\n const inspection = (await inspectQualityProfile(spec, lock))!\n if (inspection.state === \"approved\") {\n if (spec.generator === \"frames\") {\n const check = await checkQualityRecord(inspection.record)\n const roles = check.options.frameSet!.roles\n if (outputRoles) {\n const selectedRole = outputRoles[spec.assetId]\n if (!selectedRole) {\n throw new Error(\n `Mounting quality-approved frame set ${inspection.key} requires asset.outputRole.`,\n )\n }\n const index = roles.indexOf(selectedRole)\n if (index < 0) {\n throw new Error(\n `Frame set ${inspection.key} has no approved output role \"${selectedRole}\".`,\n )\n }\n sources[spec.assetId] = check.outputs[index]!\n } else {\n for (const [index, output] of check.outputs.entries()) {\n sources[`${spec.assetId}/${roles[index]}`] = output\n }\n }\n } else {\n sources[spec.assetId] = inspection.output\n }\n } else rejected.push(inspection)\n }\n if (rejected.length) {\n const detail = rejected\n .slice(0, 5)\n .map((item) => `${item.key}: ${item.state} (${item.reason})`)\n .join(\"; \")\n throw new Error(\n `Packaging requires current, human-approved quality output: ${detail}. ` +\n \"Run `pixelkiln refine`, review each PNG, then run `pixelkiln refine approve --from <record> --reviewer <name>`.\",\n )\n }\n return sources\n}\n","import path from \"node:path\"\nimport { execFile } from \"node:child_process\"\nimport { mkdtemp, readFile, rm } from \"node:fs/promises\"\nimport { tmpdir } from \"node:os\"\nimport { promisify } from \"node:util\"\nimport {\n readArtifactBundleManifest,\n verifyArtifactBundle,\n writeManagedArtifactBundle,\n type ArtifactBundleManifest,\n type ArtifactSource,\n} from \"../artifacts.ts\"\nimport { sha256File } from \"../hash.ts\"\nimport {\n decodePng,\n encodeRgbaPng,\n parseHex,\n transparencyRatio,\n type DecodedPng,\n} from \"../png.ts\"\nimport type { GridConfidence } from \"../types.ts\"\nimport { colorDistance } from \"./audit.ts\"\n\nconst execFileAsync = promisify(execFile)\n\nconst PIXEL_ART_FIXER_MIN_SIDE = 16\nconst PIXEL_ART_FIXER_MAX_PIXELS = 4_000_000\n\nexport const PIXEL_ART_FIXER_URL = \"https://github.com/Retro-Diffusion/pixel-art-fixer\"\nexport const PIXEL_ART_FIXER_REVISION = \"ef376e57e1c272633ca2dbf5f29ec3fcf6596465\"\n\nexport interface PixelArtFixerDetection {\n stepX: number\n stepY: number\n phaseX: number\n phaseY: number\n columns: number\n rows: number\n consensus: string\n confidence: GridConfidence\n}\n\nexport interface RefineAudit {\n width: number\n height: number\n colorCount: number\n paletteConformant: boolean\n transparency: number\n thresholds: {\n maxColors: number\n minTransparency: number | null\n minGridConfidence: GridConfidence\n }\n safe: boolean\n reasons: string[]\n}\n\nexport interface PendingQualityReview {\n status: \"pending\"\n}\n\nexport interface ApprovedQualityReview {\n status: \"approved\"\n reviewer: string\n approvedAt: string\n checklist: {\n nativeScale: true\n crispEdges: true\n subjectReadable: true\n paletteSeparation: true\n alphaAndSeams: true\n }\n note?: string\n}\n\nexport interface RefineRecordOptions {\n schema: \"pixelkiln-quality\"\n version: 1\n nativeGrid: {\n tool: \"pixel-art-fixer\"\n url: typeof PIXEL_ART_FIXER_URL\n revision: string\n protocol: \"python-api-v1\" | \"python-core-v1\" | \"python-cli-v1\"\n confidence: GridConfidence\n consensus: string\n stepX: number\n stepY: number\n /** Detector phase in source pixels. Older v1 single-image records omit it. */\n phaseX?: number\n phaseY?: number\n sourceWidth: number\n sourceHeight: number\n nativeWidth: number\n nativeHeight: number\n }\n palette: {\n colors: string[]\n dither: \"none\"\n distance: \"redmean\"\n }\n audit: RefineAudit\n review: PendingQualityReview | ApprovedQualityReview\n /** Present when one approval covers an ordered, jointly verified frame set. */\n frameSet?: {\n fps: number\n count: number\n roles: string[]\n frames: Array<{\n role: string\n sourceWidth: number\n sourceHeight: number\n detection: PixelArtFixerDetection\n audit: RefineAudit\n }>\n }\n}\n\nexport interface RefineOptions {\n source: string\n output: string\n palette: string[]\n /** Python containing `pixelfixer`. Defaults to the environment override or `python3`. */\n fixerPython?: string\n /** @internal Alternate Pixel Art Fixer console command used by compatibility tests. */\n fixerCommand?: string\n /** @internal Prefix arguments for the alternate console command. */\n fixerArgsPrefix?: string[]\n fixerRevision?: string\n minGridConfidence?: GridConfidence\n minTransparency?: number\n force?: boolean\n}\n\nexport interface RefineResult {\n source: string\n output: string\n record: string\n detection: PixelArtFixerDetection\n palette: string[]\n audit: RefineAudit\n}\n\nexport interface RefineFrameSetOptions {\n sources: Array<{ role: string; path: string }>\n /** Virtual .png stem used to derive numbered outputs and the shared record. */\n output: string\n fps: number\n palette: string[]\n fixerPython?: string\n fixerCommand?: string\n fixerArgsPrefix?: string[]\n fixerRevision?: string\n minGridConfidence?: GridConfidence\n minTransparency?: number\n force?: boolean\n}\n\nexport interface RefineFrameSetResult {\n sources: string[]\n outputs: string[]\n record: string\n frames: Array<{\n role: string\n sourceWidth: number\n sourceHeight: number\n detection: PixelArtFixerDetection\n audit: RefineAudit\n }>\n palette: string[]\n audit: RefineAudit\n}\n\nexport interface QualityCheck {\n safe: boolean\n current: boolean\n approved: boolean\n auditSafe: boolean\n record: string\n source: string\n output: string\n sources: string[]\n outputs: string[]\n options: RefineRecordOptions\n reasons: string[]\n}\n\nexport interface ApproveQualityOptions {\n reviewer: string\n note?: string\n /** Deterministic clock hook for callers that need reproducible tests. */\n approvedAt?: Date\n}\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nexport function qualityRecordPath(output: string): string {\n if (!/\\.png$/i.test(output)) throw new Error(\"Refined output must be a .png file.\")\n return output.replace(/\\.png$/i, \".pixelkiln.json\")\n}\n\nfunction confidenceFor(consensus: string): GridConfidence {\n if (consensus.startsWith(\"fast:\")) return \"high\"\n if (\n consensus === \"arbitrated\" ||\n consensus === \"forced\" ||\n (consensus.startsWith(\"fastmode:\") && consensus.includes(\"+\"))\n ) return \"medium\"\n return \"low\"\n}\n\nconst confidenceRank: Record<GridConfidence, number> = { low: 0, medium: 1, high: 2 }\n\nfunction requireConfidence(value: string): GridConfidence {\n if (value === \"low\" || value === \"medium\" || value === \"high\") return value\n throw new Error(`Unknown grid confidence \"${value}\"; expected low, medium, or high.`)\n}\n\nfunction firstJsonObject(text: string): unknown {\n const start = text.indexOf(\"{\")\n if (start < 0) throw new Error(\"Pixel Art Fixer did not print detection JSON.\")\n let depth = 0\n let string = false\n let escaped = false\n for (let i = start; i < text.length; i++) {\n const char = text[i]!\n if (string) {\n if (escaped) escaped = false\n else if (char === \"\\\\\") escaped = true\n else if (char === '\"') string = false\n continue\n }\n if (char === '\"') string = true\n else if (char === \"{\") depth++\n else if (char === \"}\" && --depth === 0) {\n try {\n return JSON.parse(text.slice(start, i + 1))\n } catch (error) {\n throw new Error(`Pixel Art Fixer printed invalid detection JSON: ${message(error)}`)\n }\n }\n }\n throw new Error(\"Pixel Art Fixer printed incomplete detection JSON.\")\n}\n\nconst PYTHON_FIXER_BRIDGE = [\n \"import json, sys\",\n \"from PIL import Image\",\n \"from pixelfixer.api import _load\",\n \"from pixelfixer.core import detect\",\n \"from pixelfixer.reconstruct import two_stage_pack\",\n \"rgba = _load(open(sys.argv[1], 'rb').read())\",\n \"result = detect(rgba, mode='full')\",\n \"Image.fromarray(two_stage_pack(rgba, result['cols'], result['rows'])).save(sys.argv[2], 'PNG')\",\n \"print(json.dumps({key: result[key] for key in ('cols', 'rows', 'step_x', 'step_y', 'phase_x', 'phase_y', 'consensus')}))\",\n].join(\"; \")\n\nfunction parseDetection(raw: unknown): PixelArtFixerDetection {\n if (!raw || typeof raw !== \"object\") throw new Error(\"Pixel Art Fixer returned no detection result.\")\n const value = raw as Record<string, unknown>\n const stepX = Number(value.step_x)\n const stepY = Number(value.step_y)\n const phaseX = Number(value.phase_x)\n const phaseY = Number(value.phase_y)\n const columns = Number(value.cols)\n const rows = Number(value.rows)\n const consensus = value.consensus\n if (\n !Number.isFinite(stepX) || stepX <= 0 ||\n !Number.isFinite(stepY) || stepY <= 0 ||\n !Number.isFinite(phaseX) || phaseX < 0 || phaseX > stepX ||\n !Number.isFinite(phaseY) || phaseY < 0 || phaseY > stepY ||\n !Number.isInteger(columns) || columns < 1 ||\n !Number.isInteger(rows) || rows < 1 ||\n typeof consensus !== \"string\" || !consensus\n ) {\n throw new Error(\"Pixel Art Fixer returned an invalid grid detection result.\")\n }\n return {\n stepX,\n stepY,\n phaseX,\n phaseY,\n columns,\n rows,\n consensus,\n confidence: confidenceFor(consensus),\n }\n}\n\nfunction normalizePalette(values: string[]): Array<{ hex: string; r: number; g: number; b: number }> {\n const colors = new Map<string, { hex: string; r: number; g: number; b: number }>()\n for (const value of values) {\n const rgb = parseHex(value)\n const hex = `#${rgb.r.toString(16).padStart(2, \"0\")}${rgb.g.toString(16).padStart(2, \"0\")}${rgb.b.toString(16).padStart(2, \"0\")}`\n colors.set(hex, { hex, ...rgb })\n }\n if (colors.size < 2 || colors.size > 256) {\n throw new Error(`A refinement palette must contain 2–256 unique colors; got ${colors.size}.`)\n }\n return [...colors.values()]\n}\n\n/** Canonical lowercase palette identity shared by manifest quality profiles. */\nexport function normalizeRefinementPalette(values: string[]): string[] {\n return normalizePalette(values).map((color) => color.hex)\n}\n\n/** Map every visible pixel to the nearest explicit color, without dithering. */\nexport function quantizeToPalette(png: DecodedPng, palette: string[]): DecodedPng {\n const colors = normalizePalette(palette)\n const pixels = Buffer.from(png.pixels)\n for (let i = 0; i < pixels.length; i += 4) {\n const alpha = pixels[i + 3]!\n if (alpha === 0) {\n pixels[i] = 0\n pixels[i + 1] = 0\n pixels[i + 2] = 0\n continue\n }\n const pixel = { r: pixels[i]!, g: pixels[i + 1]!, b: pixels[i + 2]! }\n let nearest = colors[0]!\n let distance = colorDistance(pixel, nearest)\n for (let j = 1; j < colors.length; j++) {\n const candidate = colors[j]!\n const candidateDistance = colorDistance(pixel, candidate)\n if (candidateDistance < distance) {\n nearest = candidate\n distance = candidateDistance\n }\n }\n pixels[i] = nearest.r\n pixels[i + 1] = nearest.g\n pixels[i + 2] = nearest.b\n }\n return { width: png.width, height: png.height, pixels }\n}\n\nfunction colorCount(png: DecodedPng): number {\n const colors = new Set<number>()\n for (let i = 0; i < png.pixels.length; i += 4) {\n if (png.pixels[i + 3]! < 128) continue\n colors.add((png.pixels[i]! << 16) | (png.pixels[i + 1]! << 8) | png.pixels[i + 2]!)\n }\n return colors.size\n}\n\nfunction unexpectedPaletteColors(png: DecodedPng, palette: string[]): number {\n const allowed = new Set(palette.map((hex) => {\n const color = parseHex(hex)\n return (color.r << 16) | (color.g << 8) | color.b\n }))\n const unexpected = new Set<number>()\n for (let i = 0; i < png.pixels.length; i += 4) {\n if (png.pixels[i + 3] === 0) continue\n const color = (png.pixels[i]! << 16) | (png.pixels[i + 1]! << 8) | png.pixels[i + 2]!\n if (!allowed.has(color)) unexpected.add(color)\n }\n return unexpected.size\n}\n\nfunction auditRefinement(\n png: DecodedPng,\n detection: PixelArtFixerDetection,\n palette: string[],\n minTransparency: number | undefined,\n minGridConfidence: GridConfidence,\n): RefineAudit {\n const colors = colorCount(png)\n const unexpectedColors = unexpectedPaletteColors(png, palette)\n const transparency = transparencyRatio(png)\n const reasons: string[] = []\n if (png.width !== detection.columns || png.height !== detection.rows) {\n reasons.push(\n `native output is ${png.width}x${png.height}, expected detected grid ` +\n `${detection.columns}x${detection.rows}`,\n )\n }\n if (colors > palette.length) reasons.push(`opaque color count ${colors} exceeds ${palette.length}`)\n if (unexpectedColors) reasons.push(`${unexpectedColors} visible color(s) are outside the final palette`)\n if (minTransparency !== undefined && transparency < minTransparency) {\n reasons.push(\n `transparency ${(transparency * 100).toFixed(1)}% is below ` +\n `${(minTransparency * 100).toFixed(1)}%`,\n )\n }\n if (confidenceRank[detection.confidence] < confidenceRank[minGridConfidence]) {\n reasons.push(\n `grid confidence ${detection.confidence} is below required ${minGridConfidence} ` +\n `(${detection.consensus})`,\n )\n }\n return {\n width: png.width,\n height: png.height,\n colorCount: colors,\n paletteConformant: unexpectedColors === 0,\n transparency,\n thresholds: {\n maxColors: palette.length,\n minTransparency: minTransparency ?? null,\n minGridConfidence,\n },\n safe: reasons.length === 0,\n reasons,\n }\n}\n\nfunction isGridConfidence(value: unknown): value is GridConfidence {\n return value === \"low\" || value === \"medium\" || value === \"high\"\n}\n\nfunction isDetection(value: unknown): value is PixelArtFixerDetection {\n if (!value || typeof value !== \"object\") return false\n const detection = value as Partial<PixelArtFixerDetection>\n return (\n Number.isFinite(detection.stepX) && detection.stepX! > 0 &&\n Number.isFinite(detection.stepY) && detection.stepY! > 0 &&\n Number.isFinite(detection.phaseX) && detection.phaseX! >= 0 &&\n detection.phaseX! <= detection.stepX! &&\n Number.isFinite(detection.phaseY) && detection.phaseY! >= 0 &&\n detection.phaseY! <= detection.stepY! &&\n Number.isInteger(detection.columns) && detection.columns! > 0 &&\n Number.isInteger(detection.rows) && detection.rows! > 0 &&\n typeof detection.consensus === \"string\" && !!detection.consensus &&\n isGridConfidence(detection.confidence)\n )\n}\n\nfunction isAudit(value: unknown): value is RefineAudit {\n if (!value || typeof value !== \"object\") return false\n const audit = value as Partial<RefineAudit>\n return (\n Number.isInteger(audit.width) && audit.width! > 0 &&\n Number.isInteger(audit.height) && audit.height! > 0 &&\n Number.isInteger(audit.colorCount) && audit.colorCount! >= 0 &&\n typeof audit.paletteConformant === \"boolean\" &&\n Number.isFinite(audit.transparency) && audit.transparency! >= 0 && audit.transparency! <= 1 &&\n !!audit.thresholds &&\n Number.isInteger(audit.thresholds.maxColors) && audit.thresholds.maxColors > 0 &&\n (audit.thresholds.minTransparency === null ||\n (Number.isFinite(audit.thresholds.minTransparency) &&\n audit.thresholds.minTransparency >= 0 && audit.thresholds.minTransparency <= 1)) &&\n isGridConfidence(audit.thresholds.minGridConfidence) &&\n typeof audit.safe === \"boolean\" &&\n Array.isArray(audit.reasons) && audit.reasons.every((reason) => typeof reason === \"string\")\n )\n}\n\nfunction validFrameSet(value: unknown): value is NonNullable<RefineRecordOptions[\"frameSet\"]> {\n if (!value || typeof value !== \"object\") return false\n const frameSet = value as NonNullable<RefineRecordOptions[\"frameSet\"]>\n return (\n Number.isInteger(frameSet.fps) && frameSet.fps >= 1 && frameSet.fps <= 60 &&\n Number.isInteger(frameSet.count) && frameSet.count >= 2 && frameSet.count <= 64 &&\n Array.isArray(frameSet.roles) && frameSet.roles.length === frameSet.count &&\n new Set(frameSet.roles).size === frameSet.roles.length &&\n frameSet.roles.every((role) => typeof role === \"string\" && !!role) &&\n Array.isArray(frameSet.frames) && frameSet.frames.length === frameSet.count &&\n frameSet.frames.every((frame, index) =>\n frame.role === frameSet.roles[index] &&\n Number.isInteger(frame.sourceWidth) && frame.sourceWidth > 0 &&\n Number.isInteger(frame.sourceHeight) && frame.sourceHeight > 0 &&\n isDetection(frame.detection) && isAudit(frame.audit),\n )\n )\n}\n\nfunction parseRecordOptions(manifest: ArtifactBundleManifest, record: string): RefineRecordOptions {\n if (manifest.kind !== \"refine\") throw new Error(`${record} is not a PixelKiln refinement record.`)\n const raw = manifest.options\n if (!raw || typeof raw !== \"object\") throw new Error(`${record} has invalid quality metadata.`)\n const options = raw as Partial<RefineRecordOptions>\n const grid = options.nativeGrid\n const palette = options.palette\n const audit = options.audit\n const review = options.review\n if (\n options.schema !== \"pixelkiln-quality\" || options.version !== 1 ||\n !grid || grid.tool !== \"pixel-art-fixer\" || grid.url !== PIXEL_ART_FIXER_URL ||\n typeof grid.revision !== \"string\" || !grid.revision ||\n (grid.protocol !== \"python-api-v1\" && grid.protocol !== \"python-core-v1\" &&\n grid.protocol !== \"python-cli-v1\") ||\n !isGridConfidence(grid.confidence) || typeof grid.consensus !== \"string\" ||\n !Number.isFinite(grid.stepX) || !Number.isFinite(grid.stepY) ||\n ((grid.phaseX !== undefined || grid.phaseY !== undefined || options.frameSet !== undefined) &&\n (!Number.isFinite(grid.phaseX) || !Number.isFinite(grid.phaseY))) ||\n !Number.isInteger(grid.sourceWidth) || !Number.isInteger(grid.sourceHeight) ||\n !Number.isInteger(grid.nativeWidth) || !Number.isInteger(grid.nativeHeight) ||\n !palette || !Array.isArray(palette.colors) || palette.colors.length < 2 ||\n !palette.colors.every((color) => typeof color === \"string\") ||\n palette.dither !== \"none\" || palette.distance !== \"redmean\" ||\n !isAudit(audit) ||\n !review || (review.status !== \"pending\" && review.status !== \"approved\") ||\n (options.frameSet !== undefined && !validFrameSet(options.frameSet))\n ) {\n throw new Error(`${record} has invalid quality metadata.`)\n }\n return options as RefineRecordOptions\n}\n\nfunction safeFrameRole(role: string, index: number): string {\n const safe = role.trim().replace(/[^a-zA-Z0-9_-]+/g, \"-\").replace(/^-+|-+$/g, \"\")\n return safe || `frame-${String(index).padStart(2, \"0\")}`\n}\n\n/** Derive a stable frame PNG beside a quality profile's virtual output stem. */\nexport function qualityFrameOutputPath(output: string, role: string, index: number): string {\n if (!/\\.png$/i.test(output)) throw new Error(\"Refined frame-set output must use a .png stem.\")\n return output.replace(/\\.png$/i, `-${safeFrameRole(role, index)}.png`)\n}\n\nfunction sameFrameGrid(\n first: RefineFrameSetResult[\"frames\"][number],\n next: RefineFrameSetResult[\"frames\"][number],\n): boolean {\n const phaseMatches = (a: number, b: number, step: number) => {\n const distance = Math.abs(a - b) % step\n return Math.min(distance, step - distance) <= 0.01\n }\n return (\n next.detection.stepX === first.detection.stepX &&\n next.detection.stepY === first.detection.stepY &&\n next.detection.columns === first.detection.columns &&\n next.detection.rows === first.detection.rows &&\n phaseMatches(next.detection.phaseX, first.detection.phaseX, first.detection.stepX) &&\n phaseMatches(next.detection.phaseY, first.detection.phaseY, first.detection.stepY) &&\n next.audit.width === first.audit.width &&\n next.audit.height === first.audit.height &&\n next.sourceWidth === first.sourceWidth &&\n next.sourceHeight === first.sourceHeight\n )\n}\n\n/** Recover an image's native grid, enforce its final palette, and write an auditable bundle. */\nexport async function refineAsset(options: RefineOptions): Promise<RefineResult> {\n const source = path.resolve(options.source)\n const output = path.resolve(options.output)\n if (source === output) throw new Error(\"Refinement source and output must be different files.\")\n const record = path.resolve(qualityRecordPath(output))\n const palette = normalizePalette(options.palette).map((color) => color.hex)\n const minGridConfidence = requireConfidence(options.minGridConfidence ?? \"high\")\n if (\n options.minTransparency !== undefined &&\n (!Number.isFinite(options.minTransparency) || options.minTransparency < 0 || options.minTransparency > 1)\n ) throw new Error(\"minTransparency must be between 0 and 1.\")\n\n let sourcePng: DecodedPng\n try {\n sourcePng = decodePng(await readFile(source))\n } catch (error) {\n throw new Error(`Cannot read refinement source ${source}: ${message(error)}`, { cause: error })\n }\n\n const compatibilityCommand = options.fixerCommand\n if (!compatibilityCommand) {\n if (\n sourcePng.width < PIXEL_ART_FIXER_MIN_SIDE ||\n sourcePng.height < PIXEL_ART_FIXER_MIN_SIDE\n ) {\n throw new Error(\n `Pixel Art Fixer requires each source side to be at least ` +\n `${PIXEL_ART_FIXER_MIN_SIDE}px; got ${sourcePng.width}x${sourcePng.height}.`,\n )\n }\n if (sourcePng.width * sourcePng.height > PIXEL_ART_FIXER_MAX_PIXELS) {\n throw new Error(\n `Pixel Art Fixer accepts at most ${PIXEL_ART_FIXER_MAX_PIXELS.toLocaleString(\"en-US\")} ` +\n `source pixels; got ${sourcePng.width}x${sourcePng.height}.`,\n )\n }\n }\n\n const temp = await mkdtemp(path.join(tmpdir(), \"pixelkiln-refine-\"))\n const recovered = path.join(temp, \"native.png\")\n const fixerCommand = compatibilityCommand ?? options.fixerPython ??\n process.env.PIXELKILN_PIXEL_FIXER_PYTHON ?? \"python3\"\n const args = compatibilityCommand\n ? [...(options.fixerArgsPrefix ?? []), source, \"--extract\", recovered]\n : [\"-c\", PYTHON_FIXER_BRIDGE, source, recovered]\n try {\n let stdout: string\n try {\n const result = await execFileAsync(fixerCommand, args, {\n encoding: \"utf8\",\n maxBuffer: 4 * 1024 * 1024,\n timeout: 10 * 60 * 1000,\n })\n stdout = result.stdout\n } catch (error) {\n const code = typeof error === \"object\" && error !== null && \"code\" in error\n ? String(error.code)\n : \"\"\n const install =\n `Install the pinned Python package from ${PIXEL_ART_FIXER_URL} at ` +\n `${options.fixerRevision ?? PIXEL_ART_FIXER_REVISION}, or pass --fixer-python.`\n throw new Error(\n code === \"ENOENT\"\n ? `Pixel Art Fixer command not found: ${fixerCommand}. ${install}`\n : `Pixel Art Fixer failed: ${message(error)}. ${install}`,\n { cause: error },\n )\n }\n const detection = parseDetection(firstJsonObject(stdout))\n const native = decodePng(await readFile(recovered))\n const quantized = quantizeToPalette(native, palette)\n const png = encodeRgbaPng(quantized.width, quantized.height, quantized.pixels)\n const audit = auditRefinement(\n quantized,\n detection,\n palette,\n options.minTransparency,\n minGridConfidence,\n )\n if (!audit.safe) {\n throw new Error(`Refinement failed its quality audit: ${audit.reasons.join(\"; \")}`)\n }\n\n const provenanceSource: ArtifactSource = {\n id: \"source\",\n path: source,\n sha256: await sha256File(source),\n included: true,\n }\n const recordOptions: RefineRecordOptions = {\n schema: \"pixelkiln-quality\",\n version: 1,\n nativeGrid: {\n tool: \"pixel-art-fixer\",\n url: PIXEL_ART_FIXER_URL,\n revision: options.fixerRevision ?? PIXEL_ART_FIXER_REVISION,\n protocol: compatibilityCommand ? \"python-cli-v1\" : \"python-core-v1\",\n confidence: detection.confidence,\n consensus: detection.consensus,\n stepX: detection.stepX,\n stepY: detection.stepY,\n phaseX: detection.phaseX,\n phaseY: detection.phaseY,\n sourceWidth: sourcePng.width,\n sourceHeight: sourcePng.height,\n nativeWidth: quantized.width,\n nativeHeight: quantized.height,\n },\n palette: { colors: palette, dither: \"none\", distance: \"redmean\" },\n audit,\n review: { status: \"pending\" },\n }\n await writeManagedArtifactBundle(\n record,\n [{ path: output, data: png }],\n { kind: \"refine\", sources: [provenanceSource], options: recordOptions },\n { force: options.force },\n )\n return { source, output, record, detection, palette, audit }\n } finally {\n await rm(temp, { recursive: true, force: true })\n }\n}\n\n/** Refine ordered still frames as one palette-locked, atomically reviewed artifact. */\nexport async function refineFrameSet(options: RefineFrameSetOptions): Promise<RefineFrameSetResult> {\n if (!Number.isInteger(options.fps) || options.fps < 1 || options.fps > 60) {\n throw new Error(\"Frame-set fps must be an integer between 1 and 60.\")\n }\n if (options.sources.length < 2 || options.sources.length > 64) {\n throw new Error(`A frame set must contain 2–64 ordered sources; got ${options.sources.length}.`)\n }\n const roles = options.sources.map((source) => source.role)\n if (roles.some((role) => !role.trim()) || new Set(roles).size !== roles.length) {\n throw new Error(\"Frame-set roles must be non-empty and unique.\")\n }\n\n const output = path.resolve(options.output)\n const record = path.resolve(qualityRecordPath(output))\n const palette = normalizeRefinementPalette(options.palette)\n const finalOutputs = options.sources.map((source, index) =>\n qualityFrameOutputPath(output, source.role, index))\n if (new Set(finalOutputs).size !== finalOutputs.length) {\n throw new Error(\"Frame-set roles resolve to duplicate output filenames.\")\n }\n const sourceSet = new Set(options.sources.map((source) => path.resolve(source.path)))\n if (finalOutputs.some((file) => sourceSet.has(file))) {\n throw new Error(\"Frame-set refinement sources and outputs must be different files.\")\n }\n const temp = await mkdtemp(path.join(tmpdir(), \"pixelkiln-refine-frames-\"))\n try {\n const frames: RefineFrameSetResult[\"frames\"] = []\n const outputs: Array<{ path: string; data: Buffer }> = []\n const provenanceSources: ArtifactSource[] = []\n const sourcePaths: string[] = []\n let firstOptions: RefineRecordOptions | null = null\n\n for (const [index, sourceEntry] of options.sources.entries()) {\n const source = path.resolve(sourceEntry.path)\n const temporaryOutput = path.join(temp, `${String(index).padStart(2, \"0\")}.png`)\n const refined = await refineAsset({\n source,\n output: temporaryOutput,\n palette,\n fixerPython: options.fixerPython,\n fixerCommand: options.fixerCommand,\n fixerArgsPrefix: options.fixerArgsPrefix,\n fixerRevision: options.fixerRevision,\n minGridConfidence: options.minGridConfidence,\n minTransparency: options.minTransparency,\n force: true,\n })\n const temporaryRecord = await readArtifactBundleManifest(refined.record)\n const frameOptions = parseRecordOptions(temporaryRecord, refined.record)\n firstOptions ??= frameOptions\n frames.push({\n role: sourceEntry.role,\n sourceWidth: frameOptions.nativeGrid.sourceWidth,\n sourceHeight: frameOptions.nativeGrid.sourceHeight,\n detection: refined.detection,\n audit: refined.audit,\n })\n sourcePaths.push(source)\n provenanceSources.push({\n id: sourceEntry.role,\n path: source,\n sha256: await sha256File(source),\n included: true,\n })\n outputs.push({\n path: finalOutputs[index]!,\n data: await readFile(temporaryOutput),\n })\n }\n\n const first = frames[0]!\n const mismatch = frames.find((frame) => !sameFrameGrid(first, frame))\n if (mismatch) {\n throw new Error(\n `Frame-set native grid mismatch: ${first.role} detected ` +\n `${first.detection.columns}x${first.detection.rows} at ` +\n `${first.detection.stepX}x${first.detection.stepY}, phase ` +\n `${first.detection.phaseX},${first.detection.phaseY}; but ${mismatch.role} detected ` +\n `${mismatch.detection.columns}x${mismatch.detection.rows} at ` +\n `${mismatch.detection.stepX}x${mismatch.detection.stepY}, phase ` +\n `${mismatch.detection.phaseX},${mismatch.detection.phaseY}.`,\n )\n }\n\n const reasons = frames.flatMap((frame) =>\n frame.audit.reasons.map((reason) => `${frame.role}: ${reason}`),\n )\n const audit: RefineAudit = {\n width: first.audit.width,\n height: first.audit.height,\n colorCount: Math.max(...frames.map((frame) => frame.audit.colorCount)),\n paletteConformant: frames.every((frame) => frame.audit.paletteConformant),\n transparency: Math.min(...frames.map((frame) => frame.audit.transparency)),\n thresholds: first.audit.thresholds,\n safe: frames.every((frame) => frame.audit.safe) && reasons.length === 0,\n reasons,\n }\n const baseOptions = firstOptions!\n const recordOptions: RefineRecordOptions = {\n ...baseOptions,\n audit,\n review: { status: \"pending\" },\n frameSet: {\n fps: options.fps,\n count: frames.length,\n roles,\n frames,\n },\n }\n await writeManagedArtifactBundle(\n record,\n outputs,\n { kind: \"refine\", sources: provenanceSources, options: recordOptions },\n { force: options.force },\n )\n return {\n sources: sourcePaths,\n outputs: outputs.map((item) => path.resolve(item.path)),\n record,\n frames,\n palette,\n audit,\n }\n } finally {\n await rm(temp, { recursive: true, force: true })\n }\n}\n\n/** Verify bytes, policy, audit, and human approval without rebuilding the image. */\nexport async function checkQualityRecord(recordPath: string): Promise<QualityCheck> {\n const record = path.resolve(recordPath)\n const manifest = await readArtifactBundleManifest(record)\n const options = parseRecordOptions(manifest, record)\n const verification = await verifyArtifactBundle(record)\n const sources = manifest.sources.map((source) => path.resolve(path.dirname(record), source.path))\n const outputs = manifest.outputs.map((output) => path.resolve(path.dirname(record), output.path))\n const source = sources[0] ?? \"\"\n const output = outputs[0] ?? \"\"\n const expectedCount = options.frameSet?.count ?? 1\n const reasons: string[] = []\n if (!verification.fingerprintValid) reasons.push(\"quality record fingerprint changed\")\n for (const source of verification.changedSources) reasons.push(`source changed: ${source}`)\n for (const changed of verification.changedOutputs) reasons.push(`output changed: ${changed}`)\n if (manifest.sources.length !== expectedCount) {\n reasons.push(`quality record must contain exactly ${expectedCount} source(s)`)\n }\n if (manifest.outputs.length !== expectedCount) {\n reasons.push(`quality record must contain exactly ${expectedCount} output(s)`)\n }\n if (!options.audit.safe) reasons.push(...options.audit.reasons.map((reason) => `audit: ${reason}`))\n if (options.review.status !== \"approved\") reasons.push(\"human 1× review is pending\")\n return {\n safe: reasons.length === 0,\n current: verification.current,\n approved: options.review.status === \"approved\",\n auditSafe: options.audit.safe,\n record,\n source,\n output,\n sources,\n outputs,\n options,\n reasons,\n }\n}\n\n/** Attach a human 1× review to an unchanged, audit-safe refinement bundle. */\nexport async function approveQualityRecord(\n recordPath: string,\n approval: ApproveQualityOptions,\n): Promise<QualityCheck> {\n const reviewer = approval.reviewer.trim()\n if (!reviewer) throw new Error(\"A human reviewer name is required.\")\n const record = path.resolve(recordPath)\n const manifest = await readArtifactBundleManifest(record)\n const options = parseRecordOptions(manifest, record)\n const verification = await verifyArtifactBundle(record)\n if (!verification.current) {\n const changes = [\n ...verification.changedSources.map((source) => `source ${source}`),\n ...verification.changedOutputs.map((output) => `output ${output}`),\n ...(!verification.fingerprintValid ? [\"quality metadata\"] : []),\n ]\n throw new Error(`Cannot approve a stale refinement; changed: ${changes.join(\", \")}. Run refine again.`)\n }\n if (!options.audit.safe) {\n throw new Error(`Cannot approve a failed quality audit: ${options.audit.reasons.join(\"; \")}`)\n }\n const expectedCount = options.frameSet?.count ?? 1\n if (manifest.sources.length !== expectedCount || manifest.outputs.length !== expectedCount) {\n throw new Error(\n `A refinement record must contain exactly ${expectedCount} source(s) and output(s).`,\n )\n }\n\n const root = path.dirname(record)\n const outputs = await Promise.all(manifest.outputs.map(async (entry) => {\n const outputPath = path.resolve(root, entry.path)\n return { path: outputPath, data: await readFile(outputPath) }\n }))\n const sources: ArtifactSource[] = manifest.sources.map((source) => ({\n ...source,\n path: path.resolve(root, source.path),\n }))\n const approved: RefineRecordOptions = {\n ...options,\n review: {\n status: \"approved\",\n reviewer,\n approvedAt: (approval.approvedAt ?? new Date()).toISOString(),\n checklist: {\n nativeScale: true,\n crispEdges: true,\n subjectReadable: true,\n paletteSeparation: true,\n alphaAndSeams: true,\n },\n ...(approval.note?.trim() ? { note: approval.note.trim() } : {}),\n },\n }\n await writeManagedArtifactBundle(\n record,\n outputs,\n { kind: \"refine\", sources, options: approved },\n )\n return checkQualityRecord(record)\n}\n","import path from \"node:path\"\nimport { createHash, randomUUID } from \"node:crypto\"\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\"\n\nexport interface ArtifactFile {\n path: string\n data: string | Uint8Array\n}\n\nexport interface ArtifactBundleResult {\n changed: string[]\n unchanged: string[]\n}\n\nexport interface ArtifactBundleOptions {\n /** @internal Failure-injection hook used to verify staging cleanup. */\n beforeStage?: (destination: string, index: number) => void | Promise<void>\n /** @internal Failure-injection hook used to verify rollback behavior. */\n beforePromote?: (destination: string, index: number) => void | Promise<void>\n /** @internal Durable transaction journal used by the managed writer. */\n recoveryFile?: string\n /** @internal Failure-injection hook used to simulate a crash after commit. */\n afterCommit?: () => void | Promise<void>\n}\n\nexport interface ManagedArtifactBundleOptions extends ArtifactBundleOptions {\n /** Explicitly replace unowned or manually modified destinations. */\n force?: boolean\n}\n\nexport interface ArtifactSource {\n id: string\n path: string\n sha256: string | null\n included: boolean\n}\n\nexport interface ArtifactProvenance {\n kind: \"pack\" | \"mount\" | \"tileset\" | \"refine\"\n sources: ArtifactSource[]\n /** Every non-source input that can change the derived bytes. */\n options: unknown\n}\n\nexport interface ArtifactBundleManifest {\n format: \"pixelkiln-artifact-bundle\"\n version: 1\n kind: ArtifactProvenance[\"kind\"]\n fingerprint: string\n sources: ArtifactSource[]\n options: unknown\n outputs: Array<{ path: string; sha256: string }>\n}\n\nexport interface ArtifactVerification {\n current: boolean\n fingerprintValid: boolean\n changedSources: string[]\n changedOutputs: string[]\n}\n\ninterface PreparedArtifact {\n destination: string\n data: Buffer\n existed: boolean\n stage?: string\n backup?: string\n backedUp: boolean\n promoted: boolean\n}\n\ninterface ArtifactTransaction {\n format: \"pixelkiln-artifact-transaction\"\n version: 1\n pid: number\n createdAt: string\n entries: Array<{\n destination: string\n stage: string\n backup?: string\n sha256: string\n }>\n}\n\nconst activeTransactions = new Set<string>()\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction digest(data: string | Uint8Array): string {\n return createHash(\"sha256\").update(data).digest(\"hex\")\n}\n\nfunction portableRelative(from: string, to: string): string {\n return path.relative(from, path.resolve(to)).split(path.sep).join(\"/\") || \".\"\n}\n\nfunction canonical(value: unknown): unknown {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) throw new Error(\"Artifact provenance numbers must be finite.\")\n return value\n }\n if (Array.isArray(value)) return value.map(canonical)\n if (typeof value === \"object\") {\n const sorted: Record<string, unknown> = {}\n for (const key of Object.keys(value).sort()) {\n const item = (value as Record<string, unknown>)[key]\n if (item !== undefined) sorted[key] = canonical(item)\n }\n return sorted\n }\n throw new Error(`Artifact provenance cannot contain ${typeof value} values.`)\n}\n\nfunction fingerprint(provenance: Pick<ArtifactBundleManifest, \"kind\" | \"sources\" | \"options\" | \"outputs\">): string {\n return digest(JSON.stringify(canonical({\n kind: provenance.kind,\n sources: provenance.sources,\n options: provenance.options,\n outputs: provenance.outputs,\n })))\n}\n\nfunction parseArtifactManifest(absolute: string, data: string): ArtifactBundleManifest {\n let raw: Partial<ArtifactBundleManifest>\n try {\n raw = JSON.parse(data) as Partial<ArtifactBundleManifest>\n } catch (error) {\n throw new Error(`${absolute} is not valid JSON: ${message(error)}`, { cause: error })\n }\n if (\n raw.format !== \"pixelkiln-artifact-bundle\" ||\n raw.version !== 1 ||\n (raw.kind !== \"pack\" && raw.kind !== \"mount\" && raw.kind !== \"tileset\" && raw.kind !== \"refine\") ||\n typeof raw.fingerprint !== \"string\" ||\n raw.options === undefined ||\n !Array.isArray(raw.sources) ||\n !Array.isArray(raw.outputs)\n ) {\n throw new Error(`${absolute} is not a PixelKiln artifact bundle manifest.`)\n }\n for (const source of raw.sources) {\n if (\n !source ||\n typeof source.id !== \"string\" ||\n typeof source.path !== \"string\" ||\n (source.sha256 !== null && typeof source.sha256 !== \"string\") ||\n typeof source.included !== \"boolean\"\n ) {\n throw new Error(`${absolute} contains an invalid artifact source.`)\n }\n }\n for (const output of raw.outputs) {\n if (!output || typeof output.path !== \"string\" || typeof output.sha256 !== \"string\") {\n throw new Error(`${absolute} contains an invalid artifact output.`)\n }\n }\n return raw as ArtifactBundleManifest\n}\n\n/** Read and validate a companion manifest without resolving its portable paths. */\nexport async function readArtifactBundleManifest(\n manifestPath: string,\n): Promise<ArtifactBundleManifest> {\n const absolute = path.resolve(manifestPath)\n return parseArtifactManifest(absolute, await readFile(absolute, \"utf8\"))\n}\n\nasync function readOptional(file: string): Promise<Buffer | null> {\n try {\n return await readFile(file)\n } catch (error) {\n if (isCode(error, \"ENOENT\")) return null\n throw error\n }\n}\n\nfunction transactionMarker(journal: string): string {\n return `${journal}.committed`\n}\n\nfunction processIsAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid < 1) return false\n try {\n process.kill(pid, 0)\n return true\n } catch (error) {\n return !isCode(error, \"ESRCH\")\n }\n}\n\nfunction validTemporaryPath(\n candidate: string,\n destination: string,\n type: \"stage\" | \"backup\",\n): boolean {\n return (\n path.dirname(candidate) === path.dirname(destination) &&\n path.basename(candidate).startsWith(\n `.${path.basename(destination)}.pixelkiln-${type}-`,\n )\n )\n}\n\nfunction parseTransaction(journal: string, data: string): ArtifactTransaction {\n let raw: Partial<ArtifactTransaction>\n try {\n raw = JSON.parse(data) as Partial<ArtifactTransaction>\n } catch (error) {\n throw new Error(`${journal} is not valid transaction JSON: ${message(error)}`, { cause: error })\n }\n if (\n raw.format !== \"pixelkiln-artifact-transaction\" ||\n raw.version !== 1 ||\n !Number.isInteger(raw.pid) ||\n typeof raw.createdAt !== \"string\" ||\n !Array.isArray(raw.entries) ||\n !raw.entries.length\n ) {\n throw new Error(`${journal} is not a PixelKiln artifact transaction.`)\n }\n return raw as ArtifactTransaction\n}\n\nasync function removeTransactionFiles(journal: string): Promise<void> {\n // Journal first: a marker without a journal means the destinations were\n // already committed and cleanup may safely be considered complete.\n await rm(journal, { force: true })\n await rm(transactionMarker(journal), { force: true })\n}\n\nasync function recoverArtifactTransaction(\n recoveryFile: string,\n allowedDestinations: Set<string>,\n): Promise<void> {\n const journal = path.resolve(recoveryFile)\n const bytes = await readOptional(journal)\n if (!bytes) {\n await rm(transactionMarker(journal), { force: true })\n return\n }\n\n if (activeTransactions.has(journal)) {\n throw new Error(`Another artifact write in this process is already using ${journal}.`)\n }\n const transaction = parseTransaction(journal, bytes.toString(\"utf8\"))\n if (transaction.pid !== process.pid && processIsAlive(transaction.pid)) {\n throw new Error(\n `Artifact transaction ${journal} is still owned by live process ${transaction.pid}; ` +\n `refusing concurrent recovery.`,\n )\n }\n\n for (const entry of transaction.entries) {\n if (\n typeof entry.destination !== \"string\" ||\n typeof entry.stage !== \"string\" ||\n typeof entry.sha256 !== \"string\" ||\n (entry.backup !== undefined && typeof entry.backup !== \"string\") ||\n !allowedDestinations.has(path.resolve(entry.destination)) ||\n !validTemporaryPath(entry.stage, entry.destination, \"stage\") ||\n (entry.backup !== undefined && !validTemporaryPath(entry.backup, entry.destination, \"backup\"))\n ) {\n throw new Error(\n `Refusing unsafe artifact recovery from ${journal}; its destinations or temporary ` +\n `paths do not match the current bundle.`,\n )\n }\n }\n\n const committed = (await readOptional(transactionMarker(journal))) !== null\n const errors: string[] = []\n if (committed) {\n for (const entry of transaction.entries) {\n if (entry.backup) await remove(entry.backup, errors)\n await remove(entry.stage, errors)\n }\n } else {\n for (const entry of [...transaction.entries].reverse()) {\n const backup = entry.backup ? await readOptional(entry.backup) : null\n const destination = await readOptional(entry.destination)\n if (backup) {\n if (destination && digest(destination) !== entry.sha256) {\n errors.push(\n `destination changed during interrupted recovery: ${entry.destination}; ` +\n `previous file remains at ${entry.backup}`,\n )\n continue\n }\n await remove(entry.destination, errors)\n try {\n await rename(entry.backup!, entry.destination)\n } catch (error) {\n errors.push(\n `could not restore ${entry.destination}; previous file remains at ` +\n `${entry.backup}: ${message(error)}`,\n )\n }\n } else if (destination && digest(destination) === entry.sha256) {\n await remove(entry.destination, errors)\n }\n await remove(entry.stage, errors)\n }\n }\n\n if (errors.length) {\n throw new Error(\n `Artifact transaction recovery needs attention; journal retained at ${journal}: ` +\n errors.join(\"; \"),\n )\n }\n await removeTransactionFiles(journal)\n}\n\n/** Build the deterministic companion metadata written beside a derived bundle. */\nexport function createArtifactBundleManifest(\n manifestPath: string,\n outputs: ArtifactFile[],\n provenance: ArtifactProvenance,\n): ArtifactBundleManifest {\n const root = path.dirname(path.resolve(manifestPath))\n const sources = provenance.sources.map((source) => ({\n ...source,\n path: portableRelative(root, source.path),\n }))\n const normalized = {\n kind: provenance.kind,\n sources,\n options: canonical(provenance.options),\n }\n const manifestOutputs = outputs.map((output) => ({\n path: portableRelative(root, output.path),\n sha256: digest(output.data),\n }))\n return {\n format: \"pixelkiln-artifact-bundle\",\n version: 1,\n ...normalized,\n fingerprint: fingerprint({ ...normalized, outputs: manifestOutputs }),\n outputs: manifestOutputs,\n }\n}\n\n/** Add deterministic provenance metadata to a related set of generated files. */\nexport function withArtifactManifest(\n manifestPath: string,\n outputs: ArtifactFile[],\n provenance: ArtifactProvenance,\n): ArtifactFile[] {\n const manifest = createArtifactBundleManifest(manifestPath, outputs, provenance)\n return [\n ...outputs,\n { path: manifestPath, data: JSON.stringify(manifest, null, 2) + \"\\n\" },\n ]\n}\n\n/**\n * Persist a generated bundle while protecting files not demonstrably owned by\n * its existing companion manifest. Byte-identical legacy files are adopted\n * without rewriting; `force` is required to take over anything else.\n */\nexport async function writeManagedArtifactBundle(\n manifestPath: string,\n outputs: ArtifactFile[],\n provenance: ArtifactProvenance,\n options: ManagedArtifactBundleOptions = {},\n): Promise<ArtifactBundleResult> {\n const absoluteManifest = path.resolve(manifestPath)\n const recoveryFile = `${absoluteManifest}.transaction`\n const allowedDestinations = new Set([\n absoluteManifest,\n ...outputs.map((output) => path.resolve(output.path)),\n ])\n await recoverArtifactTransaction(recoveryFile, allowedDestinations)\n const existingManifestBytes = await readOptional(absoluteManifest)\n let previous: ArtifactBundleManifest | null = null\n\n if (existingManifestBytes && !options.force) {\n try {\n previous = parseArtifactManifest(absoluteManifest, existingManifestBytes.toString(\"utf8\"))\n const valid = previous.fingerprint === fingerprint(previous)\n if (!valid) throw new Error(\"its integrity fingerprint does not match\")\n } catch (error) {\n throw new Error(\n `Refusing to replace unrecognized or modified provenance at ${absoluteManifest}: ` +\n `${message(error)}. Pass { force: true } (CLI: --force) to take ownership ` +\n `of this artifact bundle.`,\n { cause: error },\n )\n }\n }\n\n if (!options.force) {\n const root = path.dirname(absoluteManifest)\n const recorded = new Map(\n previous?.outputs.map((output) => [path.resolve(root, output.path), output.sha256]) ?? [],\n )\n const conflicts: string[] = []\n for (const output of outputs) {\n const destination = path.resolve(output.path)\n const current = await readOptional(destination)\n if (!current || digest(current) === digest(output.data)) continue\n const expected = recorded.get(destination)\n if (!expected || digest(current) !== expected) conflicts.push(destination)\n }\n if (conflicts.length) {\n throw new Error(\n `Refusing to overwrite modified or unowned artifact file(s):\\n` +\n conflicts.map((file) => ` ${file}`).join(\"\\n\") +\n `\\nPass { force: true } (CLI: --force) to take ownership and replace ` +\n `the complete bundle.`,\n )\n }\n }\n\n const { force: _force, ...bundleOptions } = options\n return writeArtifactBundle(\n withArtifactManifest(absoluteManifest, outputs, provenance),\n { ...bundleOptions, recoveryFile },\n )\n}\n\n/** Verify stored provenance and source/output hashes without rebuilding output. */\nexport async function verifyArtifactBundle(manifestPath: string): Promise<ArtifactVerification> {\n const absolute = path.resolve(manifestPath)\n const raw = await readArtifactBundleManifest(absolute)\n\n const root = path.dirname(absolute)\n const changedSources: string[] = []\n const changedOutputs: string[] = []\n for (const source of raw.sources) {\n let actual: string | null = null\n try {\n actual = digest(await readFile(path.resolve(root, source.path)))\n } catch (error) {\n if (!isCode(error, \"ENOENT\")) throw error\n }\n if (actual !== source.sha256) changedSources.push(source.id)\n }\n for (const output of raw.outputs) {\n try {\n if (digest(await readFile(path.resolve(root, output.path))) !== output.sha256) {\n changedOutputs.push(output.path)\n }\n } catch (error) {\n if (!isCode(error, \"ENOENT\")) throw error\n changedOutputs.push(output.path)\n }\n }\n\n const fingerprintValid = raw.fingerprint === fingerprint({\n kind: raw.kind,\n sources: raw.sources,\n options: raw.options,\n outputs: raw.outputs,\n })\n return {\n current: fingerprintValid && !changedSources.length && !changedOutputs.length,\n fingerprintValid,\n changedSources,\n changedOutputs,\n }\n}\n\nfunction isCode(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === code\n}\n\nasync function remove(file: string, errors?: string[]): Promise<void> {\n try {\n await rm(file, { force: true })\n } catch (error) {\n errors?.push(`could not remove ${file}: ${message(error)}`)\n }\n}\n\nasync function rollback(prepared: PreparedArtifact[]): Promise<string[]> {\n const errors: string[] = []\n\n // Remove newly-promoted members before putting their previous versions back.\n for (const artifact of [...prepared].reverse()) {\n if (artifact.promoted) await remove(artifact.destination, errors)\n }\n\n for (const artifact of [...prepared].reverse()) {\n if (!artifact.backup || !artifact.backedUp) continue\n try {\n await rename(artifact.backup, artifact.destination)\n artifact.backedUp = false\n } catch (error) {\n errors.push(\n `could not restore ${artifact.destination}; previous file remains at ` +\n `${artifact.backup}: ${message(error)}`,\n )\n }\n }\n\n for (const artifact of prepared) {\n if (artifact.stage) await remove(artifact.stage, errors)\n }\n return errors\n}\n\n/**\n * Write a related set of generated files without leaving a partial bundle\n * after an ordinary write failure.\n *\n * All changed members are staged before any destination is replaced. If an\n * ordinary filesystem error interrupts promotion, prior files are restored.\n * Byte-identical members are not rewritten.\n */\nexport async function writeArtifactBundle(\n files: ArtifactFile[],\n options: ArtifactBundleOptions = {},\n): Promise<ArtifactBundleResult> {\n if (!files.length) throw new Error(\"An artifact bundle must contain at least one file.\")\n\n const normalized = files.map((file) => {\n if (!file.path.trim()) throw new Error(\"Artifact paths cannot be empty.\")\n return { destination: path.resolve(file.path), data: Buffer.from(file.data) }\n })\n const destinations = new Set<string>()\n for (const artifact of normalized) {\n if (destinations.has(artifact.destination)) {\n throw new Error(`Artifact bundle contains duplicate destination: ${artifact.destination}`)\n }\n destinations.add(artifact.destination)\n }\n if (options.recoveryFile) {\n await recoverArtifactTransaction(options.recoveryFile, destinations)\n }\n\n const changed: PreparedArtifact[] = []\n const unchanged: string[] = []\n for (const artifact of normalized) {\n try {\n const current = await readFile(artifact.destination)\n if (current.equals(artifact.data)) {\n unchanged.push(artifact.destination)\n } else {\n changed.push({ ...artifact, existed: true, backedUp: false, promoted: false })\n }\n } catch (error) {\n if (!isCode(error, \"ENOENT\")) throw error\n changed.push({ ...artifact, existed: false, backedUp: false, promoted: false })\n }\n }\n\n if (!changed.length) return { changed: [], unchanged }\n\n const token = randomUUID()\n for (const [index, artifact] of changed.entries()) {\n const basename = path.basename(artifact.destination)\n artifact.stage = path.join(\n path.dirname(artifact.destination),\n `.${basename}.pixelkiln-stage-${token}-${index}`,\n )\n if (artifact.existed) {\n artifact.backup = path.join(\n path.dirname(artifact.destination),\n `.${basename}.pixelkiln-backup-${token}-${index}`,\n )\n }\n }\n\n const journal = options.recoveryFile ? path.resolve(options.recoveryFile) : null\n if (journal) {\n await mkdir(path.dirname(journal), { recursive: true })\n const transaction: ArtifactTransaction = {\n format: \"pixelkiln-artifact-transaction\",\n version: 1,\n pid: process.pid,\n createdAt: new Date().toISOString(),\n entries: changed.map((artifact) => ({\n destination: artifact.destination,\n stage: artifact.stage!,\n ...(artifact.backup ? { backup: artifact.backup } : {}),\n sha256: digest(artifact.data),\n })),\n }\n try {\n await writeFile(journal, JSON.stringify(transaction, null, 2) + \"\\n\", { flag: \"wx\" })\n activeTransactions.add(journal)\n } catch (error) {\n throw new Error(\n `Could not start durable artifact transaction at ${journal}: ${message(error)}`,\n { cause: error },\n )\n }\n }\n\n try {\n for (const [index, artifact] of changed.entries()) {\n await mkdir(path.dirname(artifact.destination), { recursive: true })\n await options.beforeStage?.(artifact.destination, index)\n await writeFile(artifact.stage!, artifact.data, { flag: \"wx\" })\n }\n } catch (error) {\n const cleanupErrors = await rollback(changed)\n if (journal && !cleanupErrors.length) await removeTransactionFiles(journal)\n if (journal) activeTransactions.delete(journal)\n const suffix = cleanupErrors.length ? ` Cleanup also failed: ${cleanupErrors.join(\"; \")}` : \"\"\n throw new Error(`Could not stage artifact bundle: ${message(error)}.${suffix}`, { cause: error })\n }\n\n let durableCommit = false\n try {\n // Move every prior member aside first. Once promotion begins, rollback has\n // a complete snapshot even when several destinations are being replaced.\n for (const artifact of changed) {\n if (!artifact.existed) continue\n await rename(artifact.destination, artifact.backup!)\n artifact.backedUp = true\n }\n\n for (const [index, artifact] of changed.entries()) {\n await options.beforePromote?.(artifact.destination, index)\n await rename(artifact.stage!, artifact.destination)\n artifact.stage = undefined\n artifact.promoted = true\n }\n if (journal) {\n await writeFile(transactionMarker(journal), `${token}\\n`, { flag: \"wx\" })\n durableCommit = true\n await options.afterCommit?.()\n }\n } catch (error) {\n if (durableCommit) {\n if (journal) activeTransactions.delete(journal)\n throw new Error(\n `Artifact bundle was committed, but final cleanup was interrupted: ${message(error)}. ` +\n `The next write will finish cleanup from ${journal}.`,\n { cause: error },\n )\n }\n const rollbackErrors = await rollback(changed)\n if (journal && !rollbackErrors.length) await removeTransactionFiles(journal)\n if (journal) activeTransactions.delete(journal)\n const suffix = rollbackErrors.length\n ? ` Rollback needs attention: ${rollbackErrors.join(\"; \")}`\n : \" Previous bundle restored.\"\n throw new Error(`Could not promote artifact bundle: ${message(error)}.${suffix}`, { cause: error })\n }\n\n const cleanupErrors: string[] = []\n for (const artifact of changed) {\n if (artifact.backup) await remove(artifact.backup, cleanupErrors)\n }\n if (cleanupErrors.length) {\n if (journal) activeTransactions.delete(journal)\n throw new Error(\n `Artifact bundle was written, but old backup cleanup failed: ${cleanupErrors.join(\"; \")}`,\n )\n }\n if (journal) {\n try {\n await removeTransactionFiles(journal)\n } finally {\n activeTransactions.delete(journal)\n }\n }\n\n return {\n changed: changed.map((artifact) => artifact.destination),\n unchanged,\n }\n}\n","import { readFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { decodePng, extractPalette, transparencyRatio, type PaletteEntry } from \"../png.ts\"\nimport type { LoadedManifest } from \"../manifest.ts\"\nimport type { Lock, ResolvedSpec } from \"../types.ts\"\nimport { resolveSpecOutputs } from \"../outputs.ts\"\n\n/**\n * Perceptual-ish distance between two colours, 0-255ish.\n *\n * \"Redmean\" — a cheap weighting that tracks human perception far better than\n * raw RGB euclidean and needs no colour-space conversion or dependency. Good\n * enough to rank outliers, which is all this is for; it is not colourimetry.\n */\nexport function colorDistance(\n a: { r: number; g: number; b: number },\n b: { r: number; g: number; b: number },\n): number {\n const rmean = (a.r + b.r) / 2\n const dr = a.r - b.r\n const dg = a.g - b.g\n const db = a.b - b.b\n return Math.sqrt(\n (((512 + rmean) * dr * dr) / 256) + 4 * dg * dg + (((767 - rmean) * db * db) / 256),\n )\n}\n\n/**\n * How far an asset's palette sits from a reference palette.\n *\n * For each colour in the asset, weighted by how much of the image it covers,\n * take the distance to its nearest reference colour. An asset built entirely\n * from on-style colours scores ~0; one introducing a foreign hue scores high\n * in proportion to how much of the image that hue occupies.\n */\nexport function paletteDistance(asset: PaletteEntry[], reference: PaletteEntry[]): number {\n if (!asset.length || !reference.length) return 0\n let total = 0\n let weight = 0\n for (const color of asset) {\n let nearest = Infinity\n for (const ref of reference) nearest = Math.min(nearest, colorDistance(color, ref))\n total += nearest * color.weight\n weight += color.weight\n }\n return weight === 0 ? 0 : total / weight\n}\n\n/** Merge many palettes into one, summing weights for repeated colours. */\nexport function mergePalettes(palettes: PaletteEntry[][], topN = 24): PaletteEntry[] {\n const totals = new Map<string, PaletteEntry>()\n for (const palette of palettes) {\n for (const color of palette) {\n const key = `${color.r},${color.g},${color.b}`\n const existing = totals.get(key)\n if (existing) existing.weight += color.weight\n else totals.set(key, { ...color })\n }\n }\n const merged = [...totals.values()].sort((a, b) => b.weight - a.weight).slice(0, topN)\n const sum = merged.reduce((s, c) => s + c.weight, 0) || 1\n return merged.map((c) => ({ ...c, weight: c.weight / sum }))\n}\n\nexport interface AssetAudit {\n assetId: string\n /** Present when this is one member of a structural multi-output asset. */\n outputRole?: string\n /** Stable report/atlas identity: assetId for one output, assetId/role for many. */\n id: string\n file: string\n width: number\n height: number\n /** Distance from the style's reference palette. Higher is more off-style. */\n paletteDistance: number\n /** Share of the canvas that is transparent. Very low suggests a baked background. */\n transparency: number\n /** Distinct opaque colours. Very high suggests photo-like rendering, not pixel art. */\n colorCount: number\n palette: PaletteEntry[]\n}\n\nexport interface StyleAudit {\n styleId: string\n /** True when the reference came from the style's own styleImages. */\n referenceFromStyleImages: boolean\n reference: PaletteEntry[]\n assets: AssetAudit[]\n missing: string[]\n unreadable: string[]\n}\n\nexport interface AuditThresholds {\n /** Absolute palette-distance ceiling. Omit to rely on relative outliers. */\n maxDistance?: number\n /** Minimum transparent share of the canvas, from 0 to 1. */\n minTransparency?: number\n /** Maximum number of distinct opaque colors. */\n maxColors?: number\n /** Relative outlier cutoff. Defaults to 1.5 standard deviations. */\n sigma?: number\n}\n\nexport interface AuditViolation {\n id: string\n reasons: string[]\n}\n\nexport interface AuditEvaluation {\n safe: boolean\n thresholds: Required<Pick<AuditThresholds, \"sigma\">> & Omit<AuditThresholds, \"sigma\">\n outliers: string[]\n violations: AuditViolation[]\n missing: string[]\n unreadable: string[]\n}\n\n/**\n * Measures how consistently a style's assets actually hold together.\n *\n * This exists to answer \"is this variant working?\" with a number instead of an\n * eyeball. Measured on a real neon trial, prose alone carried the style on\n * subjects with no strong inherent colour but was ignored on ones that had\n * some — a chocolate bar stayed brown, a camera stayed grey. Those are exactly\n * the assets this ranks to the top, before another 57 are generated to match.\n *\n * Reference palette comes from the style's `styleImages` when set, since those\n * are the declared intent. Otherwise the assets are compared against their own\n * collective palette, which still surfaces outliers but cannot tell you the\n * whole set has drifted together.\n */\nexport async function auditStyle(\n loaded: LoadedManifest,\n specs: ResolvedSpec[],\n styleId: string,\n lock?: Lock,\n): Promise<StyleAudit> {\n const style = loaded.manifest.styles[styleId]\n if (!style) throw new Error(`Unknown style \"${styleId}\"`)\n\n const mine = specs.filter((s) => s.styleId === styleId)\n const assets: AssetAudit[] = []\n const missing: string[] = []\n const unreadable: string[] = []\n\n for (const spec of mine) {\n for (const output of resolveSpecOutputs(spec, lock, loaded.root)) {\n if (!existsSync(output.absolutePath)) {\n missing.push(output.id)\n continue\n }\n try {\n const png = decodePng(await readFile(output.absolutePath))\n const palette = extractPalette(png, 12)\n assets.push({\n assetId: spec.assetId,\n ...(output.role ? { outputRole: output.role } : {}),\n id: output.id,\n file: output.absolutePath,\n width: png.width,\n height: png.height,\n paletteDistance: 0, // filled once the reference is known\n transparency: transparencyRatio(png),\n colorCount: countColors(png),\n palette,\n })\n } catch (err) {\n unreadable.push(`${output.id}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n }\n\n // Prefer the declared intent over the set's own average.\n let reference: PaletteEntry[] = []\n let referenceFromStyleImages = false\n const refPalettes: PaletteEntry[][] = []\n for (const img of style.styleImages) {\n const abs = path.resolve(loaded.root, img.path)\n if (!existsSync(abs)) continue\n try {\n refPalettes.push(extractPalette(decodePng(await readFile(abs)), 12))\n } catch {\n // A malformed reference should not sink the audit.\n }\n }\n if (refPalettes.length) {\n reference = mergePalettes(refPalettes)\n referenceFromStyleImages = true\n for (const asset of assets) {\n asset.paletteDistance = paletteDistance(asset.palette, reference)\n }\n } else {\n // Reported reference is the whole set, but each asset is scored against\n // the set MINUS itself. Including an asset in its own reference lets it\n // match perfectly, which would make the most divergent asset — the one\n // worth finding — score zero.\n reference = mergePalettes(assets.map((a) => a.palette))\n for (const asset of assets) {\n const others = assets.filter((a) => a !== asset).map((a) => a.palette)\n asset.paletteDistance = others.length\n ? paletteDistance(asset.palette, mergePalettes(others))\n : 0\n }\n }\n assets.sort((a, b) => b.paletteDistance - a.paletteDistance)\n\n return { styleId, referenceFromStyleImages, reference, assets, missing, unreadable }\n}\n\nfunction countColors(png: { pixels: Buffer }): number {\n const seen = new Set<number>()\n for (let i = 0; i < png.pixels.length; i += 4) {\n if (png.pixels[i + 3]! < 128) continue\n seen.add((png.pixels[i]! << 16) | (png.pixels[i + 1]! << 8) | png.pixels[i + 2]!)\n }\n return seen.size\n}\n\n/** Assets more than `sigma` standard deviations off the mean distance. */\nexport function outliers(audit: StyleAudit, sigma = 1.5): AssetAudit[] {\n const n = audit.assets.length\n if (n < 3) return []\n const mean = audit.assets.reduce((s, a) => s + a.paletteDistance, 0) / n\n const variance = audit.assets.reduce((s, a) => s + (a.paletteDistance - mean) ** 2, 0) / n\n const sd = Math.sqrt(variance)\n if (sd === 0) return []\n return audit.assets.filter((a) => a.paletteDistance > mean + sigma * sd)\n}\n\n/** Turn an audit into a stable CI decision without hiding the underlying measurements. */\nexport function evaluateAudit(\n audit: StyleAudit,\n thresholds: AuditThresholds = {},\n): AuditEvaluation {\n const resolved = { ...thresholds, sigma: thresholds.sigma ?? 1.5 }\n const relative = outliers(audit, resolved.sigma)\n const relativeIds = new Set(relative.map((asset) => asset.id))\n const violations: AuditViolation[] = []\n\n for (const asset of audit.assets) {\n const reasons: string[] = []\n if (relativeIds.has(asset.id)) {\n reasons.push(`palette outlier beyond ${resolved.sigma} standard deviations`)\n }\n if (resolved.maxDistance !== undefined && asset.paletteDistance > resolved.maxDistance) {\n reasons.push(\n `palette distance ${asset.paletteDistance.toFixed(1)} exceeds ${resolved.maxDistance}`,\n )\n }\n if (\n resolved.minTransparency !== undefined &&\n asset.transparency < resolved.minTransparency\n ) {\n reasons.push(\n `transparency ${(asset.transparency * 100).toFixed(1)}% is below ` +\n `${(resolved.minTransparency * 100).toFixed(1)}%`,\n )\n }\n if (resolved.maxColors !== undefined && asset.colorCount > resolved.maxColors) {\n reasons.push(`color count ${asset.colorCount} exceeds ${resolved.maxColors}`)\n }\n if (reasons.length) violations.push({ id: asset.id, reasons })\n }\n\n return {\n safe: violations.length === 0 && audit.missing.length === 0 && audit.unreadable.length === 0,\n thresholds: resolved,\n outliers: [...relativeIds],\n violations,\n missing: [...audit.missing],\n unreadable: [...audit.unreadable],\n }\n}\n\nexport function hex(c: { r: number; g: number; b: number }): string {\n return `#${[c.r, c.g, c.b].map((v) => v.toString(16).padStart(2, \"0\")).join(\"\")}`\n}\n","import { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { sha256File } from \"../hash.ts\"\nimport { currentEntryOutputPath } from \"../outputs.ts\"\nimport { lockKey, type Lock, type ResolvedSpec } from \"../types.ts\"\nimport { inspectQualityProfile } from \"./quality-profile.ts\"\n\nexport interface RevisionReadiness {\n ready: boolean\n reason: string\n}\n\n/**\n * Prove that a revision points at the current bytes of a current parent.\n *\n * This runs during planning and again immediately before submission. The\n * second check closes the gap where a source or mask changes after a plan was\n * printed but before a paid provider request begins.\n */\nexport async function inspectRevisionReadiness(\n spec: ResolvedSpec,\n lock: Lock,\n): Promise<RevisionReadiness | null> {\n if (!spec.revision) return null\n return inspectRevision(spec, lock, new Set())\n}\n\nasync function inspectRevision(\n spec: ResolvedSpec,\n lock: Lock,\n seen: Set<string>,\n): Promise<RevisionReadiness> {\n const revision = spec.revision\n if (!revision) return { ready: true, reason: \"asset has no revision inputs\" }\n const dependency = await inspectParent(revision.sourceSpec, lock, seen)\n if (!dependency.ready) {\n return {\n ready: false,\n reason: `revision source ${spec.styleId}/${revision.sourceAssetId} is not ready: ${dependency.reason}`,\n }\n }\n\n if (!revision.sourceSha256 || !existsSync(revision.sourceFile)) {\n return { ready: false, reason: `revision source is missing: ${revision.sourceFile}` }\n }\n if ((await sha256File(revision.sourceFile)) !== revision.sourceSha256) {\n return { ready: false, reason: \"revision source changed after the manifest was resolved\" }\n }\n\n if (revision.maskFile) {\n if (!revision.maskSha256 || !existsSync(revision.maskFile)) {\n return { ready: false, reason: `revision mask is missing: ${revision.maskFile}` }\n }\n if ((await sha256File(revision.maskFile)) !== revision.maskSha256) {\n return { ready: false, reason: \"revision mask changed after the manifest was resolved\" }\n }\n }\n\n return { ready: true, reason: \"revision inputs are current\" }\n}\n\nexport async function requireRevisionReady(spec: ResolvedSpec, lock: Lock): Promise<void> {\n const inspection = await inspectRevisionReadiness(spec, lock)\n if (inspection && !inspection.ready) throw new Error(inspection.reason)\n}\n\nasync function inspectParent(\n spec: ResolvedSpec,\n lock: Lock,\n seen: Set<string>,\n): Promise<RevisionReadiness> {\n const key = lockKey(spec.styleId, spec.assetId)\n if (seen.has(key)) return { ready: false, reason: `revision dependency cycle at ${key}` }\n const nextSeen = new Set(seen)\n nextSeen.add(key)\n\n if (spec.revision) {\n const inputs = await inspectRevision(spec, lock, nextSeen)\n if (!inputs.ready) return inputs\n }\n\n if (spec.quality) {\n const quality = await inspectQualityProfile(spec, lock)\n return quality?.state === \"approved\"\n ? { ready: true, reason: \"approved quality output is current\" }\n : {\n ready: false,\n reason: `quality output is ${quality?.state ?? \"missing\"}` +\n (quality?.reason ? ` (${quality.reason})` : \"\"),\n }\n }\n\n if (spec.source) {\n const source = path.resolve(spec.root, spec.source)\n return existsSync(source)\n ? { ready: true, reason: \"declared source is present\" }\n : { ready: false, reason: `declared source is missing: ${spec.source}` }\n }\n\n const entry = lock.entries[key]\n if (!entry) return { ready: false, reason: \"parent is not in the lockfile\" }\n if (entry.specHash !== spec.specHash) {\n return { ready: false, reason: \"parent generation spec is stale\" }\n }\n if (entry.status !== \"downloaded\") {\n return { ready: false, reason: `parent is ${entry.status}, not downloaded` }\n }\n if (!entry.outputs.length) return { ready: false, reason: \"parent has no recorded output\" }\n for (let index = 0; index < entry.outputs.length; index++) {\n const output = entry.outputs[index]!\n const file = currentEntryOutputPath(entry, spec, index)\n if (!existsSync(file)) return { ready: false, reason: `parent output is missing: ${file}` }\n if ((await sha256File(file)) !== output.sha256) {\n return { ready: false, reason: `parent output was modified: ${file}` }\n }\n }\n return { ready: true, reason: \"parent output is current\" }\n}\n","import {\n DEFAULT_RATE_LIMIT,\n formatCost,\n validateCostEstimate,\n type CostUnit,\n type Provider,\n} from \"../provider.ts\"\nimport { saveLock, upsert } from \"../lock.ts\"\nimport { resolveStyleImages, type LoadedManifest } from \"../manifest.ts\"\nimport type { Lock, ResolvedSpec, ResolvedStyleImage } from \"../types.ts\"\nimport type { PlanItem } from \"./plan.ts\"\nimport { requireRevisionReady } from \"./revision.ts\"\n\n/**\n * Two distinct limits, easy to conflate:\n * - submissions must be spaced apart (a rate, global across the account)\n * - background jobs in flight (a count)\n *\n * Both are the provider's own constraint (PixelLab: >2s apart; Tier 1=8,\n * Tier 2=10, Tier 3=20 in flight) surfaced through `provider.rateLimit()`,\n * not a number this pipeline layer should know on its own — a second\n * provider with different limits must not silently inherit PixelLab's.\n *\n * Submission is fast and job execution is slow, so the correct shape is a\n * serial submit loop with a global spacing gate, which pauses when too many\n * jobs are still running. Parallel workers each sleeping `spacing` would give a\n * global rate of workers/spacing and quietly breach the first limit.\n */\nconst IN_FLIGHT_POLL_MS = 5000\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))\n\nexport interface SubmitOptions {\n maxInFlight?: number\n spacingMs?: number\n /** How often to re-check occupied background-job slots. */\n slotPollMs?: number\n /** Stop waiting for an unreadable/stuck slot instead of hanging forever. */\n slotTimeoutMs?: number\n /** Refuse to submit if the run would exceed this much, in the provider's unit. */\n budget?: number\n onProgress?: (msg: string) => void\n}\n\nexport interface SubmitResult {\n submitted: number\n failed: number\n /** Successful-submission estimates in `unit`. */\n spent: number\n unit: CostUnit\n}\n\nexport async function submit(\n provider: Provider,\n loaded: LoadedManifest,\n items: PlanItem[],\n lock: Lock,\n lockPath: string,\n opts: SubmitOptions = {},\n): Promise<SubmitResult> {\n const limits = provider.rateLimit?.() ?? DEFAULT_RATE_LIMIT\n const maxInFlight = opts.maxInFlight ?? limits.maxInFlight\n const spacing = opts.spacingMs ?? limits.spacingMs\n const slotPollMs = opts.slotPollMs ?? IN_FLIGHT_POLL_MS\n const slotTimeoutMs = opts.slotTimeoutMs ?? 15 * 60 * 1000\n const log = opts.onProgress ?? (() => {})\n\n const estimates = new Map(items.map((item) => [\n item.key,\n validateCostEstimate(provider.id, provider.estimate(item.spec)),\n ]))\n const units = new Set([...estimates.values()].map((estimate) => estimate.unit))\n if (units.size > 1) {\n throw new Error(`Provider \"${provider.id}\" returned mixed cost units for one submission batch`)\n }\n const unit = units.values().next().value ?? \"free\"\n\n if (opts.budget != null) {\n const cost = [...estimates.values()].reduce((sum, estimate) => sum + estimate.amount, 0)\n if (cost > opts.budget) {\n throw new Error(\n `This run would spend ${formatCost(unit, cost)} but the budget is ` +\n `${formatCost(unit, opts.budget)}. ` +\n `Narrow it with --only/--style, or raise --budget.`,\n )\n }\n }\n\n const styleImages = new Map<string, ResolvedStyleImage[]>()\n for (const styleId of new Set(items.map((i) => i.spec.styleId))) {\n styleImages.set(styleId, await resolveStyleImages(loaded, styleId))\n }\n\n let submitted = 0\n let failed = 0\n let spent = 0\n let lastSubmitAt = 0\n\n /** Jobs submitted this run not yet observed as settled, with their generator. */\n const inFlight = new Map<string, ResolvedSpec>()\n let lastSlotError: string | null = null\n\n async function pruneInFlight(): Promise<void> {\n for (const [id, spec] of [...inFlight]) {\n try {\n const state = await provider.poll(id, spec.generator, { spec, tileFeature: spec.tileFeature })\n if (state.status !== \"processing\") inFlight.delete(id)\n lastSlotError = null\n } catch (err) {\n // A transient provider/network error is not evidence that a paid job\n // settled. Keep the slot occupied so we never exceed the upstream cap.\n lastSlotError = err instanceof Error ? err.message : String(err)\n }\n }\n }\n\n async function waitForSlot(): Promise<void> {\n const started = Date.now()\n while (inFlight.size >= maxInFlight) {\n if (Date.now() - started >= slotTimeoutMs) {\n throw new Error(\n `Timed out waiting for a generation slot` +\n (lastSlotError ? `; last poll error: ${lastSlotError}` : \"\"),\n )\n }\n await sleep(slotPollMs)\n await pruneInFlight()\n }\n }\n\n for (const { spec, key } of items) {\n const estimate = estimates.get(key)!\n await waitForSlot()\n\n const since = Date.now() - lastSubmitAt\n if (since < spacing) await sleep(spacing - since)\n\n // Planning already checked this dependency, but inputs can change while a\n // long batch waits for a provider slot. Recheck at the spending boundary.\n await requireRevisionReady(spec, lock)\n\n const previousEntry = lock.entries[key]\n const supersededOutputs = previousEntry?.outputs.length\n ? previousEntry.outputs\n : previousEntry?.supersededOutputs ?? []\n\n // Record intent before spending, so an interrupted run stays diagnosable.\n upsert(lock, key, {\n styleId: spec.styleId,\n assetId: spec.assetId,\n specHash: spec.specHash,\n generator: spec.generator,\n tileFeature: spec.tileFeature ?? null,\n prompt: spec.prompt,\n width: spec.width,\n height: spec.height,\n revision: spec.revision\n ? {\n mode: spec.revision.mode,\n sourceAssetId: spec.revision.sourceAssetId,\n sourceSha256: spec.revision.sourceSha256!,\n ...(spec.revision.maskSha256 ? { maskSha256: spec.revision.maskSha256 } : {}),\n ...(spec.revision.strength == null ? {} : { strength: spec.revision.strength }),\n }\n : null,\n status: \"pending\",\n jobId: null,\n objectId: null,\n reviewObjectId: null,\n candidateIndex: null,\n error: null,\n outputs: [],\n // Keep the old ownership proof while new bytes are pending. Fetch may\n // replace that file only while its hash still matches this record.\n supersededOutputs,\n providerMetadata: {},\n sourceUrl: null,\n sourceUrls: [],\n submittedAt: new Date().toISOString(),\n cost: estimate.amount,\n costUnit: estimate.unit,\n // Persist routing before the request starts. If the process stops while\n // the provider is accepting work, a resumed run must not fall back to\n // PixelLab (the legacy lock default) for another provider's entry.\n provider: provider.id,\n downloadedAt: null,\n })\n await saveLock(lockPath, lock)\n\n lastSubmitAt = Date.now()\n try {\n // The adapter decides whether references are meaningful for this\n // generator. Keeping that policy here used to silently discard valid\n // references for non-PixelLab still providers.\n const refs = styleImages.get(spec.styleId) ?? []\n const { jobId, metadata } = await provider.submit(spec, refs)\n upsert(lock, key, {\n jobId,\n // A multi-candidate generator routes through review; record the parent\n // so `pick` knows where to look.\n reviewObjectId:\n spec.generator === \"frames\" || (estimate.candidates > 1 && !spec.tileFeature)\n ? jobId\n : null,\n status: \"processing\",\n providerMetadata: metadata\n ? { ...lock.entries[key]!.providerMetadata, [provider.id]: metadata }\n : lock.entries[key]!.providerMetadata,\n })\n inFlight.set(jobId, spec)\n submitted++\n spent += estimate.amount\n log(\n ` ${key} → ${jobId} (${spec.width}x${spec.height}` +\n (estimate.candidates > 1\n ? `, ${estimate.candidates} ${spec.tileFeature ? \"outputs\" : \"candidates\"}`\n : \"\") +\n `, ${estimate.amount})`,\n )\n } catch (err) {\n failed++\n const message = err instanceof Error ? err.message : String(err)\n // A rejected request is not billed, so cost is cleared rather than kept.\n upsert(lock, key, { status: \"failed\", error: message, cost: 0 })\n log(` FAILED ${key}: ${message}`)\n }\n await saveLock(lockPath, lock)\n }\n\n return { submitted, failed, spent, unit }\n}\n","import { saveLock, upsert } from \"../lock.ts\"\nimport type { Provider } from \"../provider.ts\"\nimport type { Lock } from \"../types.ts\"\nimport { lockKey, type ResolvedSpec } from \"../types.ts\"\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))\n\nexport interface PollOptions {\n intervalMs?: number\n timeoutMs?: number\n onProgress?: (msg: string) => void\n specs?: ResolvedSpec[]\n}\n\nexport interface PollResult {\n review: number\n completed: number\n failed: number\n stillRunning: number\n}\n\n/**\n * Advances every unfinished lock entry to its settled state.\n *\n * Safe to run repeatedly and safe to interrupt — all state lives in the\n * lockfile, so a re-run picks up exactly where the last one stopped. Provider\n * quirks (a job record that expires before its image does, review-status\n * candidate lists) are the provider's problem, not this loop's.\n */\nexport async function poll(\n provider: Provider,\n lock: Lock,\n lockPath: string,\n opts: PollOptions = {},\n): Promise<PollResult> {\n const interval = opts.intervalMs ?? 5000\n const timeout = opts.timeoutMs ?? 15 * 60 * 1000\n const log = opts.onProgress ?? (() => {})\n const started = Date.now()\n const specByKey = new Map((opts.specs ?? []).map((s) => [lockKey(s.styleId, s.assetId), s]))\n const selectedKeys = opts.specs ? new Set(specByKey.keys()) : null\n\n const result: PollResult = { review: 0, completed: 0, failed: 0, stillRunning: 0 }\n\n const pending = () =>\n Object.entries(lock.entries).filter(\n ([key, e]) =>\n e.provider === provider.id &&\n (!selectedKeys || selectedKeys.has(key)) &&\n e.jobId &&\n (e.status === \"pending\" || e.status === \"processing\"),\n )\n\n while (pending().length > 0) {\n if (Date.now() - started > timeout) {\n result.stillRunning = pending().length\n log(` timed out with ${result.stillRunning} job(s) still running — re-run \\`poll\\` to resume`)\n break\n }\n\n for (const [key, entry] of pending()) {\n try {\n const currentSpec = specByKey.get(key)\n const state = await provider.poll(entry.jobId!, entry.generator, {\n tileFeature: entry.tileFeature ?? currentSpec?.tileFeature,\n spec: currentSpec,\n })\n if (state.status === \"review\" || state.status === \"review-set\") {\n upsert(lock, key, {\n status: \"review\",\n reviewObjectId: entry.jobId,\n providerMetadata: state.metadata\n ? {\n ...entry.providerMetadata,\n [provider.id]: {\n ...entry.providerMetadata[provider.id],\n ...state.metadata,\n },\n }\n : entry.providerMetadata,\n })\n result.review++\n log(\n state.status === \"review-set\"\n ? ` review ${key} (${state.frameUrls.length} ordered frames)`\n : ` review ${key} (${state.candidateUrls.length} candidates)`,\n )\n } else if (state.status === \"ready\") {\n const sourceUrls = state.sources?.length\n ? state.sources\n : state.sourceUrl\n ? [{ url: state.sourceUrl }]\n : []\n upsert(lock, key, {\n status: \"selected\",\n objectId: state.objectId,\n sourceUrl: sourceUrls[0]?.url ?? null,\n sourceUrls,\n providerMetadata: state.metadata\n ? {\n ...entry.providerMetadata,\n [provider.id]: {\n ...entry.providerMetadata[provider.id],\n ...state.metadata,\n },\n }\n : entry.providerMetadata,\n error: null,\n })\n result.completed++\n log(` ready ${key}`)\n } else if (state.status === \"failed\") {\n upsert(lock, key, { status: \"failed\", error: state.error })\n result.failed++\n log(` FAILED ${key}: ${state.error}`)\n }\n } catch (err) {\n log(` error polling ${key}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n\n await saveLock(lockPath, lock)\n if (pending().length > 0) await sleep(interval)\n }\n\n await saveLock(lockPath, lock)\n return result\n}\n","import { existsSync } from \"node:fs\"\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport type { Provider } from \"../provider.ts\"\nimport { sha256, sha256File } from \"../hash.ts\"\nimport { saveLock, upsert } from \"../lock.ts\"\nimport {\n expectedOutputPath,\n currentOutputPath,\n normalizeLockOutputPaths,\n portableOutputPath,\n resolveOutputPath,\n} from \"../outputs.ts\"\nimport { lockKey, type Lock, type LockOutput, type ResolvedSpec } from \"../types.ts\"\nimport {\n cacheFileName,\n detectMediaType,\n MediaType,\n validateMedia,\n type MediaType as MediaKind,\n} from \"../media.ts\"\nimport { shouldPersistSourceUrl } from \"../source-url.ts\"\n\nexport interface FetchResult {\n downloaded: number\n skipped: number\n failed: number\n}\n\n/**\n * Downloads every selected object to its manifest-defined path and records the\n * file hash. The hash is what lets `plan` tell \"untouched\" from \"edited by\n * hand\" on later runs, so a manual retouch is never silently clobbered. The\n * same hash keys a local content cache, allowing `restore` to outlive a\n * provider's temporary storage URL.\n */\nexport async function fetchAssets(\n provider: Provider,\n specs: ResolvedSpec[],\n lock: Lock,\n lockPath: string,\n opts: {\n onProgress?: (msg: string) => void\n concurrency?: number\n repair?: boolean\n /** Replace an existing untracked or modified destination. Explicit ownership override. */\n force?: boolean\n /** Content-addressed media cache. Defaults beside the lockfile; false disables it. */\n cacheDir?: string | false\n } = {},\n): Promise<FetchResult> {\n const log = opts.onProgress ?? (() => {})\n const result: FetchResult = { downloaded: 0, skipped: 0, failed: 0 }\n const specByKey = new Map(specs.map((s) => [lockKey(s.styleId, s.assetId), s]))\n normalizeLockOutputPaths(lock, specs)\n const cacheDir =\n opts.cacheDir === false\n ? null\n : path.resolve(opts.cacheDir ?? path.join(path.dirname(lockPath), \".pixelkiln\", \"cache\"))\n\n // Downloads are independent and IO-bound, so they run concurrently. The\n // lockfile is still written after each one, keeping an interrupted run\n // recoverable.\n const pending = Object.entries(lock.entries).filter(([key, e]) => {\n if (e.provider !== provider.id || !specByKey.has(key)) return false\n if (e.status === \"selected\" || e.status === \"download-failed\") return true\n if (!opts.repair || e.status !== \"downloaded\") return false\n const spec = specByKey.get(key)\n return e.outputs.length === 0 || !spec ||\n e.outputs.some((output) => !existsSync(resolveOutputPath(output.path, spec.root)))\n })\n const concurrency = Math.min(Math.max(1, opts.concurrency ?? 8), Math.max(1, pending.length))\n let cursor = 0\n\n async function worker(): Promise<void> {\n for (;;) {\n const next = pending[cursor++]\n if (!next) return\n const [key, entry] = next\n\n const spec = specByKey.get(key)\n if (!spec) {\n // In the lockfile but no longer in the manifest — the asset was removed.\n log(` skip ${key} (not in current manifest)`)\n result.skipped++\n continue\n }\n if (entry.specHash !== spec.specHash) {\n log(` skip ${key} (source belongs to a stale spec)`)\n result.skipped++\n continue\n }\n const sources = entry.sourceUrls?.length\n ? entry.sourceUrls\n : entry.sourceUrl\n ? [{ url: entry.sourceUrl }]\n : opts.repair && entry.outputs.length\n ? entry.outputs.map((o) => ({ url: \"\", role: o.role, mediaType: o.mediaType }))\n : []\n if (!sources.length) {\n upsert(lock, key, {\n status: \"download-failed\",\n error: \"no persisted source URL to download; poll the job again if it still exists upstream\",\n })\n result.failed++\n continue\n }\n\n const outputs: LockOutput[] = []\n try {\n for (let index = 0; index < sources.length; index++) {\n const source = sources[index]!\n const recorded = entry.outputs.find((o) =>\n source.role ? o.role === source.role : !o.role && sources.length === 1,\n )\n const target = recorded\n ? resolveOutputPath(recorded.path, spec.root)\n : expectedOutputPath(spec, source.role, index, sources.length, source.mediaType)\n\n if (existsSync(target)) {\n const currentHash = await sha256File(target)\n if (recorded && currentHash === recorded.sha256) {\n if (cacheDir) {\n await cacheMedia(\n cacheDir,\n await readFile(target),\n recorded.mediaType ?? MediaType.PNG,\n recorded.sha256,\n )\n }\n outputs.push({ ...recorded, path: portableOutputPath(target, spec.root) })\n continue\n }\n\n const superseded = (entry.supersededOutputs ?? []).find((output, oldIndex, all) =>\n currentOutputPath(output, spec, oldIndex, all.length) === target,\n )\n if (!opts.force) {\n if (!recorded && superseded && currentHash === superseded.sha256) {\n // A stale spec was intentionally regenerated. The old bytes\n // are still exactly the ones PixelKiln wrote, so replacing\n // them does not take ownership of a manual edit.\n } else if (recorded || superseded) {\n throw new Error(\n `refusing to overwrite modified output ${target}; pass --force to replace it`,\n )\n } else {\n throw new Error(\n `refusing to overwrite untracked output ${target}; pass --force to replace it`,\n )\n }\n }\n log(\n ` replace ${path.relative(process.cwd(), target)}` +\n (opts.force ? \" (--force)\" : \" (previous tracked generation)\"),\n )\n }\n\n const expectedMediaType = source.mediaType ?? recorded?.mediaType ?? MediaType.PNG\n let buf = recorded && cacheDir\n ? await readCachedMedia(cacheDir, recorded.sha256, expectedMediaType)\n : null\n if (buf) {\n log(` cached ${path.relative(process.cwd(), target)}`)\n } else {\n if (!source.url) {\n throw new Error(`no source URL or cached bytes remain for ${source.role ?? \"asset\"}`)\n }\n buf = await provider.download(source.url)\n }\n let mediaType: MediaKind\n try {\n mediaType = validateMedia(buf, expectedMediaType)\n } catch (err) {\n const label = expectedMediaType === MediaType.GIF ? \"GIF\" : \"PNG\"\n const mismatch = detectMediaType(buf) !== expectedMediaType\n throw new Error(\n `response for ${source.role ?? \"asset\"} was not ${mismatch ? \"a\" : \"a valid\"} ${label}` +\n (mismatch ? ` (${buf.length} bytes)` : `: ${err instanceof Error ? err.message : String(err)}`),\n )\n }\n if (cacheDir) await cacheMedia(cacheDir, buf, mediaType)\n await mkdir(path.dirname(target), { recursive: true })\n const tmp = `${target}.pixelkiln.tmp`\n await writeFile(tmp, buf)\n outputs.push({\n path: portableOutputPath(target, spec.root),\n sha256: sha256(buf),\n ...(source.role ? { role: source.role } : {}),\n mediaType,\n })\n // Record the intended rename before performing it. If the process\n // dies in either half of this two-step commit, the next repair sees\n // a missing recorded output and safely downloads it again; it never\n // sees an untracked final file and gets stuck refusing to overwrite.\n upsert(lock, key, { outputs: mergeOutputs(entry.outputs, outputs) })\n await saveLock(lockPath, lock)\n await rename(tmp, target)\n log(` wrote ${path.relative(process.cwd(), target)}`)\n }\n const persistentSources = sources.filter((source) => shouldPersistSourceUrl(source.url))\n upsert(lock, key, {\n status: \"downloaded\",\n provider: provider.id,\n outputs,\n // A finished lock may be committed. Inline bytes, machine-local\n // paths, and credential-bearing signed URLs are useful while a\n // download is retryable but must not survive successful ingestion.\n sourceUrl: persistentSources[0]?.url ?? null,\n sourceUrls: persistentSources,\n downloadedAt: new Date().toISOString(),\n error: null,\n supersededOutputs: [],\n })\n result.downloaded++\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n upsert(lock, key, {\n status: \"download-failed\",\n outputs: mergeOutputs(entry.outputs, outputs),\n error: `download failed: ${message}`,\n })\n result.failed++\n log(` FAILED ${key}: ${message}`)\n }\n await saveLock(lockPath, lock)\n }\n }\n\n await Promise.all(Array.from({ length: concurrency }, worker))\n await saveLock(lockPath, lock)\n return result\n}\n\nasync function readCachedMedia(\n cacheDir: string,\n hash: string,\n mediaType: MediaKind,\n): Promise<Buffer | null> {\n const file = path.join(cacheDir, cacheFileName(hash, mediaType))\n if (!existsSync(file)) return null\n try {\n const buf = await readFile(file)\n if (sha256(buf) !== hash) return null\n validateMedia(buf, mediaType)\n return buf\n } catch {\n return null\n }\n}\n\nasync function cacheMedia(\n cacheDir: string,\n buf: Buffer,\n mediaType: MediaKind,\n knownHash?: string,\n): Promise<void> {\n const hash = knownHash ?? sha256(buf)\n validateMedia(buf, mediaType)\n const file = path.join(cacheDir, cacheFileName(hash, mediaType))\n if (await readCachedMedia(cacheDir, hash, mediaType)) return\n await mkdir(cacheDir, { recursive: true })\n const tmp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`\n await writeFile(tmp, buf)\n try {\n await rename(tmp, file)\n } catch (err) {\n // Two workers can discover the same content concurrently. If the other\n // one won the rename race, the cache is already complete.\n if (!existsSync(file)) throw err\n } finally {\n await rm(tmp, { force: true })\n }\n}\n\nfunction mergeOutputs(previous: LockOutput[], current: LockOutput[]): LockOutput[] {\n const merged = new Map<string, LockOutput>()\n for (const output of [...previous, ...current]) {\n merged.set(output.role ? `role:${output.role}` : `path:${output.path}`, output)\n }\n return [...merged.values()]\n}\n\n/**\n * Applies the manifest's tags to each generated object upstream. Tagging is\n * free and synchronous, and it makes the account itself queryable — the thing\n * that was missing when 350 objects accumulated with no way to tell which 65\n * were the keepers.\n */\nexport async function pushTags(\n provider: Provider,\n specs: ResolvedSpec[],\n lock: Lock,\n opts: { onProgress?: (msg: string) => void } = {},\n): Promise<number> {\n const log = opts.onProgress ?? (() => {})\n const specByKey = new Map(specs.map((s) => [lockKey(s.styleId, s.assetId), s]))\n let tagged = 0\n\n for (const [key, entry] of Object.entries(lock.entries)) {\n const spec = specByKey.get(key)\n if (!spec || entry.provider !== provider.id || !entry.objectId) continue\n // pixflux results are local files with a synthetic id, not account\n // objects — tagging one would 404.\n if (entry.generator === \"pixflux\") continue\n if (!provider.setTags) return tagged // capability absent; nothing to do\n try {\n await provider.setTags(entry.objectId, spec.tags)\n tagged++\n } catch (err) {\n log(` tag failed ${key}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n return tagged\n}\n","const SENSITIVE_QUERY_KEYS = new Set([\n \"access_token\",\n \"apikey\",\n \"api_key\",\n \"auth\",\n \"authorization\",\n \"awsaccesskeyid\",\n \"googleaccessid\",\n \"key\",\n \"sig\",\n])\n\n/** True when a URL contains credentials or a temporary signing secret. */\nexport function isSensitiveSourceUrl(value: string): boolean {\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n return false\n }\n if (parsed.username || parsed.password) return true\n for (const key of parsed.searchParams.keys()) {\n const normalized = key.toLowerCase()\n if (\n SENSITIVE_QUERY_KEYS.has(normalized) ||\n normalized.includes(\"credential\") ||\n normalized.includes(\"signature\") ||\n normalized.includes(\"security-token\") ||\n normalized.includes(\"token\")\n ) return true\n }\n return false\n}\n\n/**\n * Whether a provider source is safe and useful to retain after its bytes have\n * reached the destination. Inline and machine-local sources are transient;\n * credential-bearing URLs must not settle into a committable lockfile.\n */\nexport function shouldPersistSourceUrl(value: string): boolean {\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n // Preserve unknown legacy/provider references. They remain subject to\n // provider download validation and contain no parseable URL credentials.\n return true\n }\n if (parsed.protocol === \"data:\" || parsed.protocol === \"file:\") return false\n return !isSensitiveSourceUrl(value)\n}\n","import { constants, existsSync } from \"node:fs\"\nimport { access, stat } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport type { LoadedManifest } from \"../manifest.ts\"\nimport type { Provider } from \"../provider.ts\"\nimport type { Lock, ResolvedSpec } from \"../types.ts\"\nimport { sha256File } from \"../hash.ts\"\nimport { currentEntryOutputPath, resolveOutputPath } from \"../outputs.ts\"\nimport { cacheFileName, MediaType } from \"../media.ts\"\nimport { buildPlan, resumeActions, summarize } from \"./plan.ts\"\n\nexport type DoctorLevel = \"ok\" | \"warning\" | \"error\"\n\nexport interface DoctorCheck {\n id: string\n level: DoctorLevel\n message: string\n}\n\nexport interface DoctorReport {\n ok: boolean\n checks: DoctorCheck[]\n}\n\nexport interface DoctorOptions {\n /** Provider checks for a mixed manifest. Supersedes the legacy single target. */\n providers?: DoctorProviderTarget[]\n provider?: Provider\n /** Skip provider connectivity while retaining every local check. */\n offline?: boolean\n apiKeyPresent?: boolean\n credentialEnv?: string\n}\n\nexport interface DoctorProviderTarget {\n id: string\n provider?: Provider\n apiKeyPresent: boolean\n credentialEnv?: string\n missingCredentialEnvs?: readonly string[]\n}\n\n/**\n * Checks the whole project without changing it. Loading/resolving the manifest\n * and loading the lock happen before this function, so schema, style-image,\n * filter, and output-collision validation have already passed if it runs.\n */\nexport async function doctor(\n loaded: LoadedManifest,\n specs: ResolvedSpec[],\n lock: Lock,\n lockPath: string,\n opts: DoctorOptions = {},\n): Promise<DoctorReport> {\n const checks: DoctorCheck[] = []\n const add = (id: string, level: DoctorLevel, message: string) => checks.push({ id, level, message })\n\n add(\n \"manifest\",\n \"ok\",\n `${Object.keys(loaded.manifest.styles).length} style(s), ` +\n `${Object.keys(loaded.manifest.assets).length} asset(s), ${specs.length} resolved spec(s)`,\n )\n add(\"lock\", \"ok\", `${Object.keys(lock.entries).length} valid v2 lock entr(ies)`)\n\n const dirs = [...new Set(specs.flatMap((spec) => [\n path.dirname(spec.outFile),\n ...(spec.quality ? [path.dirname(spec.quality.outFile)] : []),\n ]))]\n const unwritable: string[] = []\n for (const dir of dirs) {\n const ancestor = await nearestExistingDirectory(dir)\n try {\n await access(ancestor, constants.W_OK)\n } catch {\n unwritable.push(dir)\n }\n }\n add(\n \"outputs\",\n unwritable.length ? \"error\" : \"ok\",\n unwritable.length\n ? `output path is not writable: ${unwritable.slice(0, 3).join(\", \")}`\n : `${dirs.length} output director${dirs.length === 1 ? \"y is\" : \"ies are\"} writable`,\n )\n\n const outputOwners = new Map<string, string>()\n const duplicateOutputs: string[] = []\n const specByKey = new Map(specs.map((spec) => [`${spec.styleId}/${spec.assetId}`, spec]))\n for (const [key, entry] of Object.entries(lock.entries)) {\n for (let index = 0; index < entry.outputs.length; index++) {\n const output = entry.outputs[index]!\n const spec = specByKey.get(key)\n const absolute = spec\n ? currentEntryOutputPath(entry, spec, index)\n : resolveOutputPath(output.path, path.dirname(lockPath))\n const owner = outputOwners.get(absolute)\n if (owner && owner !== key) duplicateOutputs.push(`${output.path} (${owner}, ${key})`)\n outputOwners.set(absolute, key)\n }\n }\n if (duplicateOutputs.length) {\n // Name the remedy. This almost always means an asset was renamed or moved\n // between styles and the old entry stayed behind still claiming the path,\n // which `prune` clears — reporting the breakage without saying what fixes\n // it left the only route as hand-editing the lockfile.\n add(\n \"lock-outputs\",\n \"error\",\n `lock entries share output paths: ${duplicateOutputs.slice(0, 3).join(\", \")}` +\n `${duplicateOutputs.length > 3 ? `, and ${duplicateOutputs.length - 3} more` : \"\"}` +\n ` — run \\`pixelkiln prune\\` if the manifest no longer declares them`,\n )\n } else {\n add(\"lock-outputs\", \"ok\", `${outputOwners.size} recorded output path(s) are uniquely owned`)\n }\n\n const cacheDir = path.join(path.dirname(lockPath), \".pixelkiln\", \"cache\")\n const stranded: string[] = []\n const invalidState: string[] = []\n const staleMapUrls: string[] = []\n const now = Date.now()\n for (const [key, entry] of Object.entries(lock.entries)) {\n if ((entry.status === \"pending\" || entry.status === \"processing\") && !entry.jobId) {\n invalidState.push(`${key} (${entry.status} without job id)`)\n }\n if (entry.status === \"review\" && !entry.reviewObjectId) {\n invalidState.push(`${key} (review without review object id)`)\n }\n if (entry.status !== \"selected\" && entry.status !== \"download-failed\") continue\n const hasSource = Boolean(entry.sourceUrl || entry.sourceUrls?.length)\n let hasCache = false\n for (const output of entry.outputs) {\n const cached = path.join(\n cacheDir,\n cacheFileName(output.sha256, output.mediaType ?? MediaType.PNG),\n )\n if (existsSync(cached) && (await sha256File(cached)) === output.sha256) {\n hasCache = true\n break\n }\n }\n if (!hasSource && !hasCache) stranded.push(key)\n if (\n entry.generator === \"map\" &&\n entry.submittedAt &&\n now - Date.parse(entry.submittedAt) > 8 * 60 * 60 * 1000\n ) {\n staleMapUrls.push(key)\n }\n }\n add(\n \"recovery\",\n stranded.length || invalidState.length ? \"error\" : staleMapUrls.length ? \"warning\" : \"ok\",\n invalidState.length\n ? `invalid resumable state: ${invalidState.slice(0, 5).join(\", \")}`\n : stranded.length\n ? `${stranded.length} unfinished entr(ies) have neither source URLs nor cached bytes: ${stranded.slice(0, 5).join(\", \")}`\n : staleMapUrls.length\n ? `${staleMapUrls.length} unfinished map entr(ies) are older than the provider's 8-hour job window`\n : \"no unfinished downloads are stranded without a source or cached bytes\",\n )\n\n const plan = await buildPlan(specs, lock)\n const counts = summarize(plan)\n const unsettled = plan.items.filter((i) => i.state !== \"ok\").length\n add(\n \"plan\",\n unsettled ? \"warning\" : \"ok\",\n unsettled\n ? `${unsettled} spec(s) are not current: ` +\n Object.entries(counts)\n .filter(([, n]) => n > 0)\n .map(([state, n]) => `${n} ${state}`)\n .join(\", \")\n : \"every resolved spec is current\",\n )\n\n const resumable = resumeActions(specs, lock)\n add(\n \"next-actions\",\n resumable.length ? \"warning\" : \"ok\",\n resumable.length\n ? \"resume paid work without regenerating: \" +\n resumable\n .map((action) =>\n `pixelkiln ${action.command} (${action.keys.length} asset${action.keys.length === 1 ? \"\" : \"s\"})`\n )\n .join(\", \")\n : \"no generation stage is waiting for poll, pick, or fetch\",\n )\n\n const quality = plan.items.flatMap((item) => item.quality ? [item.quality] : [])\n const qualityPending = quality.filter((item) => item.state !== \"approved\")\n if (quality.length) {\n add(\n \"quality\",\n qualityPending.length ? \"warning\" : \"ok\",\n qualityPending.length\n ? `${qualityPending.length}/${quality.length} configured quality output(s) are not approved: ` +\n qualityPending.slice(0, 3).map((item) => `${item.key} ${item.state}`).join(\", \")\n : `all ${quality.length} configured quality output(s) are current and approved`,\n )\n }\n\n const legacyTarget = !opts.providers\n const targets: DoctorProviderTarget[] = opts.providers ?? [{\n id: opts.provider?.id ?? \"provider\",\n provider: opts.provider,\n apiKeyPresent: opts.apiKeyPresent ?? Boolean(opts.provider),\n credentialEnv: opts.credentialEnv,\n }]\n for (const target of targets) {\n const checkId = targets.length === 1 ? \"provider\" : `provider:${target.id}`\n if (opts.offline) {\n add(checkId, \"warning\", `${target.id} connectivity skipped (--dry-run)`)\n } else if (!target.provider) {\n add(\n checkId,\n \"error\",\n !target.apiKeyPresent\n ? `${target.missingCredentialEnvs?.length\n ? target.missingCredentialEnvs.join(\", \")\n : target.credentialEnv ?? (legacyTarget ? \"PIXELLAB_API_KEY\" : `${target.id} credential`)} ` +\n `${target.missingCredentialEnvs && target.missingCredentialEnvs.length > 1 ? \"are\" : \"is\"} not configured`\n : `${target.id} is not configured`,\n )\n } else if (!target.provider.balance && !target.provider.checkConnection) {\n add(checkId, \"ok\", `${target.id} configured; connectivity check unavailable`)\n } else if (!target.provider.balance) {\n try {\n await target.provider.checkConnection!()\n add(checkId, \"ok\", `${target.id} reachable; balance reporting unavailable`)\n } catch (err) {\n add(\n checkId,\n \"error\",\n `${legacyTarget ? \"provider\" : target.id} connectivity failed: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n } else {\n try {\n const balance = await target.provider.balance()\n add(\n checkId,\n \"ok\",\n `${target.id} reachable; ${balance.remaining} ${balance.unit} remaining`,\n )\n } catch (err) {\n add(\n checkId,\n \"error\",\n `${legacyTarget ? \"provider\" : target.id} connectivity failed: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n }\n\n return { ok: !checks.some((c) => c.level === \"error\"), checks }\n}\n\nasync function nearestExistingDirectory(start: string): Promise<string> {\n let current = start\n for (;;) {\n try {\n if ((await stat(current)).isDirectory()) return current\n } catch {\n // Walk upward until a parent exists; creating descendants needs write\n // permission on that nearest existing ancestor.\n }\n const parent = path.dirname(current)\n if (parent === current) return current\n current = parent\n }\n}\n","import { existsSync } from \"node:fs\"\nimport { readFile, writeFile } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { requireList, validateCostEstimate, type Provider, type RemoteAsset } from \"../provider.ts\"\nimport { sha256 } from \"../hash.ts\"\nimport { loadCache, saveCache, pruneCache, cachePathFor, type HashCache } from \"../cache.ts\"\nimport { saveLock, upsert } from \"../lock.ts\"\nimport { portableOutputPath } from \"../outputs.ts\"\nimport { decodePng } from \"../png.ts\"\nimport { shouldPersistSourceUrl } from \"../source-url.ts\"\nimport { lockKey, type Lock, type ResolvedSpec } from \"../types.ts\"\n\nexport interface AdoptResult {\n scanned: number\n matched: number\n unmatchedLocal: string[]\n /** Objects on the account that correspond to no local file — safe to delete. */\n unmatchedRemote: RemoteAsset[]\n ambiguous: string[]\n}\n\n/**\n * Reconciles an account full of previously generated objects against the files\n * already committed in the repo, and writes the mapping into the lockfile.\n *\n * Matching is by exact SHA-256 of the image bytes. That was verified to hold:\n * a file downloaded from PixelLab storage is byte-identical to the copy sitting\n * in the repo, so a hash match is proof of provenance rather than a guess. No\n * fuzzy prompt matching is involved and nothing is regenerated.\n */\nexport async function adopt(\n provider: Provider,\n specs: ResolvedSpec[],\n lock: Lock,\n lockPath: string,\n opts: { onProgress?: (msg: string) => void; concurrency?: number; noCache?: boolean } = {},\n): Promise<AdoptResult> {\n const log = opts.onProgress ?? (() => {})\n const concurrency = opts.concurrency ?? 8\n // Generated objects are immutable, so a hash computed once stays valid.\n const cachePath = cachePathFor(lockPath)\n const cache: HashCache = opts.noCache ? { version: 1, hashes: {} } : await loadCache(cachePath)\n let cacheHits = 0\n\n // 1. Hash every local file the manifest expects to exist.\n const localByHash = new Map<string, ResolvedSpec[]>()\n const unmatchedLocal: string[] = []\n for (const spec of specs) {\n if (!existsSync(spec.outFile)) {\n unmatchedLocal.push(`${spec.styleId}/${spec.assetId} (no file at ${spec.outFile})`)\n continue\n }\n const bytes = await readFile(spec.outFile)\n try {\n decodePng(bytes)\n } catch (err) {\n unmatchedLocal.push(\n `${spec.styleId}/${spec.assetId} (invalid PNG: ` +\n `${err instanceof Error ? err.message : String(err)})`,\n )\n continue\n }\n const hash = sha256(bytes)\n const bucket = localByHash.get(hash) ?? []\n bucket.push(spec)\n localByHash.set(hash, bucket)\n }\n log(` hashed ${localByHash.size} distinct local image(s)`)\n\n // 2. Walk the account and hash every remote object's image.\n const remote: RemoteAsset[] = []\n for await (const obj of requireList(provider)()) remote.push(obj)\n log(` found ${remote.length} object(s) on the account`)\n\n const matchedRemote = new Set<string>()\n const ambiguous: string[] = []\n let matched = 0\n let cursor = 0\n\n async function worker() {\n for (;;) {\n const obj = remote[cursor++]\n if (!obj) return\n const url = obj.previewUrl\n if (!url || obj.status !== \"completed\") continue\n\n let hash: string | undefined = cache.hashes[obj.id]\n if (hash) {\n cacheHits++\n } else {\n try {\n const bytes = await provider.download(url)\n decodePng(bytes)\n hash = sha256(bytes)\n } catch {\n continue\n }\n cache.hashes[obj.id] = hash\n }\n\n const hits = localByHash.get(hash)\n if (!hits?.length) continue\n\n matchedRemote.add(obj.id)\n for (const spec of hits) {\n const key = lockKey(spec.styleId, spec.assetId)\n const existing = lock.entries[key]\n if (existing?.objectId && existing.objectId !== obj.id) {\n // Two account objects produced identical bytes. Harmless, but the\n // first wins so re-running adopt stays deterministic.\n ambiguous.push(`${key}: already mapped to ${existing.objectId}, also matches ${obj.id}`)\n continue\n }\n const durableSource = shouldPersistSourceUrl(url) ? url : null\n upsert(lock, key, {\n styleId: spec.styleId,\n assetId: spec.assetId,\n // Deliberately the CURRENT spec hash: adoption declares \"the file on\n // disk satisfies today's spec\", so plan reports it as ok, not stale.\n specHash: spec.specHash,\n generator: spec.generator,\n prompt: obj.prompt || spec.prompt,\n width: obj.width,\n height: obj.height,\n jobId: obj.id,\n objectId: obj.id,\n reviewObjectId: null,\n candidateIndex: null,\n status: \"downloaded\",\n error: null,\n sourceUrl: durableSource,\n sourceUrls: durableSource ? [{ url: durableSource }] : [],\n outputs: [{ path: portableOutputPath(spec.outFile, spec.root), sha256: hash }],\n submittedAt: obj.createdAt,\n downloadedAt: new Date().toISOString(),\n cost: 0, // already paid for, in a previous billing period\n costUnit: validateCostEstimate(provider.id, provider.estimate(spec)).unit,\n provider: provider.id,\n })\n matched++\n log(` adopted ${key} ← ${obj.id}`)\n }\n }\n }\n\n await Promise.all(Array.from({ length: Math.min(concurrency, remote.length || 1) }, worker))\n await saveLock(lockPath, lock)\n\n if (!opts.noCache) {\n pruneCache(cache, new Set(remote.map((o) => o.id)))\n await saveCache(cachePath, cache)\n if (cacheHits) log(` reused ${cacheHits} cached hash(es); downloaded ${remote.length - cacheHits}`)\n }\n\n return {\n scanned: remote.length,\n matched,\n unmatchedLocal,\n unmatchedRemote: remote.filter((o) => !matchedRemote.has(o.id)),\n ambiguous,\n }\n}\n\n/** Applies manifest tags to every adopted object so the account becomes filterable. */\nexport async function tagAdopted(\n provider: Provider,\n specs: ResolvedSpec[],\n lock: Lock,\n opts: { onProgress?: (msg: string) => void } = {},\n): Promise<number> {\n const log = opts.onProgress ?? (() => {})\n const specByKey = new Map(specs.map((s) => [lockKey(s.styleId, s.assetId), s]))\n let count = 0\n for (const [key, entry] of Object.entries(lock.entries)) {\n const spec = specByKey.get(key)\n if (!spec || !entry.objectId) continue\n if (!provider.setTags) return count // capability absent\n try {\n await provider.setTags(entry.objectId, spec.tags)\n count++\n } catch (err) {\n log(` tag failed ${key}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n return count\n}\n\n/**\n * Backfills empty manifest prompts from the prompts recorded on adopted objects.\n *\n * For a project onboarded with `init`, this is how the manifest becomes real:\n * the prompts that actually produced the shipped art are recovered from the\n * account rather than reconstructed by guesswork. Only empty prompts are\n * touched, so hand-authored text is never overwritten.\n */\nexport async function writePromptsBack(\n manifestPath: string,\n lock: Lock,\n opts: {\n onProgress?: (msg: string) => void\n /** Restrict recovered prompts to lock entries from one provider. */\n provider?: string\n /** Restrict manifest writes and missing reports to these asset ids. */\n assetIds?: Iterable<string>\n } = {},\n): Promise<{ filled: number; stillEmpty: string[] }> {\n const log = opts.onProgress ?? (() => {})\n const selectedAssets = opts.assetIds ? new Set(opts.assetIds) : null\n const raw = JSON.parse(await readFile(manifestPath, \"utf8\")) as {\n assets: Record<string, { prompt?: string }>\n }\n\n // An asset can be adopted under several styles; prefer the longest recovered\n // prompt, which is the most complete description of what was generated.\n const best = new Map<string, string>()\n for (const entry of Object.values(lock.entries)) {\n if (opts.provider && entry.provider !== opts.provider) continue\n if (selectedAssets && !selectedAssets.has(entry.assetId)) continue\n if (!entry.objectId || !entry.prompt) continue\n const current = best.get(entry.assetId)\n if (!current || entry.prompt.length > current.length) best.set(entry.assetId, entry.prompt)\n }\n\n let filled = 0\n const stillEmpty: string[] = []\n for (const [id, asset] of Object.entries(raw.assets)) {\n if (selectedAssets && !selectedAssets.has(id)) continue\n if (asset.prompt && asset.prompt.trim()) continue\n const recovered = best.get(id)\n if (recovered) {\n asset.prompt = recovered\n filled++\n } else {\n stillEmpty.push(id)\n }\n }\n\n await writeFile(manifestPath, JSON.stringify(raw, null, 2) + \"\\n\")\n log(` filled ${filled} prompt(s) from adopted objects`)\n return { filled, stillEmpty }\n}\n\nexport function formatUnmatchedRemote(objects: RemoteAsset[], limit = 15): string {\n const lines = objects\n .slice(0, limit)\n .map((o) => ` ${o.id} ${o.createdAt.slice(0, 10)} ${(o.prompt || \"\").slice(0, 60)}`)\n if (objects.length > limit) lines.push(` … and ${objects.length - limit} more`)\n return lines.join(\"\\n\")\n}\n\nexport function relativeToCwd(p: string): string {\n return path.relative(process.cwd(), p) || p\n}\n","import { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport pathModule from \"node:path\"\nimport { z } from \"zod\"\n\nexport const HashCacheSchema = z.object({\n version: z.literal(1),\n /** objectId → sha256 of that object's image bytes. */\n hashes: z.record(z.string()),\n})\n\nexport type HashCache = z.infer<typeof HashCacheSchema>\nconst SHA256_HEX = /^[a-f0-9]{64}$/\n\nexport function isSha256Hash(value: string): boolean {\n return SHA256_HEX.test(value)\n}\n\n/** Strict parser for diagnostics; ordinary cache loading remains self-healing. */\nexport function parseCache(value: unknown): HashCache {\n return HashCacheSchema.parse(value)\n}\n\n/**\n * Remembers the hash of every remote object already downloaded.\n *\n * `adopt` and `salvage` work by hashing image bytes, which means downloading\n * every object on the account on every run — measured at 363 downloads and\n * ~4.5s for one project, and it grows with the account rather than with the\n * work. Generated objects are immutable, so a hash only ever needs computing\n * once.\n *\n * Purely derived state: deleting the file costs one slow run and nothing else.\n * It belongs in .gitignore.\n */\nexport async function loadCache(path: string): Promise<HashCache> {\n if (!existsSync(path)) return { version: 1, hashes: {} }\n try {\n const parsed = HashCacheSchema.safeParse(JSON.parse(await readFile(path, \"utf8\")))\n if (!parsed.success) return { version: 1, hashes: {} }\n // Never trust malformed derived data during adoption. Dropping one cache\n // entry costs one download; trusting it can hide a real provenance match.\n return {\n version: 1,\n hashes: Object.fromEntries(\n Object.entries(parsed.data.hashes).filter(([, hash]) => isSha256Hash(hash)),\n ),\n }\n } catch {\n // A corrupt cache is not worth failing a run over — rebuild it.\n return { version: 1, hashes: {} }\n }\n}\n\nexport async function saveCache(path: string, cache: HashCache): Promise<void> {\n const sorted: Record<string, string> = {}\n for (const key of Object.keys(cache.hashes).sort()) {\n const hash = cache.hashes[key]!\n if (!isSha256Hash(hash)) throw new Error(`Refusing to cache invalid SHA-256 for ${key}`)\n sorted[key] = hash\n }\n await mkdir(pathModule.dirname(pathModule.resolve(path)), { recursive: true })\n const tmp = `${path}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`\n try {\n await writeFile(tmp, JSON.stringify({ version: 1, hashes: sorted }, null, 2) + \"\\n\")\n await rename(tmp, path)\n } finally {\n await rm(tmp, { force: true })\n }\n}\n\n/** Drop entries for objects that no longer exist, so the file cannot grow forever. */\nexport function pruneCache(cache: HashCache, liveIds: Set<string>): number {\n let removed = 0\n for (const id of Object.keys(cache.hashes)) {\n if (!liveIds.has(id)) {\n delete cache.hashes[id]\n removed++\n }\n }\n return removed\n}\n\n/**\n * A lockfile named exactly `*.lock.json` gets the conventional\n * `*.cache.json` sibling. Anything else — a custom `--lock` name, which\n * projects in this monorepo already use for variant lockfiles — falls back\n * to appending `.cache.json` to the whole path instead of returning it\n * unchanged. Returning the input unchanged here used to mean the cache,\n * which is a completely different schema, got written straight over the\n * real lockfile on the very first `adopt`.\n */\nexport function cachePathFor(lockPath: string): string {\n if (lockPath.endsWith(\".lock.json\")) return lockPath.replace(/\\.lock\\.json$/, \".cache.json\")\n return `${lockPath}.cache.json`\n}\n","export interface SheetGroup {\n key: string\n assetId: string\n styleId: string\n prompt: string\n reviewObjectId: string\n frameUrls: string[]\n width: number\n height: number\n mode?: \"candidates\" | \"frame-set\"\n frameLabels?: string[]\n fps?: number\n revision?: {\n mode: \"image-to-image\" | \"inpaint\" | \"outpaint\"\n sourceAssetId: string\n sourceUrl: string\n width: number\n height: number\n }\n}\n\nconst escapeHtml = (s: string) =>\n s.replace(/[&<>\"']/g, (c) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" })[c]!)\n\n/**\n * A contact sheet for choosing among generated candidates.\n *\n * This is the only step that needs human judgement, so it is optimised for one\n * thing: deciding fast. Small candidates render at an exact integer zoom with\n * a transparency checkerboard and a true-size swatch. Large candidates are\n * fitted without changing their aspect ratio, so a wide browser cannot turn a\n * review into an oversized or stretched image wall. Keyboard-first, one row\n * per asset, and the page posts back and closes itself.\n */\nexport function renderSheet(groups: SheetGroup[]): string {\n // Prompts are author-controlled but arbitrary text, and they reach the page\n // both as JSON inside a <script> and via innerHTML. Escape for both: HTML\n // entities for the markup path, and `<\\/` for the script-tag path so a\n // prompt containing \"</script>\" cannot break out.\n const safe = groups.map((g) => ({\n ...g,\n styleId: escapeHtml(g.styleId),\n assetId: escapeHtml(g.assetId),\n prompt: escapeHtml(g.prompt),\n ...(g.revision\n ? {\n revision: {\n ...g.revision,\n sourceAssetId: escapeHtml(g.revision.sourceAssetId),\n },\n }\n : {}),\n }))\n const data = JSON.stringify(safe).replace(/<\\//g, \"<\\\\/\")\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>pixelkiln — pick candidates</title>\n<style>\n :root {\n --bg: #17150f; --panel: #201d17; --panel-deep: #100f0c;\n --line: rgba(243,234,214,.16); --line-strong: rgba(243,234,214,.3);\n --text: #f3ead6; --dim: #9b9384; --accent: #ff6b35;\n --accent-soft: #ff9c5f; --ok: #b9f27c; --warn: #ff9c5f;\n --content: 1440px; --preview: 560px;\n }\n * { box-sizing: border-box; }\n body { margin:0; background:var(--bg); color:var(--text);\n font:14px/1.5 ui-sans-serif,-apple-system,\"SF Pro Text\",Inter,system-ui,sans-serif; }\n header { position:sticky; top:0; z-index:10; background:var(--panel);\n border-bottom:1px solid var(--line-strong); }\n .bar { width:min(100%,var(--content)); margin:0 auto; padding:15px 22px;\n display:flex; align-items:center; gap:16px; flex-wrap:wrap; }\n h1 { font:700 14px/1 ui-monospace,SFMono-Regular,Menlo,monospace;\n margin:0; letter-spacing:-.02em; }\n h1::before { content:'◆'; color:var(--accent); margin-right:9px; font-size:11px; }\n .count { color:var(--dim); font-variant-numeric:tabular-nums; }\n button { font:inherit; font-weight:600; border-radius:0; padding:9px 16px;\n border:1px solid var(--line); background:transparent; color:var(--text); cursor:pointer; }\n button.primary { background:var(--accent); border-color:var(--accent); color:var(--bg); }\n button:disabled { opacity:.45; cursor:not-allowed; }\n main, footer { width:min(100%,var(--content)); margin-inline:auto; }\n main { border-inline:1px solid var(--line); }\n .group { border-bottom:1px solid var(--line); padding:22px; overflow:hidden; }\n .group.done { background:rgba(185,242,124,.035); }\n .ghead { display:flex; align-items:baseline; gap:12px; margin-bottom:16px; flex-wrap:wrap; }\n .style { font-size:10.5px; font-weight:650; text-transform:uppercase; letter-spacing:.03em;\n color:var(--accent-soft); border:1px solid var(--accent); border-radius:0; padding:2px 6px; }\n .aid { font-weight:650; font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }\n .prompt { flex:1; min-width:280px; color:var(--dim); font-size:12.5px; max-width:80ch; }\n .review { display:grid; grid-template-columns:minmax(180px,280px) minmax(0,1fr); gap:16px;\n align-items:start; }\n .review.no-context { display:block; }\n .context { border:1px solid var(--line); padding:8px; background:var(--panel-deep);\n min-width:0; }\n .context-label { display:flex; justify-content:space-between; gap:8px; margin-bottom:7px;\n color:var(--dim); font-size:10.5px; font-variant-numeric:tabular-nums; }\n .context img { display:block; width:100%; height:auto; max-height:420px; object-fit:contain;\n image-rendering:pixelated;\n background-image:linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%),\n linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%);\n background-size:12px 12px; background-position:0 0,6px 6px; }\n .frames { display:flex; flex-wrap:wrap; gap:10px; max-width:100%; overflow-x:auto; }\n .loop { display:flex; align-items:flex-start; gap:12px; margin-bottom:12px; }\n .loop img { image-rendering:pixelated; border:2px solid var(--accent); padding:7px;\n background:var(--panel-deep); max-width:min(var(--preview),calc(100vw - 62px)); height:auto; }\n .loop-copy { color:var(--dim); font-size:11px; max-width:32ch; }\n .cand { border:2px solid var(--line-strong); border-radius:0; padding:7px; background:var(--panel-deep);\n cursor:pointer; display:flex; flex:0 0 auto; flex-direction:column; align-items:center; gap:5px;\n position:relative; max-width:100%; }\n .cand:hover { border-color:var(--dim); }\n .cand.active { border-color:var(--dim); box-shadow:0 0 0 2px color-mix(in srgb, var(--dim) 20%, transparent); }\n .cand.sel { border-color:var(--ok); box-shadow:0 0 0 3px color-mix(in srgb, var(--ok) 22%, transparent); }\n .cand.set-frame { cursor:pointer; }\n .cand img { image-rendering:pixelated; display:block;\n background-image:\n linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%),\n linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%);\n background-size:12px 12px; background-position:0 0,6px 6px; border-radius:0; }\n .cand img.preview { max-width:min(var(--preview),calc(100vw - 62px)); height:auto; }\n .idx { font-size:10.5px; color:var(--dim); font-variant-numeric:tabular-nums; }\n .actual { position:absolute; right:-3px; bottom:-3px; image-rendering:pixelated;\n border:1px solid var(--line); border-radius:0; background:var(--panel); }\n .skip { align-self:center; color:var(--dim); font-size:12px; }\n footer { padding:26px 20px 60px; color:var(--dim); }\n kbd { border:1px solid var(--line); border-bottom-width:2px; border-radius:0;\n padding:1px 5px; font-size:11px; font-family:ui-monospace,Menlo,monospace; }\n #status { color:var(--warn); }\n @media (max-width:640px) {\n .bar, .group { padding-inline:14px; }\n .prompt { min-width:100%; }\n .cand img.preview { max-width:calc(100vw - 50px); }\n }\n @media (max-width:900px) {\n .review { grid-template-columns:1fr; }\n .context { max-width:280px; }\n }\n</style>\n</head>\n<body>\n<header>\n <div class=\"bar\">\n <h1>pixelkiln</h1>\n <span class=\"count\"><span id=\"picked\">0</span> of <span id=\"total\">0</span> chosen</span>\n <span id=\"status\"></span>\n <span style=\"flex:1\"></span>\n <button id=\"submit\" class=\"primary\" disabled>Apply selections</button>\n </div>\n</header>\n<main id=\"root\"></main>\n<footer>\n Click a candidate to choose it, or any ordered frame to accept its whole set;\n click again to undo. In the focused row,\n <kbd>←</kbd>/<kbd>→</kbd> browses every candidate and <kbd>Enter</kbd> chooses;\n <kbd>1</kbd>–<kbd>9</kbd> picks directly, <kbd>0</kbd> skips, and\n <kbd>↑</kbd>/<kbd>↓</kbd> changes rows. Unchosen rows stay in review — nothing is\n discarded by closing this page.\n</footer>\n<script>\nconst GROUPS = ${data};\nconst picks = new Map();\nconst root = document.getElementById('root');\ndocument.getElementById('total').textContent = GROUPS.length;\n\nGROUPS.forEach((g, gi) => {\n const el = document.createElement('section');\n el.className = 'group';\n el.tabIndex = 0;\n el.dataset.gi = String(gi);\n const largestSide = Math.max(g.width, g.height);\n const preferredScale = largestSide <= 48 ? 4 : largestSide <= 96 ? 3 : 2;\n const scale = Math.min(preferredScale, 560 / largestSide);\n const displayScale = scale >= 1 ? Math.floor(scale) : scale;\n const displayWidth = Math.max(1, Math.round(g.width * displayScale));\n const displayHeight = Math.max(1, Math.round(g.height * displayScale));\n const scaleLabel = displayScale >= 1 ? displayScale + '×' : 'fit';\n el.innerHTML =\n '<div class=\"ghead\"><span class=\"style\">' + g.styleId + '</span>' +\n '<span class=\"aid\">' + g.assetId + '</span>' +\n '<span class=\"prompt\">' + g.prompt + '</span></div>' +\n '<div class=\"review' + (g.revision ? '' : ' no-context') + '\">' +\n '<div class=\"frames\"></div></div>';\n const review = el.querySelector('.review');\n const frames = el.querySelector('.frames');\n if (g.revision) {\n const context = document.createElement('aside');\n context.className = 'context';\n const label = document.createElement('div');\n label.className = 'context-label';\n const identity = document.createElement('span');\n identity.textContent = g.revision.mode.toUpperCase() + ' · SOURCE ' + g.revision.sourceAssetId;\n const dimensions = document.createElement('span');\n dimensions.textContent = g.revision.width + '×' + g.revision.height;\n label.append(identity, dimensions);\n const source = document.createElement('img');\n source.src = g.revision.sourceUrl;\n source.alt = 'Revision source ' + g.revision.sourceAssetId;\n context.append(label, source);\n review.insertBefore(context, frames);\n }\n if (g.mode === 'frame-set') {\n const loop = document.createElement('div');\n loop.className = 'loop';\n const preview = document.createElement('img');\n preview.src = g.frameUrls[0];\n preview.width = displayWidth;\n preview.height = displayHeight;\n preview.alt = 'Animated frame-set preview';\n const copy = document.createElement('div');\n copy.className = 'loop-copy';\n copy.textContent = g.frameUrls.length + ' ordered frames · ' + (g.fps || 12) +\n ' fps. Accepting keeps every frame; one bad frame means leave the set unchosen.';\n loop.append(preview, copy);\n review.insertBefore(loop, frames);\n let loopIndex = 0;\n setInterval(() => {\n loopIndex = (loopIndex + 1) % g.frameUrls.length;\n preview.src = g.frameUrls[loopIndex];\n }, Math.max(16, Math.round(1000 / (g.fps || 12))));\n }\n g.frameUrls.forEach((url, i) => {\n const c = document.createElement('button');\n c.type = 'button';\n c.className = 'cand' + (g.mode === 'frame-set' ? ' set-frame' : '');\n c.tabIndex = -1;\n c.setAttribute('aria-label', g.mode === 'frame-set'\n ? 'Accept ordered frame set from frame ' + (i + 1)\n : 'Choose candidate ' + (i + 1) + ' of ' + g.frameUrls.length);\n\n const preview = document.createElement('img');\n preview.className = 'preview';\n preview.src = url;\n preview.width = displayWidth;\n preview.height = displayHeight;\n preview.loading = 'lazy';\n const index = document.createElement('span');\n index.className = 'idx';\n index.textContent = (g.frameLabels?.[i] || String(i + 1)) + ' · ' +\n g.width + '×' + g.height + ' · ' + scaleLabel;\n c.append(preview, index);\n if (displayScale > 1 && largestSide <= 96) {\n const actual = document.createElement('img');\n actual.className = 'actual';\n actual.src = url;\n actual.width = g.width;\n actual.height = g.height;\n actual.loading = 'lazy';\n actual.setAttribute('aria-label', 'Actual size');\n c.append(actual);\n }\n\n c.onclick = () => {\n activate(i, frames);\n choose(gi, i, c, frames, el);\n // Keep the row as the keyboard target. Otherwise a clicked <button>\n // receives focus and Enter would invoke both its native click and the\n // row shortcut, toggling the same choice twice.\n el.focus();\n };\n c.onmouseenter = () => activate(i, frames);\n frames.appendChild(c);\n });\n frames.dataset.active = '0';\n frames.querySelector('.cand')?.classList.add('active');\n root.appendChild(el);\n});\n\nfunction activate(i, frames) {\n const candidates = [...frames.querySelectorAll('.cand')];\n if (!candidates.length) return null;\n const next = ((i % candidates.length) + candidates.length) % candidates.length;\n candidates.forEach(n => n.classList.remove('active'));\n candidates[next].classList.add('active');\n frames.dataset.active = String(next);\n candidates[next].scrollIntoView({ block: 'nearest', inline: 'nearest' });\n return candidates[next];\n}\n\nfunction choose(gi, i, node, frames, groupEl) {\n if (GROUPS[gi].mode === 'frame-set') {\n const selected = picks.has(gi);\n frames.querySelectorAll('.cand').forEach(n => n.classList.toggle('sel', !selected));\n if (selected) { picks.delete(gi); groupEl.classList.remove('done'); }\n else { picks.set(gi, 0); groupEl.classList.add('done'); }\n refresh();\n return;\n }\n const current = picks.get(gi);\n frames.querySelectorAll('.cand').forEach(n => n.classList.remove('sel'));\n if (current === i) { picks.delete(gi); groupEl.classList.remove('done'); }\n else { picks.set(gi, i); node.classList.add('sel'); groupEl.classList.add('done'); }\n refresh();\n}\nfunction refresh() {\n document.getElementById('picked').textContent = picks.size;\n document.getElementById('submit').disabled = picks.size === 0;\n}\ndocument.addEventListener('keydown', e => {\n const g = document.activeElement?.closest?.('.group');\n if (!g) return;\n const gi = Number(g.dataset.gi);\n const frames = g.querySelector('.frames');\n const candidates = [...frames.querySelectorAll('.cand')];\n const active = Number(frames.dataset.active || 0);\n let advance = false;\n\n if (e.key === 'ArrowLeft') activate(active - 1, frames);\n else if (e.key === 'ArrowRight') activate(active + 1, frames);\n else if (e.key === 'Home') activate(0, frames);\n else if (e.key === 'End') activate(candidates.length - 1, frames);\n else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n const sibling = e.key === 'ArrowUp' ? g.previousElementSibling : g.nextElementSibling;\n if (sibling) { sibling.focus(); sibling.scrollIntoView({ block: 'center', behavior: 'smooth' }); }\n } else if (e.key === 'Enter' || e.key === ' ') {\n const node = candidates[active];\n if (!node) return;\n choose(gi, active, node, frames, g);\n advance = true;\n } else if (e.key === '0') {\n picks.delete(gi); g.classList.remove('done');\n frames.querySelectorAll('.cand').forEach(n => n.classList.remove('sel'));\n refresh();\n advance = true;\n } else if (/^[1-9]$/.test(e.key)) {\n const i = Number(e.key) - 1;\n const node = candidates[i];\n if (!node) return;\n activate(i, frames);\n choose(gi, i, node, frames, g);\n advance = true;\n } else {\n return;\n }\n if (advance) {\n const next = g.nextElementSibling;\n if (next) { next.focus(); next.scrollIntoView({ block: 'center', behavior: 'smooth' }); }\n }\n e.preventDefault();\n});\n\ndocument.getElementById('submit').onclick = async () => {\n const btn = document.getElementById('submit');\n btn.disabled = true;\n const status = document.getElementById('status');\n status.textContent = 'applying…';\n const selections = [...picks.entries()].map(([gi, index]) => ({ key: GROUPS[gi].key, index }));\n try {\n const res = await fetch('/apply', {\n method: 'POST', headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ selections }),\n });\n if (!res.ok) throw new Error(await res.text());\n status.textContent = 'done — you can close this tab';\n document.body.style.opacity = '.6';\n } catch (err) {\n status.textContent = 'failed: ' + err.message;\n btn.disabled = false;\n }\n};\n</script>\n</body>\n</html>`\n}\n","import { createServer } from \"node:http\"\nimport { spawn } from \"node:child_process\"\nimport { readFile } from \"node:fs/promises\"\n\n/**\n * The HTTP plumbing shared by every local review page (`pick`, `salvage`):\n * serve one static page at `/`, accept one POST of decisions, hand the parsed\n * body to the caller, and resolve once that caller's handler succeeds.\n *\n * This exists because `pick` and `salvage` each hand-rolled the identical\n * server — same GET/POST routing, same ephemeral-port dance, same `open`\n * spawn, same error handling — and a bug fixed in one silently stayed a bug\n * in the other (as happened here: `salvage`'s manifest-write bug had no\n * equivalent in `pick` only because `pick` never merges a whole manifest back\n * in). A third review page now gets this for free instead of a third copy to\n * keep in sync.\n *\n * Deliberately NOT a full framework: one page, one apply endpoint, one round\n * trip. Anything needing more should not reach for this.\n */\nexport interface ReviewServerOptions<TResult> {\n /** The full HTML document served at GET /. */\n html: string\n /** Parses the POSTed decisions and performs them. Only closes the server\n * on success — a thrown error leaves the page free to retry. */\n handleApply: (body: unknown) => Promise<TResult>\n /** Logged once the server is listening, given its localhost URL. */\n onReady: (url: string) => void\n port?: number\n /** Open the URL in the system browser once listening. Default true. */\n open?: boolean\n onProgress?: (msg: string) => void\n /** Exact local media routes exposed only for the lifetime of this review. */\n assets?: ReadonlyMap<string, { path: string; contentType: string }>\n}\n\nexport function serveReviewPage<TResult>(opts: ReviewServerOptions<TResult>): Promise<TResult> {\n const log = opts.onProgress ?? (() => {})\n\n return new Promise<TResult>((resolve, reject) => {\n const server = createServer(async (req, res) => {\n if (req.method === \"GET\" && req.url && opts.assets?.has(req.url)) {\n try {\n const asset = opts.assets.get(req.url)!\n const bytes = await readFile(asset.path)\n res.writeHead(200, {\n \"Content-Type\": asset.contentType,\n \"Cache-Control\": \"no-store\",\n \"X-Content-Type-Options\": \"nosniff\",\n })\n res.end(bytes)\n } catch {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" })\n res.end(\"review asset is unavailable\")\n }\n return\n }\n\n if (req.method === \"GET\" && (req.url === \"/\" || req.url?.startsWith(\"/?\"))) {\n res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" })\n res.end(opts.html)\n return\n }\n\n if (req.method === \"POST\" && req.url === \"/apply\") {\n const expectedOrigin = req.headers.host ? `http://${req.headers.host}` : null\n if (req.headers.origin && req.headers.origin !== expectedOrigin) {\n res.writeHead(403, { \"Content-Type\": \"text/plain\" })\n res.end(\"cross-origin review submissions are not allowed\")\n return\n }\n if (!req.headers[\"content-type\"]?.toLowerCase().startsWith(\"application/json\")) {\n res.writeHead(415, { \"Content-Type\": \"text/plain\" })\n res.end(\"application/json is required\")\n return\n }\n try {\n const chunks: Buffer[] = []\n let bytes = 0\n for await (const c of req) {\n const chunk = c as Buffer\n bytes += chunk.length\n if (bytes > 64 * 1024) {\n res.writeHead(413, { \"Content-Type\": \"text/plain\" })\n res.end(\"review submission is too large\")\n return\n }\n chunks.push(chunk)\n }\n const body: unknown = JSON.parse(Buffer.concat(chunks).toString(\"utf8\"))\n const result = await opts.handleApply(body)\n res.writeHead(200, { \"Content-Type\": \"application/json\" })\n res.end(JSON.stringify(result))\n server.close(() => resolve(result))\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n log(` apply failed: ${message}`)\n res.writeHead(500, { \"Content-Type\": \"text/plain\" })\n res.end(message)\n }\n return\n }\n\n res.writeHead(404)\n res.end()\n })\n\n server.on(\"error\", reject)\n server.listen(opts.port ?? 0, \"127.0.0.1\", () => {\n const address = server.address()\n const port = typeof address === \"object\" && address ? address.port : opts.port\n opts.onReady(`http://127.0.0.1:${port}/`)\n if (opts.open !== false && process.platform === \"darwin\") {\n spawn(\"open\", [`http://127.0.0.1:${port}/`], { stdio: \"ignore\", detached: true }).unref()\n }\n })\n })\n}\n","import { requireSelectCandidate, type Provider } from \"../provider.ts\"\nimport { saveLock, upsert } from \"../lock.ts\"\nimport { lockKey, type Lock, type ResolvedSpec } from \"../types.ts\"\nimport { renderSheet, type SheetGroup } from \"./sheet.ts\"\nimport { serveReviewPage } from \"./review-server.ts\"\n\nexport interface PickResult {\n selected: number\n skipped: number\n}\n\nexport interface ReviewReadyInfo {\n url: string\n keys: string[]\n}\n\n/**\n * Serves the contact sheet on localhost, waits for the selections to be\n * applied, then shuts down.\n *\n * Selections are committed through the provider (`select-frames` promotes the chosen\n * candidate to its own object and drops the rest) and written to the lockfile\n * before the browser gets its response, so a closed tab never loses a choice.\n */\nexport async function runPicker(\n provider: Provider,\n lock: Lock,\n lockPath: string,\n opts: {\n port?: number\n open?: boolean\n onProgress?: (msg: string) => void\n /** Optional lock-key selection for a filtered or mixed-provider run. */\n keys?: Iterable<string>\n /** Resolved intent supplies immutable revision context for comparison. */\n specs?: ResolvedSpec[]\n /** Receives the live URL as soon as the server listens. */\n onReady?: (info: ReviewReadyInfo) => void\n } = {},\n): Promise<PickResult> {\n const log = opts.onProgress ?? (() => {})\n const selectedKeys = opts.keys ? new Set(opts.keys) : null\n const specByKey = new Map(\n (opts.specs ?? []).map((spec) => [lockKey(spec.styleId, spec.assetId), spec]),\n )\n const reviewAssets = new Map<string, { path: string; contentType: string }>()\n\n const groups: SheetGroup[] = []\n for (const [key, entry] of Object.entries(lock.entries)) {\n if (entry.provider !== provider.id || (selectedKeys && !selectedKeys.has(key))) continue\n if (entry.status !== \"review\" || !entry.reviewObjectId) continue\n try {\n const spec = specByKey.get(key)\n const state = await provider.poll(entry.reviewObjectId, entry.generator, { spec })\n if (\n (state.status !== \"review\" && state.status !== \"review-set\") ||\n (state.status === \"review\" ? !state.candidateUrls.length : !state.frameUrls.length)\n ) continue\n const frameUrls = state.status === \"review\" ? state.candidateUrls : state.frameUrls\n const sourceRoute = spec?.revision\n ? `/revision-source/${encodeURIComponent(String(groups.length))}`\n : null\n if (sourceRoute && spec?.revision) {\n reviewAssets.set(sourceRoute, {\n path: spec.revision.sourceFile,\n contentType: spec.revision.sourceFormat === \"jpeg\" ? \"image/jpeg\" : \"image/png\",\n })\n }\n groups.push({\n key,\n assetId: entry.assetId,\n styleId: entry.styleId,\n prompt: entry.prompt,\n reviewObjectId: entry.reviewObjectId,\n frameUrls,\n width: entry.width,\n height: entry.height,\n ...(state.status === \"review-set\"\n ? {\n mode: \"frame-set\" as const,\n frameLabels: state.sources.map((source, index) => source.role ?? `frame-${index}`),\n fps: state.fps,\n }\n : { mode: \"candidates\" as const }),\n ...(sourceRoute && spec?.revision && spec.revision.sourceWidth && spec.revision.sourceHeight\n ? {\n revision: {\n mode: spec.revision.mode,\n sourceAssetId: spec.revision.sourceAssetId,\n sourceUrl: sourceRoute,\n width: spec.revision.sourceWidth,\n height: spec.revision.sourceHeight,\n },\n }\n : {}),\n })\n } catch (err) {\n log(` could not load candidates for ${key}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n\n if (groups.length === 0) return { selected: 0, skipped: 0 }\n\n const html = renderSheet(groups)\n const byKey = new Map(groups.map((g) => [g.key, g]))\n\n return serveReviewPage<PickResult>({\n html,\n port: opts.port,\n open: opts.open,\n onProgress: log,\n assets: reviewAssets,\n onReady: (url) => {\n const info = { url, keys: groups.map((group) => group.key) }\n if (opts.onReady) {\n opts.onReady(info)\n } else {\n log(`\\n ${groups.length} asset(s) awaiting selection: ${url}`)\n log(` (leave this running; it exits once you apply)\\n`)\n }\n },\n handleApply: async (body) => {\n const { selections } = body as { selections: { key: string; index: number }[] }\n\n let selected = 0\n for (const { key, index } of selections) {\n const group = byKey.get(key)\n const entry = lock.entries[key]\n if (!group || !entry?.reviewObjectId) continue\n if (!Number.isInteger(index) || index < 0 || index >= group.frameUrls.length) continue\n\n if (group.mode === \"frame-set\") {\n const spec = specByKey.get(key)\n const state = await provider.poll(entry.reviewObjectId, entry.generator, { spec })\n if (state.status !== \"review-set\") {\n throw new Error(`Frame set ${key} is no longer ready for review`)\n }\n upsert(lock, key, {\n status: \"selected\",\n objectId: state.objectId,\n candidateIndex: null,\n sourceUrl: state.sources[0]?.url ?? null,\n sourceUrls: state.sources,\n provider: provider.id,\n providerMetadata: state.metadata\n ? {\n ...entry.providerMetadata,\n [provider.id]: {\n ...entry.providerMetadata[provider.id],\n ...state.metadata,\n },\n }\n : entry.providerMetadata,\n })\n selected++\n log(` accepted ${key} → ${state.sources.length} ordered frames`)\n continue\n }\n\n // Promote the chosen candidate; the review parent is removed upstream\n // once nothing is left in it.\n const { objectId, sourceUrl, metadata } = await requireSelectCandidate(provider)(\n entry.reviewObjectId,\n index,\n `asset:${entry.assetId}`,\n entry.generator,\n )\n\n upsert(lock, key, {\n status: \"selected\",\n objectId,\n candidateIndex: index,\n sourceUrl: sourceUrl ?? group.frameUrls[index] ?? null,\n sourceUrls: [],\n provider: provider.id,\n providerMetadata: metadata\n ? {\n ...entry.providerMetadata,\n [provider.id]: {\n ...entry.providerMetadata[provider.id],\n ...metadata,\n },\n }\n : entry.providerMetadata,\n })\n selected++\n log(` picked ${key} → candidate ${index + 1}`)\n }\n\n await saveLock(lockPath, lock)\n return { selected, skipped: groups.length - selected }\n },\n })\n}\n","import { readdir, readFile, writeFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport type { Generator, Manifest } from \"../types.ts\"\n\n/** Minimal PNG header read — avoids pulling in an image library just for dimensions. */\nexport function pngSize(buf: Buffer): { width: number; height: number } | null {\n if (buf.length < 24) return null\n const isPng = buf.readUInt32BE(0) === 0x89504e47 && buf.readUInt32BE(4) === 0x0d0a1a0a\n if (!isPng) return null\n if (buf.toString(\"ascii\", 12, 16) !== \"IHDR\") return null\n return { width: buf.readUInt32BE(16), height: buf.readUInt32BE(20) }\n}\n\n/** Path segment → a stable, readable asset id. */\nexport function slugify(value: string): string {\n return value\n .replace(/\\.png$/i, \"\")\n .replace(/[^a-zA-Z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .toLowerCase()\n}\n\nexport interface ScannedAsset {\n id: string\n category: string\n file: string\n width: number\n height: number\n}\n\nasync function walk(dir: string, exclude: string[]): Promise<string[]> {\n const out: string[] = []\n for (const entry of await readdir(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name)\n if (exclude.some((x) => full.includes(x))) continue\n if (entry.isDirectory()) out.push(...(await walk(full, exclude)))\n else if (entry.name.toLowerCase().endsWith(\".png\")) out.push(full)\n }\n return out\n}\n\n/**\n * Scans an existing asset tree and produces manifest entries for it.\n *\n * Prompts are left empty on purpose. For a project whose art already exists,\n * the accurate prompts are the ones actually used upstream — `adopt\n * --write-prompts` recovers those from the matched objects rather than having\n * anyone invent plausible-looking replacements.\n */\nexport async function scanAssets(\n root: string,\n opts: { exclude?: string[] } = {},\n): Promise<{ assets: ScannedAsset[]; skipped: string[] }> {\n const exclude = opts.exclude ?? []\n const files = await walk(root, exclude)\n const assets: ScannedAsset[] = []\n const skipped: string[] = []\n const seen = new Map<string, number>()\n\n for (const file of files.sort()) {\n const size = pngSize(await readFile(file))\n if (!size) {\n skipped.push(`${file} (not a readable PNG)`)\n continue\n }\n const rel = path.relative(root, file)\n const category = path.dirname(rel) === \".\" ? \"\" : path.dirname(rel)\n let id = slugify(path.basename(rel))\n\n // Basenames repeat across category folders; disambiguate rather than collide.\n if (seen.has(id)) {\n const n = seen.get(id)! + 1\n seen.set(id, n)\n id = `${slugify(category.replace(/[/\\\\]/g, \"_\"))}_${id}`.replace(/^_+/, \"\")\n } else {\n seen.set(id, 1)\n }\n\n assets.push({ id, category, file: rel, width: size.width, height: size.height })\n }\n\n return { assets, skipped }\n}\n\nexport function buildManifest(\n name: string,\n styleId: string,\n generator: Generator,\n outDir: string,\n scanned: ScannedAsset[],\n): Manifest {\n const squares = scanned.filter((a) => a.width === a.height)\n const commonSize = squares.length ? mode(squares.map((a) => a.width)) : 64\n\n const assets: Manifest[\"assets\"] = {}\n for (const asset of scanned) {\n assets[asset.id] = {\n prompt: \"\",\n promptByStyle: {},\n category: asset.category || undefined,\n file: asset.file,\n tags: [],\n styles: [],\n providerInputs: {},\n ...(generator === \"map\"\n ? { width: asset.width, height: asset.height }\n : asset.width === asset.height && asset.width !== commonSize\n ? { size: asset.width }\n : {}),\n }\n }\n\n return {\n name,\n provider: \"pixellab\",\n styles: {\n [styleId]: {\n generator,\n size: commonSize,\n // Matches the schema default: a scaffolded style is for sprites, and\n // a sprite wants its background stripped.\n noBackground: true,\n promptPrefix: \"\",\n promptSuffix: \"\",\n styleImages: [],\n palette: [],\n outDir,\n tags: [name],\n providerOptions: {},\n },\n },\n assets,\n }\n}\n\nfunction mode(values: number[]): number {\n const counts = new Map<number, number>()\n for (const v of values) counts.set(v, (counts.get(v) ?? 0) + 1)\n return [...counts.entries()].sort((a, b) => b[1] - a[1])[0]?.[0] ?? 64\n}\n\nexport async function writeManifestFile(target: string, manifest: Manifest): Promise<void> {\n if (existsSync(target)) {\n throw new Error(`${target} already exists — refusing to overwrite an existing manifest.`)\n }\n await writeFile(target, JSON.stringify(manifest, null, 2) + \"\\n\")\n}\n","import { readFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { requireList, type Provider, type RemoteAsset } from \"../provider.ts\"\nimport { loadManifest } from \"../manifest.ts\"\nimport { parseLock, type Lock, type Manifest } from \"../types.ts\"\n\n/**\n * Objects on the account that no known lockfile claims.\n *\n * The point of this is recovery, not cleanup. An account accumulates work that\n * was generated, paid for, and never landed in a repo — alternate takes,\n * abandoned experiments, whole categories that were explored and forgotten.\n * Measured on one account: 190 of 361 objects were unclaimed, and a visual\n * sample showed usable character portraits, tree variants, terrain tiles, and\n * UI icons rather than rejects.\n *\n * Correctness here depends entirely on being given EVERY lockfile. One account\n * is shared across projects, so an incomplete claim set makes another project's\n * shipped art look like an orphan.\n */\nexport interface LoadClaimsOptions {\n /** Include only entries owned by this provider. */\n provider?: string\n /** Prefix ids with their provider so unrelated accounts cannot collide. */\n qualify?: boolean\n}\n\nexport function providerClaimId(provider: string, objectId: string): string {\n // Encode both halves so a provider/id pair such as (\"a:b\", \"c\") cannot\n // collide with (\"a\", \"b:c\"). Built-in ids stay human-readable.\n return `${encodeURIComponent(provider)}:${encodeURIComponent(objectId)}`\n}\n\nexport async function loadClaims(\n lockPaths: string[],\n opts: LoadClaimsOptions = {},\n): Promise<Set<string>> {\n const claimed = new Set<string>()\n for (const p of lockPaths) {\n if (!existsSync(p)) throw new Error(`Claim lockfile not found: ${p}`)\n let parsed: Lock\n try {\n parsed = parseLock(JSON.parse(await readFile(p, \"utf8\")))\n } catch {\n throw new Error(`Claim lockfile is malformed: ${p}`)\n }\n for (const entry of Object.values(parsed.entries)) {\n if (opts.provider && entry.provider !== opts.provider) continue\n const add = (id: string | null) => {\n if (id) claimed.add(opts.qualify ? providerClaimId(entry.provider, id) : id)\n }\n add(entry.objectId)\n add(entry.reviewObjectId)\n add(entry.jobId)\n }\n }\n return claimed\n}\n\nexport interface Orphan {\n id: string\n prompt: string\n width: number\n height: number\n createdAt: string\n previewUrl: string\n tags: string[]\n}\n\nexport async function findOrphans(\n provider: Provider,\n claimed: Set<string>,\n opts: { onProgress?: (msg: string) => void } = {},\n): Promise<{ orphans: Orphan[]; total: number }> {\n const log = opts.onProgress ?? (() => {})\n const all: RemoteAsset[] = []\n for await (const obj of requireList(provider)()) all.push(obj)\n log(` scanned ${all.length} object(s) on the account`)\n\n const orphans = all\n .filter((o) =>\n !claimed.has(o.id) &&\n !claimed.has(providerClaimId(provider.id, o.id)) &&\n o.status === \"completed\" &&\n o.previewUrl,\n )\n .map((o) => ({\n id: o.id,\n prompt: o.prompt || \"(no prompt recorded)\",\n width: o.width,\n height: o.height,\n createdAt: o.createdAt,\n previewUrl: o.previewUrl!,\n tags: o.tags ?? [],\n }))\n // Newest first: recent work is likeliest to be worth recovering.\n .sort((a, b) => b.createdAt.localeCompare(a.createdAt))\n\n return { orphans, total: all.length }\n}\n\n/**\n * Fragments shorter than this match too much by accident (an empty\n * `promptPrefix`/`promptSuffix`, or a short one like \"clean\", would otherwise\n * \"match\" nearly every prompt via `.includes`).\n */\nconst MIN_STYLE_FRAGMENT_LENGTH = 12\n\n/**\n * Whether a style's `promptPrefix`/`promptSuffix` — boilerplate baked into\n * every generation of that style — appears in a prompt. Unlike\n * `matchOrphanStyle`, this never assumes a match just because a manifest\n * only has one style: it is the \"is this genuinely recognisable\" check, used\n * both by `matchOrphanStyle` and to test a prompt against a project that\n * isn't the current one.\n */\nfunction matchStyleByPattern(prompt: string, manifest: Manifest): string | null {\n const p = prompt.toLowerCase()\n for (const styleId of Object.keys(manifest.styles)) {\n const style = manifest.styles[styleId]!\n for (const raw of [style.promptPrefix, style.promptSuffix]) {\n const frag = raw?.trim().toLowerCase()\n if (frag && frag.length >= MIN_STYLE_FRAGMENT_LENGTH && p.includes(frag)) return styleId\n }\n }\n return null\n}\n\n/**\n * Which manifest style, if any, an orphan's prompt was generated from.\n *\n * A manifest with only one style skips the pattern check entirely — there is\n * nothing to disambiguate, and a style with an empty prefix/suffix (common\n * for single-style projects that don't template their prompts, like a\n * `map`-generator asset pack) would otherwise match nothing at all. This is\n * a routing decision (\"where would salvage import this\"), not a claim that\n * the content is genuinely this project's — see `groupOrphansByStyle`'s\n * `siblings` param for that distinction, which single-style manifests need\n * and multi-style ones get from the plain pattern check already.\n */\nexport function matchOrphanStyle(prompt: string, manifest: Manifest): string | null {\n const styleIds = Object.keys(manifest.styles)\n if (styleIds.length <= 1) return styleIds[0] ?? null\n return matchStyleByPattern(prompt, manifest)\n}\n\n/** A sibling project's manifest, consulted only to recognise its own style\n * patterns — never as an import target. */\nexport interface SiblingManifest {\n /** How to refer to this sibling in output — a project directory name, typically. */\n label: string\n manifest: Manifest\n}\n\n/**\n * Loads every sibling project's manifest for `groupOrphansByStyle`'s\n * sibling-exclusion signal, from the union of a workspace catalog's\n * registered manifests and the conventional sibling beside each `--claims`\n * lockfile (same directory, by the convention `--lock` defaults from\n * `--manifest`). The two sources are meant to combine, not choose between\n * (docs/RECOVERY.md: \"`--claims` still works and unions with a workspace's\n * claim set\") — a `--claims` path passed alongside `--workspace` must still\n * contribute its own style signal. Best-effort: a missing or malformed\n * sibling just means no extra signal for that orphan, not an error.\n */\nexport async function loadSiblingManifests(\n ownManifestPath: string,\n workspaceManifestPaths: string[],\n claimPaths: string[],\n): Promise<SiblingManifest[]> {\n const own = path.resolve(ownManifestPath)\n const siblingManifestPaths = [\n ...new Set([\n ...workspaceManifestPaths,\n ...claimPaths.map((c) => path.join(path.dirname(path.resolve(c)), \"pixelkiln.manifest.json\")),\n ]),\n ]\n const siblings: SiblingManifest[] = []\n for (const siblingManifestPath of siblingManifestPaths) {\n if (path.resolve(siblingManifestPath) === own) continue\n if (!existsSync(siblingManifestPath)) continue\n try {\n const { manifest } = await loadManifest(siblingManifestPath)\n siblings.push({ label: path.basename(path.dirname(siblingManifestPath)), manifest })\n } catch {\n // Not this run's problem to solve — the orphan just gets no extra signal.\n }\n }\n return siblings\n}\n\nexport interface OrphanGroups {\n /** styleId → its matched orphans, in manifest style order. */\n matched: Map<string, Orphan[]>\n /** Orphans that matched no style anywhere known — this manifest or any sibling. */\n unmatched: Orphan[]\n /** \"<sibling label>: <styleId>\" → orphans that confidently matched a\n * SIBLING's own pattern instead of this manifest's — excluded from\n * `matched` even where this manifest would otherwise have swallowed them\n * by default (a single-style manifest with nothing of its own to check\n * against). Empty unless `siblings` was passed to `groupOrphansByStyle`. */\n elsewhere: Map<string, Orphan[]>\n}\n\n/**\n * Splits orphans by the style that most likely produced them.\n *\n * `salvage` used to hand a single `--style` to a whole session regardless of\n * how many the orphan pool actually spanned, so importing anything wrong\n * silently mislabeled it under the first style in the manifest. Grouping\n * first lets the caller run one correctly-scoped session per style instead.\n *\n * A single-style manifest has no pattern of its own to filter by, so by\n * default everything routes to that one style — correct for a genuinely\n * single-project account, wrong for a shared one where the orphan pool is\n * mostly a sibling's art. Passing that sibling's manifest via `siblings` (its\n * lockfile sits beside it, by the same convention `--lock` defaults from\n * `--manifest`) lets a confident match against ITS pattern win instead,\n * pulling those orphans out of `matched` and into `elsewhere` even though\n * this manifest would otherwise have claimed them.\n */\nexport function groupOrphansByStyle(\n orphans: Orphan[],\n manifest: Manifest,\n siblings: SiblingManifest[] = [],\n): OrphanGroups {\n const matched = new Map<string, Orphan[]>()\n const elsewhere = new Map<string, Orphan[]>()\n const unmatched: Orphan[] = []\n const ownStyleIds = Object.keys(manifest.styles)\n for (const styleId of ownStyleIds) matched.set(styleId, [])\n\n for (const o of orphans) {\n const own = matchStyleByPattern(o.prompt, manifest)\n if (own) {\n matched.get(own)!.push(o)\n continue\n }\n\n const sibling = siblings.find((s) => matchStyleByPattern(o.prompt, s.manifest))\n if (sibling) {\n const key = `${sibling.label}: ${matchStyleByPattern(o.prompt, sibling.manifest)}`\n const list = elsewhere.get(key) ?? []\n list.push(o)\n elsewhere.set(key, list)\n continue\n }\n\n // Nothing recognised it anywhere. A single-style manifest still has no\n // better place to put it than its one style — the same pragmatic default\n // matchOrphanStyle uses — but a multi-style one genuinely doesn't know.\n if (ownStyleIds.length <= 1 && ownStyleIds[0]) matched.get(ownStyleIds[0])!.push(o)\n else unmatched.push(o)\n }\n for (const [styleId, list] of [...matched]) if (!list.length) matched.delete(styleId)\n return { matched, unmatched, elsewhere }\n}\n\n/**\n * A prompt makes a better id than a UUID. These are a starting point meant to\n * be renamed, so the goal is \"recognisable at a glance\", not perfection.\n */\nconst STYLE_WORDS = new Set([\n \"a\", \"an\", \"the\", \"one\", \"two\", \"three\", \"single\", \"centered\", \"center\", \"with\", \"and\",\n \"of\", \"on\", \"in\", \"for\", \"its\", \"has\", \"pixel\", \"art\", \"style\", \"game\", \"icon\",\n \"transparent\", \"background\", \"no\", \"premium\", \"indie\", \"achievement\", \"sprite\",\n \"isometric\", \"topdown\", \"top\", \"down\", \"view\", \"high\", \"low\", \"detailed\", \"simple\",\n \"clean\", \"bold\", \"dark\", \"outline\", \"silhouette\", \"colour\", \"color\", \"palette\",\n])\n\nexport function idFromPrompt(prompt: string, taken: Set<string>): string {\n // Prompts commonly read \"<style boilerplate>: <the actual subject>\". When a\n // colon is present the subject is after it, and using the whole string would\n // name every asset after the shared prefix.\n const colon = prompt.indexOf(\":\")\n const subject = colon >= 0 && colon < prompt.length - 12 ? prompt.slice(colon + 1) : prompt\n\n const words = subject\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length > 2 && !STYLE_WORDS.has(w))\n .slice(0, 4)\n\n let base = words.join(\"_\") || \"salvaged\"\n let id = base\n let n = 2\n while (taken.has(id)) id = `${base}_${n++}`\n taken.add(id)\n return id\n}\n\n/**\n * Placeholder spec hash written by a salvage import. The real hash cannot be\n * computed until the manifest has been rewritten with the new asset, so the CLI\n * re-baselines these immediately afterwards. Exported so the writer and the\n * re-baseliner reference one constant rather than two copies of a string.\n */\nexport const SALVAGED_SPEC_HASH = \"salvaged\"\n\nexport type SalvageAction = \"import\" | \"keep\" | \"discard\"\n\nexport interface SalvageDecision {\n id: string\n action: SalvageAction\n}\n\n/**\n * Tags are the durable record of a decision. They are free and synchronous, and\n * unlike a local file they survive on the account itself — so a later salvage\n * run from a different machine sees what was already triaged.\n *\n * `discard` deliberately only tags. Deleting is a separate, explicit command.\n */\nexport async function applyTags(\n provider: Provider,\n decisions: SalvageDecision[],\n existing: Map<string, string[]>,\n opts: { onProgress?: (msg: string) => void } = {},\n): Promise<{ tagged: number; failed: number }> {\n const log = opts.onProgress ?? (() => {})\n let tagged = 0\n let failed = 0\n\n for (const { id, action } of decisions) {\n const current = (existing.get(id) ?? []).filter(\n (t) => t !== \"pixelkiln:keep\" && t !== \"pixelkiln:discard\" && t !== \"pixelkiln:imported\",\n )\n const decisionTag = `pixelkiln:${action === \"import\" ? \"imported\" : action}`\n // PixelLab caps tags at 20. Preserve the decision tag even when the object\n // already has 20 unrelated tags; it is the durable record of this action.\n const next = [...current.slice(0, 19), decisionTag]\n if (!provider.setTags) return { tagged, failed }\n try {\n await provider.setTags(id, next)\n tagged++\n } catch (err) {\n failed++\n log(` tag failed ${id}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n return { tagged, failed }\n}\n","import { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { z } from \"zod\"\n\n/**\n * One sibling project registered in a workspace catalog. Only paths and\n * identity live here — never a credential. Each project keeps loading its own\n * key from its own `.env`, the same as it does standalone.\n */\nexport const WorkspaceProjectSchema = z\n .object({\n id: z.string().min(1),\n /** Manifest path, relative to the catalog file's own directory. */\n manifest: z.string().min(1),\n /** Lockfile path, relative to the catalog file's own directory. */\n lock: z.string().min(1),\n provider: z.string().min(1).default(\"pixellab\"),\n /** Free-form label for a shared account, e.g. distinguishing sandboxes. */\n account: z.string().optional(),\n })\n .strict()\n\nexport const WorkspaceSchema = z\n .object({\n version: z.literal(1),\n projects: z.array(WorkspaceProjectSchema).default([]),\n })\n .strict()\n\nexport type WorkspaceProject = z.infer<typeof WorkspaceProjectSchema>\nexport type Workspace = z.infer<typeof WorkspaceSchema>\n\n/**\n * Parses a workspace catalog, rejecting anything that is not v1.\n *\n * Mirrors `parseLock`'s stance: no migration path, fail loudly rather than\n * guess at a hand-edited or corrupted file's intent.\n */\nexport function parseWorkspace(raw: unknown): Workspace {\n const parsed = WorkspaceSchema.safeParse(raw)\n if (parsed.success) return parsed.data\n throw new Error(\n `Workspace catalog is not valid v1:\\n${parsed.error.issues\n .slice(0, 5)\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\")}`,\n )\n}\n\nexport async function loadWorkspace(workspacePath: string): Promise<Workspace> {\n if (!existsSync(workspacePath)) return { version: 1, projects: [] }\n let raw: unknown\n try {\n raw = JSON.parse(await readFile(workspacePath, \"utf8\"))\n } catch (err) {\n throw new Error(\n `Workspace catalog at ${workspacePath} is malformed:\\n` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n return parseWorkspace(raw)\n}\n\n/** Atomic write — a crash mid-save must not leave a truncated catalog. */\nexport async function saveWorkspace(workspacePath: string, ws: Workspace): Promise<void> {\n const sorted: Workspace = {\n version: 1,\n projects: [...ws.projects].sort((a, b) => a.id.localeCompare(b.id)),\n }\n await mkdir(path.dirname(path.resolve(workspacePath)), { recursive: true })\n const tmp = `${workspacePath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`\n try {\n await writeFile(tmp, JSON.stringify(sorted, null, 2) + \"\\n\")\n await rename(tmp, workspacePath)\n } finally {\n await rm(tmp, { force: true })\n }\n}\n\n/** Stored path convention: relative to the catalog's directory, forward-slash. */\nexport function toPortablePath(dir: string, absolute: string): string {\n return path.relative(dir, absolute).split(path.sep).join(\"/\")\n}\n\n/** Resolve a registered project's stored paths against the catalog's directory. */\nexport function resolveProject(\n dir: string,\n project: WorkspaceProject,\n): { manifestPath: string; lockPath: string } {\n return {\n manifestPath: path.resolve(dir, project.manifest.split(\"/\").join(path.sep)),\n lockPath: path.resolve(dir, project.lock.split(\"/\").join(path.sep)),\n }\n}\n\nexport interface WorkspaceDiagnostic {\n id:\n | \"duplicate-id\"\n | \"duplicate-lock\"\n | \"duplicate-manifest\"\n | \"missing-manifest\"\n | \"missing-lock\"\n | \"absolute-path\"\n | \"mixed-provider\"\n level: \"error\" | \"warning\"\n message: string\n}\n\n/**\n * Checks the catalog without touching the network or any registered\n * project's files. Duplicate ids and duplicate lock paths are errors — either\n * would corrupt the union claim set. A duplicate manifest is only a warning,\n * because a manifest paired with a variant `--lock` is an already-supported\n * pattern (see `cachePathFor`). Missing files are errors: a claim set derived\n * from a workspace that silently skipped a project is the exact hazard this\n * catalog exists to prevent.\n */\nexport function validateWorkspace(ws: Workspace, dir: string): WorkspaceDiagnostic[] {\n const diagnostics: WorkspaceDiagnostic[] = []\n\n const idCounts = new Map<string, number>()\n const lockOwners = new Map<string, string[]>()\n const manifestOwners = new Map<string, string[]>()\n\n for (const project of ws.projects) {\n idCounts.set(project.id, (idCounts.get(project.id) ?? 0) + 1)\n\n const { manifestPath, lockPath } = resolveProject(dir, project)\n lockOwners.set(lockPath, [...(lockOwners.get(lockPath) ?? []), project.id])\n manifestOwners.set(manifestPath, [...(manifestOwners.get(manifestPath) ?? []), project.id])\n\n if (path.isAbsolute(project.manifest) || path.isAbsolute(project.lock)) {\n diagnostics.push({\n id: \"absolute-path\",\n level: \"warning\",\n message:\n `project \"${project.id}\" stores an absolute path — the catalog will not resolve ` +\n `correctly if this tree is cloned or moved elsewhere`,\n })\n }\n if (!existsSync(manifestPath)) {\n diagnostics.push({\n id: \"missing-manifest\",\n level: \"error\",\n message: `project \"${project.id}\" manifest not found: ${manifestPath}`,\n })\n }\n if (!existsSync(lockPath)) {\n diagnostics.push({\n id: \"missing-lock\",\n level: \"error\",\n message: `project \"${project.id}\" lockfile not found: ${lockPath}`,\n })\n }\n }\n\n for (const [id, count] of idCounts) {\n if (count > 1) {\n diagnostics.push({\n id: \"duplicate-id\",\n level: \"error\",\n message: `project id \"${id}\" is registered ${count} times`,\n })\n }\n }\n for (const [lockPath, ids] of lockOwners) {\n if (ids.length > 1) {\n diagnostics.push({\n id: \"duplicate-lock\",\n level: \"error\",\n message: `${ids.join(\", \")} all register the same lockfile: ${lockPath}`,\n })\n }\n }\n for (const [manifestPath, ids] of manifestOwners) {\n if (ids.length > 1) {\n diagnostics.push({\n id: \"duplicate-manifest\",\n level: \"warning\",\n message:\n `${ids.join(\", \")} share manifest ${manifestPath} — expected only when they are ` +\n `variant lockfiles beside one manifest`,\n })\n }\n }\n\n const providers = new Set(ws.projects.map((p) => p.provider))\n if (providers.size > 1) {\n diagnostics.push({\n id: \"mixed-provider\",\n level: \"warning\",\n message:\n `registered projects use different providers: ${[...providers].sort().join(\", \")} — ` +\n `spend totals are kept separate per unit, but confirm this is intentional`,\n })\n }\n\n return diagnostics\n}\n","import { loadLock, spendByUnit } from \"../lock.ts\"\nimport { loadManifest, resolveSpecs } from \"../manifest.ts\"\nimport { normalizeLockOutputPaths } from \"../outputs.ts\"\nimport type { CostUnit } from \"../provider.ts\"\nimport {\n resolveProject,\n validateWorkspace,\n type Workspace,\n type WorkspaceDiagnostic,\n} from \"../workspace.ts\"\nimport { loadClaims } from \"./salvage.ts\"\nimport { buildPlan, summarize, type PlanState } from \"./plan.ts\"\n\nexport interface WorkspaceClaims {\n /** Provider-qualified remote ids (`provider:id`) across every lock. */\n claimed: Set<string>\n /** Claim count contributed by each registered project. */\n byProject: Record<string, number>\n lockPaths: string[]\n}\n\n/**\n * The complete account-wide claim set, derived from every registered lock.\n *\n * Delegates the union rule itself to `loadClaims` rather than reimplementing\n * it, so the workspace and single-project `--claims` paths cannot drift. Each\n * lock is loaded one at a time — rather than handing `loadClaims` the whole\n * path list at once — purely so a failure can be attributed to the project\n * that owns it; the safety property (any unreadable registered lock aborts\n * before returning a claim set) is identical either way.\n */\nexport async function workspaceClaims(ws: Workspace, dir: string): Promise<WorkspaceClaims> {\n const lockPaths: string[] = []\n const byProject: Record<string, number> = {}\n const claimed = new Set<string>()\n\n for (const project of ws.projects) {\n const { lockPath } = resolveProject(dir, project)\n lockPaths.push(lockPath)\n let projectClaims: Set<string>\n try {\n projectClaims = await loadClaims([lockPath], { qualify: true })\n } catch (err) {\n throw new Error(\n `Project \"${project.id}\" lockfile is unreadable: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n byProject[project.id] = projectClaims.size\n for (const id of projectClaims) claimed.add(id)\n }\n\n return { claimed, byProject, lockPaths }\n}\n\nfunction emptyStateCounts(): Record<PlanState, number> {\n return {\n ok: 0, missing: 0, untracked: 0, stale: 0, orphaned: 0, \"in-flight\": 0,\n recoverable: 0, blocked: 0, failed: 0,\n }\n}\n\nexport interface WorkspaceProjectStatus {\n id: string\n /** Legacy/default catalog provider. */\n provider: string\n /** Effective providers resolved from every manifest style. */\n providers: string[]\n account: string | null\n manifest: string\n lock: string\n entries: number\n byState: Record<PlanState, number>\n spendByUnit: Record<CostUnit, number>\n error: string | null\n}\n\nexport interface WorkspaceStatusReport {\n version: 1\n safe: boolean\n /** The catalog's own directory — resolved paths in `projects` sit under it. */\n dir: string\n projects: WorkspaceProjectStatus[]\n totals: {\n byState: Record<PlanState, number>\n spendByUnit: Record<CostUnit, number>\n claims: number\n }\n diagnostics: WorkspaceDiagnostic[]\n}\n\n/**\n * Aggregate, read-only account/project state — offline throughout, using the\n * same offline cost estimator `plan` uses. A project whose manifest or lock\n * fails to load surfaces as that project's own `error` rather than aborting\n * the whole report, so one broken sibling does not hide every other\n * project's status. It never writes to any registered project's lock.\n */\nexport async function workspaceStatus(ws: Workspace, dir: string): Promise<WorkspaceStatusReport> {\n const diagnostics = validateWorkspace(ws, dir)\n const projects: WorkspaceProjectStatus[] = []\n const totalsByState = emptyStateCounts()\n const totalsSpend: Record<CostUnit, number> = { generations: 0, usd: 0, free: 0 }\n\n for (const project of ws.projects) {\n const { manifestPath, lockPath } = resolveProject(dir, project)\n const base = {\n id: project.id,\n provider: project.provider,\n account: project.account ?? null,\n manifest: manifestPath,\n lock: lockPath,\n }\n try {\n const loaded = await loadManifest(manifestPath)\n const specs = await resolveSpecs(loaded)\n const providers = [...new Set(\n Object.values(loaded.manifest.styles).map(\n (style) => style.provider ?? loaded.manifest.provider,\n ),\n )].sort()\n if (!providers.length) providers.push(loaded.manifest.provider)\n const lock = await loadLock(lockPath)\n normalizeLockOutputPaths(lock, specs)\n const plan = await buildPlan(specs, lock)\n const byState = summarize(plan)\n const spend = spendByUnit(lock)\n for (const state of Object.keys(byState) as PlanState[]) {\n totalsByState[state] += byState[state]\n }\n for (const unit of Object.keys(spend) as CostUnit[]) {\n totalsSpend[unit] = (totalsSpend[unit] ?? 0) + (spend[unit] ?? 0)\n }\n projects.push({\n ...base,\n provider: providers.length === 1 ? providers[0]! : project.provider,\n providers,\n entries: Object.keys(lock.entries).length,\n byState,\n spendByUnit: spend,\n error: null,\n })\n } catch (err) {\n projects.push({\n ...base,\n providers: [project.provider],\n entries: 0,\n byState: emptyStateCounts(),\n spendByUnit: { generations: 0, usd: 0, free: 0 },\n error: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n let claims = 0\n try {\n claims = (await workspaceClaims(ws, dir)).claimed.size\n } catch {\n // Already visible via a project's own `error` or a missing-lock\n // diagnostic; not worth surfacing a second time here.\n }\n\n return {\n version: 1,\n safe: !diagnostics.some((d) => d.level === \"error\") && projects.every((p) => !p.error),\n dir,\n projects,\n totals: { byState: totalsByState, spendByUnit: totalsSpend, claims },\n diagnostics,\n }\n}\n","import { existsSync } from \"node:fs\"\nimport { readFile, readdir, rm } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport {\n cachePathFor,\n isSha256Hash,\n parseCache,\n saveCache,\n type HashCache,\n} from \"../cache.ts\"\nimport { sha256 } from \"../hash.ts\"\nimport type { Lock } from \"../types.ts\"\nimport { mediaTypeFromExtension, validateMedia } from \"../media.ts\"\n\nexport interface ContentCacheIssue {\n name: string\n reason: string\n}\n\nexport interface ContentCacheHealth {\n path: string\n exists: boolean\n files: number\n bytes: number\n valid: number\n referenced: number\n unreferenced: string[]\n missingReferenced: string[]\n invalid: ContentCacheIssue[]\n}\n\nexport interface RemoteHashCacheHealth {\n path: string\n exists: boolean\n entries: number\n valid: number\n invalidIds: string[]\n error: string | null\n}\n\nexport interface CacheHealthReport {\n safe: boolean\n content: ContentCacheHealth\n remoteHashes: RemoteHashCacheHealth\n removed: {\n contentFiles: number\n remoteHashEntries: number\n resetRemoteHashCache: boolean\n }\n}\n\nexport interface CacheHealthOptions {\n /** Remove invalid and unreferenced content, plus invalid remote hash entries. */\n prune?: boolean\n}\n\n/**\n * Inspect both local caches without contacting the provider.\n *\n * Content PNGs are project-local and keyed by lockfile SHA, so orphaned bytes\n * can be removed safely. The object-hash cache is account-wide: this function\n * validates its schema and hashes but never removes an object merely because\n * the current project does not reference it. `adopt` owns that live-ID prune,\n * because only it has walked the complete provider account.\n */\nexport async function inspectCaches(\n lock: Lock,\n lockPath: string,\n options: CacheHealthOptions = {},\n): Promise<CacheHealthReport> {\n if (options.prune && !existsSync(lockPath)) {\n throw new Error(`Refusing to prune without an existing lockfile at ${path.resolve(lockPath)}`)\n }\n const contentDir = path.resolve(path.dirname(lockPath), \".pixelkiln\", \"cache\")\n const remotePath = path.resolve(cachePathFor(lockPath))\n const referenced = new Set(\n Object.values(lock.entries).flatMap((entry) => entry.outputs.map((output) => output.sha256)),\n )\n\n let content = await inspectContentCache(contentDir, referenced)\n let remoteHashes = await inspectRemoteHashCache(remotePath)\n const removed = { contentFiles: 0, remoteHashEntries: 0, resetRemoteHashCache: false }\n\n if (options.prune) {\n const names = new Set([\n ...content.unreferenced,\n ...content.invalid.map((issue) => issue.name),\n ])\n for (const name of names) {\n // Every name came directly from a non-recursive readdir of contentDir;\n // removing this explicit child cannot escape through path traversal.\n try {\n await rm(path.join(contentDir, name), { force: true })\n removed.contentFiles++\n } catch {\n // Directories and permission failures remain in the follow-up report.\n }\n }\n\n if (remoteHashes.error) {\n await saveCache(remotePath, { version: 1, hashes: {} })\n removed.resetRemoteHashCache = true\n } else if (remoteHashes.invalidIds.length) {\n const cache = parseCache(JSON.parse(await readFile(remotePath, \"utf8\")))\n for (const id of remoteHashes.invalidIds) delete cache.hashes[id]\n removed.remoteHashEntries = remoteHashes.invalidIds.length\n await saveCache(remotePath, cache)\n }\n\n content = await inspectContentCache(contentDir, referenced)\n remoteHashes = await inspectRemoteHashCache(remotePath)\n }\n\n return {\n safe: content.invalid.length === 0 && !remoteHashes.error && remoteHashes.invalidIds.length === 0,\n content,\n remoteHashes,\n removed,\n }\n}\n\nasync function inspectContentCache(\n contentDir: string,\n referenced: Set<string>,\n): Promise<ContentCacheHealth> {\n const report: ContentCacheHealth = {\n path: contentDir,\n exists: existsSync(contentDir),\n files: 0,\n bytes: 0,\n valid: 0,\n referenced: 0,\n unreferenced: [],\n missingReferenced: [],\n invalid: [],\n }\n if (!report.exists) {\n report.missingReferenced = [...referenced].sort()\n return report\n }\n\n const present = new Set<string>()\n const entries = await readdir(contentDir, { withFileTypes: true })\n for (const entry of entries) {\n if (!entry.isFile()) {\n report.invalid.push({ name: entry.name, reason: \"not a regular file\" })\n continue\n }\n report.files++\n const file = path.join(contentDir, entry.name)\n const mediaType = mediaTypeFromExtension(entry.name)\n const expected = mediaType ? entry.name.slice(0, -4) : \"\"\n let bytes: Buffer\n try {\n bytes = await readFile(file)\n report.bytes += bytes.length\n } catch (err) {\n report.invalid.push({\n name: entry.name,\n reason: `unreadable: ${err instanceof Error ? err.message : String(err)}`,\n })\n continue\n }\n if (!isSha256Hash(expected)) {\n report.invalid.push({ name: entry.name, reason: \"filename is not <sha256>.png or <sha256>.gif\" })\n continue\n }\n if (sha256(bytes) !== expected) {\n report.invalid.push({ name: entry.name, reason: \"bytes do not match filename hash\" })\n continue\n }\n try {\n validateMedia(bytes, mediaType!)\n } catch (err) {\n report.invalid.push({\n name: entry.name,\n reason: `invalid ${mediaType === \"image/gif\" ? \"GIF\" : \"PNG\"}: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n })\n continue\n }\n present.add(expected)\n report.valid++\n if (referenced.has(expected)) report.referenced++\n else report.unreferenced.push(entry.name)\n }\n report.unreferenced.sort()\n report.missingReferenced = [...referenced].filter((hash) => !present.has(hash)).sort()\n return report\n}\n\nasync function inspectRemoteHashCache(remotePath: string): Promise<RemoteHashCacheHealth> {\n const report: RemoteHashCacheHealth = {\n path: remotePath,\n exists: existsSync(remotePath),\n entries: 0,\n valid: 0,\n invalidIds: [],\n error: null,\n }\n if (!report.exists) return report\n let cache: HashCache\n try {\n cache = parseCache(JSON.parse(await readFile(remotePath, \"utf8\")))\n } catch (err) {\n report.error = err instanceof Error ? err.message : String(err)\n return report\n }\n report.entries = Object.keys(cache.hashes).length\n for (const [id, hash] of Object.entries(cache.hashes)) {\n if (isSha256Hash(hash)) report.valid++\n else report.invalidIds.push(id)\n }\n report.invalidIds.sort()\n return report\n}\n","import type { LockEntry, ResolvedSpec } from \"../types.ts\"\nimport { fallbackOutputRole, resolveSpecEntryOutputs } from \"../outputs.ts\"\nimport { packSprites, type PackedFrame, type PackedSource } from \"./pack.ts\"\n\nexport type TilesetFormat = \"generic\" | \"tiled\" | \"godot\"\n\nexport interface NormalizedTileRules {\n ruleType: \"edge\" | \"corner\" | \"outline\"\n arity: 4 | 6\n connectivity?: \"same\" | \"other\"\n terrains: string[]\n /** Provider tile index to adjacency mask. Tiles absent here are stamp-only. */\n masks: Record<number, number>\n raw: Record<string, unknown>\n}\n\nexport interface GenericTileset {\n format: \"pixelkiln-tileset\"\n version: 1\n name: string\n style: string\n asset: string\n image: string\n tile: { width: number; height: number }\n sheet: { width: number; height: number; columns: number }\n tiles: Array<{\n id: number\n /** Original provider index; can differ from id when stamp-only keys leave gaps. */\n sourceIndex: number\n role: string\n x: number\n y: number\n width: number\n height: number\n bitmask?: number\n stampOnly: boolean\n }>\n /** Complete provider object, even when its rule family is not normalized yet. */\n providerRules: Record<string, unknown> | null\n rules: NormalizedTileRules | null\n}\n\nexport interface TilesetExport {\n png: Buffer\n extension: \".json\" | \".tsj\" | \".tres\"\n document: string\n generic: GenericTileset\n sources: PackedSource[]\n}\n\nexport interface TilesetExportOptions {\n format: TilesetFormat\n manifestDir: string\n imageName: string\n columns?: number\n}\n\n/** Parse the deliberately open provider schema into the stable export subset. */\nexport function normalizeTileRules(raw: unknown): NormalizedTileRules | null {\n if (!isRecord(raw)) return null\n const ruleType = raw.rule_type\n const arity = raw.arity\n if (ruleType !== \"edge\" && ruleType !== \"corner\" && ruleType !== \"outline\") return null\n if (arity !== 4 && arity !== 6) return null\n\n const masks: Record<number, number> = {}\n if (isRecord(raw.tiles)) {\n for (const [key, value] of Object.entries(raw.tiles)) {\n const index = tileIndex(key)\n const mask = typeof value === \"number\"\n ? value\n : isRecord(value) && typeof value.bitmask === \"number\"\n ? value.bitmask\n : isRecord(value) && typeof value.mask === \"number\"\n ? value.mask\n : null\n if (index !== null && mask !== null && Number.isInteger(mask) && mask >= 0) masks[index] = mask\n }\n }\n\n const connectivity = raw.connectivity === \"same\" || raw.connectivity === \"other\"\n ? raw.connectivity\n : undefined\n const terrains = Array.isArray(raw.terrains)\n ? raw.terrains.filter((item): item is string => typeof item === \"string\")\n : []\n return {\n ruleType,\n arity,\n ...(connectivity ? { connectivity } : {}),\n terrains,\n masks,\n raw,\n }\n}\n\n/** Build an atlas plus generic, Tiled TSJ, or Godot 4 TileSet metadata. */\nexport function exportTileset(\n entry: LockEntry,\n spec: ResolvedSpec,\n options: TilesetExportOptions,\n): TilesetExport {\n const outputs = resolveSpecEntryOutputs(entry, spec)\n if (!outputs.length) throw new Error(`${spec.styleId}/${spec.assetId} has no downloaded outputs`)\n\n const packed = packSprites(\n outputs.map((output) => ({\n id: output.role ?? fallbackOutputRole(output.index),\n path: output.absolutePath,\n })),\n { columns: options.columns, order: \"input\" },\n )\n if (packed.skipped.length) {\n throw new Error(\n `Cannot export ${spec.styleId}/${spec.assetId}: ` +\n packed.skipped.map((item) => `${item.id}: ${item.reason}`).join(\"; \"),\n )\n }\n\n const metadata = entry.providerMetadata?.[entry.provider]\n const rawRules = isRecord(metadata) ? metadata.tileRules : undefined\n const rules = normalizeTileRules(rawRules)\n const frames = packed.atlas.frames\n const generic = buildGeneric(\n spec,\n options.imageName,\n packed.atlas,\n frames,\n isRecord(rawRules) ? rawRules : null,\n rules,\n )\n\n if (options.format === \"generic\") {\n return {\n png: packed.png,\n extension: \".json\",\n document: JSON.stringify(generic, null, 2) + \"\\n\",\n generic,\n sources: packed.sources,\n }\n }\n\n assertUniformTiles(generic)\n if ((rawRules !== undefined || entry.tileFeature) && !rules) {\n throw new Error(\n `${options.format} export needs recognized adjacency rules; use --format generic ` +\n `to retain this provider rule object without guessing`,\n )\n }\n if (rules?.arity === 6) {\n throw new Error(\n `${options.format} export does not yet map six-edge hex masks safely; use --format generic`,\n )\n }\n if (rules?.ruleType === \"outline\") {\n throw new Error(\n `${options.format} export cannot infer adjacency from outline/stamp-only rules; use --format generic`,\n )\n }\n\n if (options.format === \"tiled\") {\n return {\n png: packed.png,\n extension: \".tsj\",\n document: JSON.stringify(buildTiled(generic), null, 2) + \"\\n\",\n generic,\n sources: packed.sources,\n }\n }\n return {\n png: packed.png,\n extension: \".tres\",\n document: buildGodot(generic, spec),\n generic,\n sources: packed.sources,\n }\n}\n\nfunction buildGeneric(\n spec: ResolvedSpec,\n imageName: string,\n atlas: { sheet: { width: number; height: number }; cell: { width: number; height: number }; columns: number },\n frames: PackedFrame[],\n providerRules: Record<string, unknown> | null,\n rules: NormalizedTileRules | null,\n): GenericTileset {\n return {\n format: \"pixelkiln-tileset\",\n version: 1,\n name: `${spec.styleId}/${spec.assetId}`,\n style: spec.styleId,\n asset: spec.assetId,\n image: imageName,\n tile: { ...atlas.cell },\n sheet: { ...atlas.sheet, columns: atlas.columns },\n tiles: frames.map((frame, index) => {\n const sourceIndex = tileIndex(frame.id) ?? index\n return {\n id: index,\n sourceIndex,\n role: frame.id,\n x: frame.x,\n y: frame.y,\n width: frame.width,\n height: frame.height,\n ...(rules?.masks[sourceIndex] !== undefined ? { bitmask: rules.masks[sourceIndex] } : {}),\n stampOnly: rules ? rules.masks[sourceIndex] === undefined : true,\n }\n }),\n providerRules,\n rules,\n }\n}\n\nfunction buildTiled(generic: GenericTileset): Record<string, unknown> {\n const rules = generic.rules\n const tiled: Record<string, unknown> = {\n type: \"tileset\",\n version: \"1.10\",\n tiledversion: \"1.12.2\",\n name: generic.name.replace(\"/\", \"-\"),\n tilewidth: generic.tile.width,\n tileheight: generic.tile.height,\n tilecount: generic.tiles.length,\n columns: generic.sheet.columns,\n image: generic.image,\n imagewidth: generic.sheet.width,\n imageheight: generic.sheet.height,\n margin: 0,\n spacing: 0,\n }\n if (!rules || rules.ruleType === \"outline\") return tiled\n\n const terrainNames = terrainNamesFor(rules)\n tiled.wangsets = [{\n name: generic.name,\n type: rules.ruleType,\n tile: representativeTile(generic, 0),\n colors: terrainNames.map((name, index) => ({\n name,\n color: index === 0 ? \"#5ab552\" : \"#4c78a8\",\n tile: representativeTile(generic, index),\n probability: 1,\n })),\n properties: rules.connectivity\n ? [{ name: \"pixelkiln:connectivity\", type: \"string\", value: rules.connectivity }]\n : [],\n wangtiles: generic.tiles\n .filter((tile) => tile.bitmask !== undefined)\n .map((tile) => ({ tileid: tile.id, wangid: tiledWangId(rules, tile.bitmask!) })),\n }]\n return tiled\n}\n\nfunction tiledWangId(rules: NormalizedTileRules, mask: number): number[] {\n const bitColor = (bit: number) => ((mask & (1 << bit)) !== 0 ? 1 : 2)\n if (rules.ruleType === \"corner\") {\n // Tiled order: top edge, NE, right edge, SE, bottom edge, SW, left edge, NW.\n return [0, bitColor(2), 0, bitColor(0), 0, bitColor(1), 0, bitColor(3)]\n }\n // PixelLab edge mask: bit0=N bit1=E bit2=S bit3=W.\n return [bitColor(0), 0, bitColor(1), 0, bitColor(2), 0, bitColor(3), 0]\n}\n\nfunction buildGodot(generic: GenericTileset, spec: ResolvedSpec): string {\n const rules = generic.rules\n const lines = [\n `[gd_resource type=\"TileSet\" load_steps=3 format=3]`,\n \"\",\n `[ext_resource type=\"Texture2D\" path=${JSON.stringify(`./${generic.image}`)} id=\"1_texture\"]`,\n \"\",\n `[sub_resource type=\"TileSetAtlasSource\" id=\"TileSetAtlasSource_pixelkiln\"]`,\n `texture = ExtResource(\"1_texture\")`,\n `texture_region_size = Vector2i(${generic.tile.width}, ${generic.tile.height})`,\n ]\n\n for (const tile of generic.tiles) {\n const x = tile.id % generic.sheet.columns\n const y = Math.floor(tile.id / generic.sheet.columns)\n lines.push(`${x}:${y}/0 = 0`)\n if (!rules || tile.bitmask === undefined || rules.ruleType === \"outline\") continue\n const values = godotTerrainBits(rules, tile.bitmask)\n lines.push(`${x}:${y}/0/terrain_set = 0`)\n lines.push(`${x}:${y}/0/terrain = ${dominantTerrain(values)}`)\n for (const [side, value] of Object.entries(values)) {\n lines.push(`${x}:${y}/0/terrains_peering_bit/${side} = ${value}`)\n }\n }\n\n lines.push(\"\", \"[resource]\")\n lines.push(`tile_size = Vector2i(${generic.tile.width}, ${generic.tile.height})`)\n const shape = godotTileShape(spec.tileType ?? \"isometric\")\n if (shape !== 0) lines.push(`tile_shape = ${shape}`)\n if (rules && rules.ruleType !== \"outline\") {\n lines.push(`terrain_set_0/mode = ${rules.ruleType === \"corner\" ? 1 : 2}`)\n for (const [index, name] of terrainNamesFor(rules).entries()) {\n lines.push(`terrain_set_0/terrain_${index}/name = ${JSON.stringify(name)}`)\n lines.push(\n `terrain_set_0/terrain_${index}/color = ` +\n (index === 0 ? \"Color(0.3529, 0.7098, 0.3216, 1)\" : \"Color(0.298, 0.4706, 0.6588, 1)\"),\n )\n }\n }\n lines.push(`sources/0 = SubResource(\"TileSetAtlasSource_pixelkiln\")`, \"\")\n return lines.join(\"\\n\")\n}\n\nfunction godotTerrainBits(rules: NormalizedTileRules, mask: number): Record<string, number> {\n const terrain = (bit: number) => ((mask & (1 << bit)) !== 0 ? 0 : 1)\n if (rules.ruleType === \"corner\") {\n return {\n top_left_corner: terrain(3),\n top_right_corner: terrain(2),\n bottom_left_corner: terrain(1),\n bottom_right_corner: terrain(0),\n }\n }\n return {\n top_side: terrain(0),\n right_side: terrain(1),\n bottom_side: terrain(2),\n left_side: terrain(3),\n }\n}\n\nfunction dominantTerrain(values: Record<string, number>): number {\n const terrainZero = Object.values(values).filter((value) => value === 0).length\n return terrainZero * 2 >= Object.keys(values).length ? 0 : 1\n}\n\nfunction godotTileShape(tileType: string | undefined): number {\n if (tileType === \"isometric\" || tileType === \"oblique\") return 1\n if (tileType === \"hex\" || tileType === \"hex_pointy\") return 3\n return 0\n}\n\nfunction representativeTile(generic: GenericTileset, terrainIndex: number): number {\n const rules = generic.rules!\n const full = (1 << rules.arity) - 1\n const wanted = terrainIndex === 0 ? full : 0\n return generic.tiles.find((tile) => tile.bitmask === wanted)?.id ?? -1\n}\n\nfunction terrainNamesFor(rules: NormalizedTileRules): string[] {\n return [rules.terrains[0] ?? \"feature\", rules.terrains[1] ?? \"background\"]\n}\n\nfunction assertUniformTiles(generic: GenericTileset): void {\n const mismatched = generic.tiles.filter(\n (tile) => tile.width !== generic.tile.width || tile.height !== generic.tile.height,\n )\n if (mismatched.length) {\n throw new Error(\n `Engine tilesets require uniform ${generic.tile.width}x${generic.tile.height} cells; ` +\n `mismatched: ${mismatched.map((tile) => tile.role).join(\", \")}. Use --format generic.`,\n )\n }\n}\n\nfunction tileIndex(key: string): number | null {\n const match = key.match(/(?:^|[_-])(\\d+)$/)\n return match ? Number(match[1]) : null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n","import { mkdir, writeFile, readFile } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport type { Provider } from \"../provider.ts\"\nimport { sha256 } from \"../hash.ts\"\nimport { saveLock, upsert } from \"../lock.ts\"\nimport { portableOutputPath } from \"../outputs.ts\"\nimport { decodePng } from \"../png.ts\"\nimport { shouldPersistSourceUrl } from \"../source-url.ts\"\nimport { lockKey, type Lock, type Manifest } from \"../types.ts\"\nimport {\n applyTags,\n idFromPrompt,\n SALVAGED_SPEC_HASH,\n type Orphan,\n type SalvageDecision,\n} from \"../pipeline/salvage.ts\"\nimport { renderSalvageSheet } from \"./salvage-sheet.ts\"\nimport { serveReviewPage } from \"./review-server.ts\"\n\nconst PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])\n\nexport interface SalvageResult {\n imported: number\n kept: number\n discarded: number\n failed: number\n}\n\n/**\n * Serves the triage sheet and applies decisions.\n *\n * `import` is the only action that touches local state: it downloads the image,\n * writes a manifest asset and a lock entry, so a recovered sprite becomes a\n * first-class tracked asset rather than a loose file. `keep` and `discard` only\n * write tags upstream — no object is ever deleted here.\n */\nexport async function runSalvage(\n provider: Provider,\n orphans: Orphan[],\n ctx: {\n manifestPath: string\n manifest: Manifest\n styleId: string\n importDir: string\n lock: Lock\n lockPath: string\n },\n opts: { port?: number; open?: boolean; onProgress?: (msg: string) => void } = {},\n): Promise<SalvageResult> {\n const log = opts.onProgress ?? (() => {})\n const html = renderSalvageSheet(orphans, {\n styleId: ctx.styleId,\n importDir: path.relative(process.cwd(), ctx.importDir) || \".\",\n })\n const byId = new Map(orphans.map((o) => [o.id, o]))\n const existingTags = new Map(orphans.map((o) => [o.id, o.tags]))\n\n return serveReviewPage<SalvageResult>({\n html,\n port: opts.port,\n open: opts.open,\n onProgress: log,\n onReady: (url) => {\n log(`\\n ${orphans.length} unclaimed object(s) to triage: ${url}`)\n log(` (nothing is deleted here — discard only tags)\\n`)\n },\n handleApply: async (body) => {\n const { decisions } = body as { decisions: SalvageDecision[] }\n\n const result: SalvageResult = { imported: 0, kept: 0, discarded: 0, failed: 0 }\n const taken = new Set(Object.keys(ctx.manifest.assets))\n const importedAssetIds: string[] = []\n\n for (const decision of decisions) {\n const orphan = byId.get(decision.id)\n if (!orphan) continue\n\n if (decision.action === \"import\") {\n try {\n const buf = await provider.download(orphan.previewUrl)\n if (!buf.subarray(0, 8).equals(PNG_SIGNATURE)) throw new Error(\"not a PNG\")\n decodePng(buf)\n\n const assetId = idFromPrompt(orphan.prompt, taken)\n const rel = path.join(\"_salvaged\", `${assetId}.png`)\n const outFile = path.resolve(ctx.importDir, rel)\n await mkdir(path.dirname(outFile), { recursive: true })\n await writeFile(outFile, buf)\n\n ctx.manifest.assets[assetId] = {\n prompt: orphan.prompt,\n promptByStyle: {},\n category: \"_salvaged\",\n file: rel,\n tags: [\"salvaged\"],\n styles: [ctx.styleId],\n providerInputs: {},\n ...(orphan.width === orphan.height\n ? { size: orphan.width }\n : { width: orphan.width, height: orphan.height }),\n }\n\n const durableSource = shouldPersistSourceUrl(orphan.previewUrl)\n ? orphan.previewUrl\n : null\n\n upsert(ctx.lock, lockKey(ctx.styleId, assetId), {\n styleId: ctx.styleId,\n assetId,\n specHash: SALVAGED_SPEC_HASH,\n generator: orphan.width === orphan.height ? \"1dir\" : \"map\",\n prompt: orphan.prompt,\n width: orphan.width,\n height: orphan.height,\n jobId: orphan.id,\n reviewObjectId: null,\n objectId: orphan.id,\n candidateIndex: null,\n status: \"downloaded\",\n error: null,\n // The bytes are already local. Do not turn a temporary signed\n // review URL into a credential-bearing committed lock entry.\n sourceUrl: durableSource,\n sourceUrls: durableSource ? [{ url: durableSource }] : [],\n outputs: [{\n path: portableOutputPath(outFile, path.dirname(ctx.manifestPath)),\n sha256: sha256(buf),\n }],\n submittedAt: orphan.createdAt,\n downloadedAt: new Date().toISOString(),\n cost: 0, // already paid for, in an earlier period\n costUnit: \"generations\",\n provider: provider.id,\n })\n importedAssetIds.push(assetId)\n result.imported++\n log(` imported ${assetId} ← ${orphan.id}`)\n } catch (err) {\n result.failed++\n log(` import failed ${orphan.id}: ${err instanceof Error ? err.message : String(err)}`)\n }\n } else if (decision.action === \"keep\") {\n result.kept++\n } else {\n result.discarded++\n }\n }\n\n await applyTags(provider, decisions, existingTags, { onProgress: log })\n\n // Persist the manifest additions and the lock together. Only the\n // newly imported entries are written back — re-merging the whole\n // in-memory manifest would overwrite every pre-existing asset with\n // its loadManifest()-normalized copy, turning a one-asset import\n // into a diff touching the entire file.\n const raw = JSON.parse(await readFile(ctx.manifestPath, \"utf8\")) as Manifest\n for (const id of importedAssetIds) raw.assets[id] = ctx.manifest.assets[id]!\n await writeFile(ctx.manifestPath, JSON.stringify(raw, null, 2) + \"\\n\")\n await saveLock(ctx.lockPath, ctx.lock)\n\n return result\n },\n })\n}\n","import type { Orphan } from \"../pipeline/salvage.ts\"\n\nconst escapeHtml = (s: string) =>\n s.replace(/[&<>\"']/g, (c) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" })[c]!)\n\nexport interface SalvageSheetContext {\n /** The style every \"import\" on this page will be tagged and routed under. */\n styleId: string\n /** Where an import lands, shown so the page answers \"where does this go\"\n * without anyone needing to go check the manifest. */\n importDir: string\n}\n\n/**\n * Triage sheet for unclaimed account objects.\n *\n * Optimised for volume: a couple of hundred items, most of which get a\n * one-keystroke verdict. Everything defaults to no decision, so closing the tab\n * changes nothing, and `discard` only ever writes a tag — deletion is a\n * separate command that has to be asked for by name.\n *\n * `salvage` opens one tab per matched style in sequence (grouping — see\n * pipeline/salvage.ts), and every one of them used to render the exact same\n * generic title. With several left open across styles there was no way to\n * tell them apart short of squinting at which images loaded. The tab title\n * and header now name the style the page is actually scoped to.\n */\nexport function renderSalvageSheet(orphans: Orphan[], ctx?: SalvageSheetContext): string {\n const safe = orphans.map((o) => ({ ...o, prompt: escapeHtml(o.prompt) }))\n const data = JSON.stringify(safe).replace(/<\\//g, \"<\\\\/\")\n const styleId = ctx ? escapeHtml(ctx.styleId) : null\n const importDir = ctx ? escapeHtml(ctx.importDir) : null\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>pixelkiln salvage${styleId ? ` — ${styleId}` : \"\"}</title>\n<style>\n :root { --bg:#0f1115; --panel:#171a21; --line:#262b36; --text:#e6e8ee; --dim:#8b93a7;\n --import:#6ee7a8; --keep:#7cc4ff; --discard:#f87171; }\n @media (prefers-color-scheme: light) {\n :root { --bg:#f6f7f9; --panel:#fff; --line:#dfe3ea; --text:#1a1d23; --dim:#666e80;\n --import:#0a8f52; --keep:#1a6fd4; --discard:#c0392b; }\n }\n * { box-sizing:border-box; }\n body { margin:0; background:var(--bg); color:var(--text);\n font:14px/1.5 ui-sans-serif,-apple-system,\"SF Pro Text\",Inter,system-ui,sans-serif; }\n header { position:sticky; top:0; z-index:10; background:var(--panel);\n border-bottom:1px solid var(--line); padding:12px 20px; display:flex; gap:14px;\n align-items:center; flex-wrap:wrap; }\n h1 { font-size:15px; margin:0; font-weight:600; }\n h1 .ctx { font-weight:500; color:var(--dim); }\n h1 .dest { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12.5px; }\n .tally { color:var(--dim); font-variant-numeric:tabular-nums; }\n .tally b { color:var(--text); font-weight:600; }\n button { font:inherit; font-weight:550; border-radius:7px; padding:7px 14px;\n border:1px solid var(--line); background:transparent; color:var(--text); cursor:pointer; }\n button.primary { background:var(--import); border-color:var(--import); color:#08130d; }\n button:disabled { opacity:.45; cursor:not-allowed; }\n main { display:grid; grid-template-columns:repeat(auto-fill,minmax(190px,1fr)); gap:12px; padding:18px 20px 80px; }\n .card { border:2px solid var(--line); border-radius:10px; background:var(--panel);\n padding:10px; display:flex; flex-direction:column; gap:8px; }\n .card.import { border-color:var(--import); }\n .card.keep { border-color:var(--keep); }\n .card.discard { border-color:var(--discard); opacity:.5; }\n .thumb { height:120px; display:flex; align-items:center; justify-content:center;\n border-radius:6px;\n background-image:\n linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%),\n linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%);\n background-size:12px 12px; background-position:0 0,6px 6px; }\n .thumb img { image-rendering:pixelated; max-height:112px; max-width:100%; }\n .meta { font-size:11px; color:var(--dim); font-variant-numeric:tabular-nums; }\n .prompt { font-size:11.5px; color:var(--dim); max-height:3.2em; overflow:hidden; }\n .acts { display:flex; gap:5px; }\n .acts button { flex:1; padding:5px 0; font-size:11.5px; }\n .acts button.on-import { background:var(--import); border-color:var(--import); color:#08130d; }\n .acts button.on-keep { background:var(--keep); border-color:var(--keep); color:#04121f; }\n .acts button.on-discard { background:var(--discard); border-color:var(--discard); color:#fff; }\n footer { position:fixed; bottom:0; left:0; right:0; background:var(--panel);\n border-top:1px solid var(--line); padding:10px 20px; font-size:12px; color:var(--dim); }\n kbd { border:1px solid var(--line); border-bottom-width:2px; border-radius:4px;\n padding:1px 5px; font-size:11px; font-family:ui-monospace,Menlo,monospace; }\n</style>\n</head>\n<body>\n<header>\n <h1>pixelkiln salvage${\n styleId\n ? ` <span class=\"ctx\">— ${styleId}<span class=\"dest\"> → ${importDir}/_salvaged/</span></span>`\n : \"\"\n }</h1>\n <span class=\"tally\"><b id=\"ti\">0</b> import · <b id=\"tk\">0</b> keep · <b id=\"td\">0</b> discard ·\n <b id=\"tu\">0</b> undecided</span>\n <span style=\"flex:1\"></span>\n <button id=\"allDiscard\">Discard all undecided</button>\n <button id=\"allKeep\">Keep all undecided</button>\n <button id=\"submit\" class=\"primary\" disabled>Apply</button>\n</header>\n<main id=\"grid\"></main>\n<footer>\n <b>import</b> downloads it and adds it to your manifest · <b>keep</b> tags it and leaves it ·\n <b>discard</b> only tags it — nothing is deleted here.\n Hover a card and press <kbd>i</kbd> / <kbd>k</kbd> / <kbd>d</kbd>, or <kbd>u</kbd> to undo.\n</footer>\n<script>\nconst ITEMS = ${data};\nconst picks = new Map();\nconst grid = document.getElementById('grid');\nlet hovered = null;\n\nITEMS.forEach((o, i) => {\n const el = document.createElement('div');\n el.className = 'card';\n el.dataset.i = String(i);\n el.innerHTML =\n '<div class=\"thumb\"><img src=\"' + o.previewUrl + '\" loading=\"lazy\"></div>' +\n '<div class=\"meta\">' + o.width + '×' + o.height + ' · ' + o.createdAt.slice(0,10) + '</div>' +\n '<div class=\"prompt\">' + o.prompt + '</div>' +\n '<div class=\"acts\">' +\n '<button data-a=\"import\">import</button>' +\n '<button data-a=\"keep\">keep</button>' +\n '<button data-a=\"discard\">discard</button>' +\n '</div>';\n el.querySelectorAll('.acts button').forEach(b => {\n b.onclick = () => choose(i, b.dataset.a);\n });\n el.onmouseenter = () => { hovered = i; };\n grid.appendChild(el);\n});\n\nfunction choose(i, action) {\n if (picks.get(i) === action) picks.delete(i); else picks.set(i, action);\n const el = grid.children[i];\n el.className = 'card' + (picks.has(i) ? ' ' + picks.get(i) : '');\n el.querySelectorAll('.acts button').forEach(b => {\n b.className = picks.get(i) === b.dataset.a ? 'on-' + b.dataset.a : '';\n });\n refresh();\n}\n\nfunction refresh() {\n const c = { import: 0, keep: 0, discard: 0 };\n for (const a of picks.values()) c[a]++;\n ti.textContent = c.import; tk.textContent = c.keep; td.textContent = c.discard;\n tu.textContent = ITEMS.length - picks.size;\n document.getElementById('submit').disabled = picks.size === 0;\n}\n\ndocument.addEventListener('keydown', e => {\n if (hovered === null) return;\n const map = { i: 'import', k: 'keep', d: 'discard' };\n if (map[e.key]) { choose(hovered, map[e.key]); e.preventDefault(); }\n else if (e.key === 'u') { picks.delete(hovered); choose(hovered, '__none__'); }\n});\n\ndocument.getElementById('allKeep').onclick = () => {\n ITEMS.forEach((_, i) => { if (!picks.has(i)) choose(i, 'keep'); });\n};\ndocument.getElementById('allDiscard').onclick = () => {\n ITEMS.forEach((_, i) => { if (!picks.has(i)) choose(i, 'discard'); });\n};\n\ndocument.getElementById('submit').onclick = async () => {\n const btn = document.getElementById('submit');\n btn.disabled = true; btn.textContent = 'applying…';\n const decisions = [...picks.entries()].map(([i, action]) => ({ id: ITEMS[i].id, action }));\n try {\n const res = await fetch('/apply', {\n method: 'POST', headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ decisions }),\n });\n if (!res.ok) throw new Error(await res.text());\n btn.textContent = 'done — close this tab';\n document.body.style.opacity = '.6';\n } catch (err) {\n btn.textContent = 'failed: ' + err.message; btn.disabled = false;\n }\n};\nrefresh();\n</script>\n</body>\n</html>`\n}\n","import path from \"node:path\"\nimport { existsSync } from \"node:fs\"\nimport { readdir, readFile } from \"node:fs/promises\"\nimport { fileURLToPath } from \"node:url\"\nimport { z } from \"zod\"\nimport { writeArtifactBundle } from \"./artifacts.ts\"\nimport { sha256, sha256File } from \"./hash.ts\"\nimport { StyleSchema, type Style } from \"./types.ts\"\n\nconst SHA256_RE = /^[0-9a-f]{64}$/\nconst RECIPE_ID_RE = /^[a-z0-9][a-z0-9-]*\\/[a-z0-9][a-z0-9-]*$/\nconst VERSION_RE = /^\\d+\\.\\d+\\.\\d+$/\nconst RECIPE_FILE = \"pixelkiln.recipe.json\"\nconst RECIPE_DIR_TOKEN = \"{{recipeDir}}\"\n\nconst PortablePathSchema = z.string().min(1).refine((value) => {\n if (value.includes(\"\\\\\") || path.posix.isAbsolute(value)) return false\n const parts = value.split(\"/\")\n return !parts.includes(\"\") && !parts.includes(\".\") && !parts.includes(\"..\")\n}, \"expected a portable relative path without '.', '..', or backslashes\")\n\nconst RecipeBindingSchema = z.object({\n nodeId: z.string().min(1),\n input: z.string().min(1),\n}).strict()\n\nexport const RecipeSchema = z.object({\n $schema: z.string().url().optional(),\n format: z.literal(\"pixelkiln-recipe\"),\n schemaVersion: z.literal(1),\n id: z.string().regex(RECIPE_ID_RE, \"expected provider/name\"),\n version: z.string().regex(VERSION_RE, \"expected x.y.z\"),\n provider: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),\n summary: z.string().min(1).max(240),\n files: z.array(z.object({\n path: PortablePathSchema,\n role: z.enum([\"workflow\", \"reference\"]),\n sha256: z.string().regex(SHA256_RE),\n }).strict()).default([]),\n models: z.array(z.object({\n path: PortablePathSchema,\n sha256: z.string().regex(SHA256_RE),\n source: z.string().url(),\n license: z.string().min(1),\n }).strict()).default([]),\n styleId: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),\n style: StyleSchema,\n workflow: z.object({\n path: PortablePathSchema,\n outputNodeId: z.string().min(1),\n numImages: z.number().int().min(1).max(16),\n bindings: z.object({\n prompt: RecipeBindingSchema,\n width: RecipeBindingSchema.optional(),\n height: RecipeBindingSchema.optional(),\n batchSize: RecipeBindingSchema.optional(),\n seed: RecipeBindingSchema.optional(),\n sourceImage: RecipeBindingSchema.optional(),\n maskImage: RecipeBindingSchema.optional(),\n strength: RecipeBindingSchema.optional(),\n }).strict(),\n }).strict().optional(),\n quality: z.object({\n stage: z.enum([\"composition-source\", \"production-candidate\"]),\n workingCanvas: z.object({\n width: z.number().int().min(16),\n height: z.number().int().min(16),\n }).strict(),\n recommendedNativeSize: z.object({\n min: z.number().int().min(1),\n max: z.number().int().min(1),\n }).strict(),\n paletteColors: z.object({\n min: z.number().int().min(1),\n max: z.number().int().min(1),\n }).strict(),\n background: z.enum([\"opaque\", \"transparent\", \"full-bleed\"]),\n checks: z.array(z.enum([\n \"prompt-coverage\",\n \"native-grid\",\n \"final-palette\",\n \"alpha-edge\",\n \"human-1x\",\n ])).min(1),\n notes: z.array(z.string().min(1)).default([]),\n }).strict(),\n integrity: z.object({\n algorithm: z.literal(\"sha256\"),\n digest: z.string().regex(SHA256_RE),\n }).strict(),\n}).strict().superRefine((recipe, context) => {\n if (recipe.style.provider && recipe.style.provider !== recipe.provider) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"style\", \"provider\"],\n message: \"must match the recipe provider\",\n })\n }\n const filePaths = recipe.files.map((file) => file.path)\n if (new Set(filePaths).size !== filePaths.length) {\n context.addIssue({ code: z.ZodIssueCode.custom, path: [\"files\"], message: \"duplicate file path\" })\n }\n const modelPaths = recipe.models.map((model) => model.path)\n if (new Set(modelPaths).size !== modelPaths.length) {\n context.addIssue({ code: z.ZodIssueCode.custom, path: [\"models\"], message: \"duplicate model path\" })\n }\n if (filePaths.includes(RECIPE_FILE)) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"files\"],\n message: `${RECIPE_FILE} cannot hash itself`,\n })\n }\n if (recipe.quality.recommendedNativeSize.min > recipe.quality.recommendedNativeSize.max) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"quality\", \"recommendedNativeSize\"],\n message: \"min cannot exceed max\",\n })\n }\n if (recipe.quality.paletteColors.min > recipe.quality.paletteColors.max) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"quality\", \"paletteColors\"],\n message: \"min cannot exceed max\",\n })\n }\n if (recipe.workflow && !recipe.files.some(\n (file) => file.path === recipe.workflow!.path && file.role === \"workflow\",\n )) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"workflow\", \"path\"],\n message: \"must name a file whose role is workflow\",\n })\n }\n if (recipe.provider === \"comfyui\") {\n if (!recipe.workflow) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"workflow\"],\n message: \"ComfyUI recipes require workflow metadata\",\n })\n return\n }\n const options = recipe.style.providerOptions.comfyui\n if (!options || typeof options !== \"object\" || Array.isArray(options)) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"style\", \"providerOptions\", \"comfyui\"],\n message: \"ComfyUI recipes require ComfyUI provider options\",\n })\n return\n }\n const expected = {\n workflowFile: `${RECIPE_DIR_TOKEN}/${recipe.workflow.path}`,\n outputNodeId: recipe.workflow.outputNodeId,\n numImages: recipe.workflow.numImages,\n bindings: recipe.workflow.bindings,\n }\n if (JSON.stringify(canonical(options)) !== JSON.stringify(canonical(expected))) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"style\", \"providerOptions\", \"comfyui\"],\n message: \"must match workflow metadata and use {{recipeDir}} for workflowFile\",\n })\n }\n }\n})\n\nexport type Recipe = z.infer<typeof RecipeSchema>\n\nexport interface LoadedRecipe {\n recipe: Recipe\n path: string\n dir: string\n bundled: boolean\n}\n\nexport interface RecipeFileVerification {\n path: string\n expectedSha256: string\n actualSha256: string | null\n status: \"ok\" | \"missing\" | \"mismatch\"\n}\n\nexport interface RecipeModelVerification {\n path: string\n expectedSha256: string\n actualSha256: string | null\n source: string\n license: string\n status: RecipeFileVerification[\"status\"] | \"unchecked\"\n}\n\nexport interface RecipeVerification {\n version: 1\n ok: boolean\n recipe: {\n id: string\n version: string\n path: string\n bundled: boolean\n }\n integrity: {\n expectedSha256: string\n actualSha256: string\n status: \"ok\" | \"mismatch\"\n }\n files: RecipeFileVerification[]\n models: RecipeModelVerification[]\n modelRoot: string | null\n}\n\nexport interface InstallRecipeOptions {\n out?: string\n force?: boolean\n cwd?: string\n bundledRoot?: string\n}\n\nexport interface InstallRecipeResult {\n recipe: Recipe\n destination: string\n changed: string[]\n unchanged: string[]\n styleId: string\n style: Style\n}\n\nfunction canonical(value: unknown): unknown {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) throw new Error(\"Recipe numbers must be finite.\")\n return value\n }\n if (Array.isArray(value)) return value.map(canonical)\n if (typeof value === \"object\") {\n const sorted: Record<string, unknown> = {}\n for (const key of Object.keys(value).sort()) {\n const item = (value as Record<string, unknown>)[key]\n if (item !== undefined) sorted[key] = canonical(item)\n }\n return sorted\n }\n throw new Error(`Recipe metadata cannot contain ${typeof value} values.`)\n}\n\nexport function recipeDigest(recipe: Recipe): string {\n const { integrity: _integrity, ...payload } = recipe\n return sha256(JSON.stringify(canonical(payload)))\n}\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nasync function readRecipeFile(recipePath: string, bundled: boolean): Promise<LoadedRecipe> {\n const absolute = path.resolve(recipePath)\n let raw: unknown\n try {\n raw = JSON.parse(await readFile(absolute, \"utf8\"))\n } catch (error) {\n throw new Error(`Could not read recipe ${absolute}: ${message(error)}`, { cause: error })\n }\n const parsed = RecipeSchema.safeParse(raw)\n if (!parsed.success) {\n throw new Error(\n `Invalid recipe ${absolute}:\\n` +\n parsed.error.issues.map((issue) => ` ${issue.path.join(\".\") || \"$\"}: ${issue.message}`).join(\"\\n\"),\n )\n }\n return { recipe: parsed.data, path: absolute, dir: path.dirname(absolute), bundled }\n}\n\nasync function walkRecipeFiles(root: string): Promise<string[]> {\n if (!existsSync(root)) return []\n const out: string[] = []\n for (const entry of await readdir(root, { withFileTypes: true })) {\n const resolved = path.join(root, entry.name)\n if (entry.isDirectory()) out.push(...await walkRecipeFiles(resolved))\n else if (entry.isFile() && entry.name === RECIPE_FILE) out.push(resolved)\n }\n return out\n}\n\nexport function bundledRecipeRoot(): string {\n return fileURLToPath(new URL(\"../recipes/\", import.meta.url))\n}\n\nexport async function listBundledRecipes(root = bundledRecipeRoot()): Promise<LoadedRecipe[]> {\n const recipes = await Promise.all(\n (await walkRecipeFiles(path.resolve(root))).map((file) => readRecipeFile(file, true)),\n )\n return recipes.sort((a, b) =>\n a.recipe.id.localeCompare(b.recipe.id) || compareVersions(b.recipe.version, a.recipe.version),\n )\n}\n\nfunction compareVersions(a: string, b: string): number {\n const av = a.split(\".\").map(Number)\n const bv = b.split(\".\").map(Number)\n for (let i = 0; i < 3; i++) {\n const difference = av[i]! - bv[i]!\n if (difference) return difference\n }\n return 0\n}\n\nfunction parseSelector(selector: string): { id: string; version?: string } {\n const match = selector.match(/^([^@]+?)(?:@(\\d+\\.\\d+\\.\\d+))?$/)\n if (!match || !RECIPE_ID_RE.test(match[1]!)) {\n throw new Error(`Invalid recipe selector \"${selector}\". Expected provider/name or provider/name@x.y.z.`)\n }\n return { id: match[1]!, version: match[2] }\n}\n\nexport async function resolveRecipe(\n target: string,\n bundledRoot = bundledRecipeRoot(),\n): Promise<LoadedRecipe> {\n const local = path.resolve(target)\n if (existsSync(local)) {\n const recipePath = path.basename(local) === RECIPE_FILE ? local : path.join(local, RECIPE_FILE)\n return readRecipeFile(recipePath, false)\n }\n if (target.startsWith(\".\") || target.startsWith(\"/\") || target.includes(\"\\\\\")) {\n throw new Error(`Recipe path not found: ${local}`)\n }\n const selector = parseSelector(target)\n const matches = (await listBundledRecipes(bundledRoot)).filter((entry) =>\n entry.recipe.id === selector.id &&\n (selector.version === undefined || entry.recipe.version === selector.version),\n )\n if (!matches.length) throw new Error(`Bundled recipe not found: ${target}`)\n return matches[0]!\n}\n\nasync function verifyFile(root: string, file: { path: string; sha256: string }): Promise<RecipeFileVerification> {\n const absolute = path.resolve(root, ...file.path.split(\"/\"))\n if (!existsSync(absolute)) {\n return { path: file.path, expectedSha256: file.sha256, actualSha256: null, status: \"missing\" }\n }\n const actualSha256 = await sha256File(absolute)\n return {\n path: file.path,\n expectedSha256: file.sha256,\n actualSha256,\n status: actualSha256 === file.sha256 ? \"ok\" : \"mismatch\",\n }\n}\n\nexport async function verifyRecipe(\n target: string,\n options: { modelRoot?: string; bundledRoot?: string } = {},\n): Promise<RecipeVerification> {\n const loaded = await resolveRecipe(target, options.bundledRoot)\n const actualIntegrity = recipeDigest(loaded.recipe)\n const files = await Promise.all(loaded.recipe.files.map((file) => verifyFile(loaded.dir, file)))\n const modelRoot = options.modelRoot ? path.resolve(options.modelRoot) : null\n const models: RecipeModelVerification[] = modelRoot\n ? await Promise.all(loaded.recipe.models.map(async (model) => ({\n ...await verifyFile(modelRoot, model),\n source: model.source,\n license: model.license,\n })))\n : loaded.recipe.models.map((model) => ({\n path: model.path,\n expectedSha256: model.sha256,\n actualSha256: null,\n source: model.source,\n license: model.license,\n status: \"unchecked\",\n }))\n const integrityStatus = actualIntegrity === loaded.recipe.integrity.digest ? \"ok\" : \"mismatch\"\n return {\n version: 1,\n ok:\n integrityStatus === \"ok\" &&\n files.every((file) => file.status === \"ok\") &&\n (!modelRoot || models.every((model) => model.status === \"ok\")),\n recipe: {\n id: loaded.recipe.id,\n version: loaded.recipe.version,\n path: loaded.path,\n bundled: loaded.bundled,\n },\n integrity: {\n expectedSha256: loaded.recipe.integrity.digest,\n actualSha256: actualIntegrity,\n status: integrityStatus,\n },\n files,\n models,\n modelRoot,\n }\n}\n\nfunction renderStyle(style: Style, destination: string, cwd: string): Style {\n const portableDir = path.relative(cwd, destination).split(path.sep).join(\"/\") || \".\"\n const replace = (value: unknown): unknown => {\n if (typeof value === \"string\") return value.replaceAll(RECIPE_DIR_TOKEN, portableDir)\n if (Array.isArray(value)) return value.map(replace)\n if (value && typeof value === \"object\") {\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, replace(item)]))\n }\n return value\n }\n return replace(style) as Style\n}\n\nexport async function installRecipe(\n target: string,\n options: InstallRecipeOptions = {},\n): Promise<InstallRecipeResult> {\n const cwd = path.resolve(options.cwd ?? process.cwd())\n const loaded = await resolveRecipe(target, options.bundledRoot)\n const verification = await verifyRecipe(loaded.path)\n if (!verification.ok) {\n throw new Error(`Recipe ${loaded.recipe.id}@${loaded.recipe.version} failed integrity verification.`)\n }\n const destination = options.out\n ? path.resolve(cwd, options.out)\n : path.join(cwd, \"pixelkiln-recipes\", ...loaded.recipe.id.split(\"/\"), loaded.recipe.version)\n const sources = [\n { path: RECIPE_FILE, source: loaded.path },\n ...loaded.recipe.files.map((file) => ({ path: file.path, source: path.join(loaded.dir, ...file.path.split(\"/\")) })),\n ]\n const files = await Promise.all(sources.map(async (file) => ({\n path: path.join(destination, ...file.path.split(\"/\")),\n data: await readFile(file.source),\n })))\n\n if (!options.force) {\n for (const file of files) {\n if (!existsSync(file.path)) continue\n const current = await readFile(file.path)\n if (!current.equals(file.data)) {\n throw new Error(\n `Recipe destination has local changes: ${file.path}. Choose another --out or pass --force to replace declared recipe files.`,\n )\n }\n }\n }\n\n const written = await writeArtifactBundle(files)\n const renderedStyle = renderStyle(loaded.recipe.style, destination, cwd)\n return {\n recipe: loaded.recipe,\n destination,\n changed: written.changed,\n unchanged: written.unchanged,\n styleId: loaded.recipe.styleId,\n // A recipe snippet should remain correct when pasted into a manifest whose\n // top-level default is another provider.\n style: { ...renderedStyle, provider: renderedStyle.provider ?? loaded.recipe.provider },\n }\n}\n","import path from \"node:path\"\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { z } from \"zod\"\nimport {\n readArtifactBundleManifest,\n verifyArtifactBundle,\n writeArtifactBundle,\n} from \"../artifacts.ts\"\nimport { sha256, sha256File } from \"../hash.ts\"\nimport { decodePng, type DecodedPng } from \"../png.ts\"\nimport { colorDistance } from \"./audit.ts\"\n\nconst SHA256_RE = /^[0-9a-f]{64}$/\nconst HEX_RE = /^#[0-9a-f]{6}$/\nconst MAX_REDMEAN_DISTANCE = 765\n\nconst QualityPathSchema = z.string().min(1).refine(\n (value) => !path.posix.isAbsolute(value) && !value.includes(\"\\\\\"),\n \"expected a portable relative path\",\n)\n\nexport const DEFAULT_QUALITY_TOLERANCES = {\n requireExactHash: false,\n maxColorCountIncrease: 0,\n maxNewColors: 0,\n maxTransparencyDelta: 0.01,\n maxPartialAlphaIncrease: 0,\n maxEdgeDensityDelta: 0.03,\n maxEdgeContrastDrop: 0.03,\n maxIsolatedPixelIncrease: 0.005,\n} as const\n\nexport const QualityToleranceSchema = z.object({\n requireExactHash: z.boolean(),\n maxColorCountIncrease: z.number().int().min(0),\n maxNewColors: z.number().int().min(0),\n maxTransparencyDelta: z.number().min(0).max(1),\n maxPartialAlphaIncrease: z.number().min(0).max(1),\n maxEdgeDensityDelta: z.number().min(0).max(1),\n maxEdgeContrastDrop: z.number().min(0).max(1),\n maxIsolatedPixelIncrease: z.number().min(0).max(1),\n}).strict()\n\nexport type QualityTolerances = z.infer<typeof QualityToleranceSchema>\n\nexport const ImageQualityMetricsSchema = z.object({\n sha256: z.string().regex(SHA256_RE),\n width: z.number().int().min(1),\n height: z.number().int().min(1),\n colorCount: z.number().int().min(0),\n colors: z.array(z.string().regex(HEX_RE)),\n transparency: z.number().min(0).max(1),\n partialAlpha: z.number().min(0).max(1),\n edgeDensity: z.number().min(0).max(1),\n meanEdgeContrast: z.number().min(0).max(1),\n isolatedPixelRatio: z.number().min(0).max(1),\n}).strict()\n\nexport type ImageQualityMetrics = z.infer<typeof ImageQualityMetricsSchema>\n\nconst QualityBaselineCaseSchema = z.object({\n id: z.string().regex(/^[a-z0-9][a-z0-9/_-]*$/),\n file: QualityPathSchema,\n record: z.object({\n path: QualityPathSchema,\n sha256: z.string().regex(SHA256_RE),\n }).strict().optional(),\n expected: ImageQualityMetricsSchema,\n tolerances: QualityToleranceSchema,\n}).strict()\n\nexport const QualityBaselineSchema = z.object({\n $schema: z.string().url().optional(),\n format: z.literal(\"pixelkiln-quality-baseline\"),\n schemaVersion: z.literal(1),\n cases: z.array(QualityBaselineCaseSchema).min(1),\n}).strict().superRefine((baseline, context) => {\n const ids = baseline.cases.map((entry) => entry.id)\n if (new Set(ids).size !== ids.length) {\n context.addIssue({ code: z.ZodIssueCode.custom, path: [\"cases\"], message: \"duplicate case id\" })\n }\n})\n\nexport type QualityBaseline = z.infer<typeof QualityBaselineSchema>\n\nconst QualityInputSchema = z.object({\n id: z.string().regex(/^[a-z0-9][a-z0-9/_-]*$/),\n path: z.string().min(1),\n record: z.string().min(1).optional(),\n tolerances: QualityToleranceSchema.partial().optional(),\n}).strict()\n\nexport interface ResolvedQualityInput {\n id: string\n file: string\n record?: string\n tolerances: QualityTolerances\n}\n\nexport interface QualitySnapshotResult {\n baseline: QualityBaseline\n path: string\n changed: boolean\n}\n\nexport interface QualityRegressionCaseResult {\n id: string\n file: string\n status: \"pass\" | \"fail\"\n hashChanged: boolean\n expected: ImageQualityMetrics\n actual: ImageQualityMetrics | null\n violations: string[]\n warnings: string[]\n}\n\nexport interface QualityRegressionReport {\n version: 1\n safe: boolean\n baseline: string\n summary: {\n total: number\n passed: number\n failed: number\n changed: number\n }\n cases: QualityRegressionCaseResult[]\n}\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction round(value: number): number {\n return Number(value.toFixed(6))\n}\n\nfunction pixelKey(pixels: Buffer, offset: number): number {\n const alpha = pixels[offset + 3]!\n if (alpha === 0) return 0\n return (\n ((pixels[offset]! << 24) >>> 0) |\n (pixels[offset + 1]! << 16) |\n (pixels[offset + 2]! << 8) |\n alpha\n ) >>> 0\n}\n\nfunction edgeContrast(pixels: Buffer, a: number, b: number): number {\n const alphaA = pixels[a + 3]!\n const alphaB = pixels[b + 3]!\n const alphaDistance = Math.abs(alphaA - alphaB) / 255\n if (alphaA === 0 || alphaB === 0) return alphaDistance\n const rgbDistance = colorDistance(\n { r: pixels[a]!, g: pixels[a + 1]!, b: pixels[a + 2]! },\n { r: pixels[b]!, g: pixels[b + 1]!, b: pixels[b + 2]! },\n ) / MAX_REDMEAN_DISTANCE\n return Math.min(1, Math.max(alphaDistance, rgbDistance))\n}\n\nexport function measureDecodedImageQuality(\n png: DecodedPng,\n digest: string,\n): ImageQualityMetrics {\n const colors = new Set<number>()\n let transparent = 0\n let partialAlpha = 0\n let visible = 0\n let isolated = 0\n\n for (let offset = 0; offset < png.pixels.length; offset += 4) {\n const alpha = png.pixels[offset + 3]!\n if (alpha === 0) {\n transparent++\n continue\n }\n visible++\n if (alpha < 255) partialAlpha++\n colors.add((png.pixels[offset]! << 16) | (png.pixels[offset + 1]! << 8) | png.pixels[offset + 2]!)\n\n const index = offset / 4\n const x = index % png.width\n const y = Math.floor(index / png.width)\n const key = pixelKey(png.pixels, offset)\n const hasSameNeighbor =\n (x > 0 && pixelKey(png.pixels, offset - 4) === key) ||\n (x + 1 < png.width && pixelKey(png.pixels, offset + 4) === key) ||\n (y > 0 && pixelKey(png.pixels, offset - png.width * 4) === key) ||\n (y + 1 < png.height && pixelKey(png.pixels, offset + png.width * 4) === key)\n if (!hasSameNeighbor) {\n isolated++\n }\n }\n\n let neighborPairs = 0\n let changedPairs = 0\n let contrastTotal = 0\n for (let y = 0; y < png.height; y++) {\n for (let x = 0; x < png.width; x++) {\n const offset = (y * png.width + x) * 4\n if (x + 1 < png.width) {\n const neighbor = offset + 4\n neighborPairs++\n if (pixelKey(png.pixels, offset) !== pixelKey(png.pixels, neighbor)) {\n changedPairs++\n contrastTotal += edgeContrast(png.pixels, offset, neighbor)\n }\n }\n if (y + 1 < png.height) {\n const neighbor = offset + png.width * 4\n neighborPairs++\n if (pixelKey(png.pixels, offset) !== pixelKey(png.pixels, neighbor)) {\n changedPairs++\n contrastTotal += edgeContrast(png.pixels, offset, neighbor)\n }\n }\n }\n }\n\n const total = png.width * png.height\n return {\n sha256: digest,\n width: png.width,\n height: png.height,\n colorCount: colors.size,\n colors: [...colors]\n .sort((a, b) => a - b)\n .map((color) => `#${color.toString(16).padStart(6, \"0\")}`),\n transparency: round(total ? transparent / total : 0),\n partialAlpha: round(total ? partialAlpha / total : 0),\n edgeDensity: round(neighborPairs ? changedPairs / neighborPairs : 0),\n meanEdgeContrast: round(changedPairs ? contrastTotal / changedPairs : 0),\n isolatedPixelRatio: round(visible ? isolated / visible : 0),\n }\n}\n\nexport async function measureImageQuality(file: string): Promise<ImageQualityMetrics> {\n const absolute = path.resolve(file)\n let bytes: Buffer\n try {\n bytes = await readFile(absolute)\n } catch (error) {\n throw new Error(`Cannot read quality image ${absolute}: ${message(error)}`, { cause: error })\n }\n try {\n return measureDecodedImageQuality(decodePng(bytes), sha256(bytes))\n } catch (error) {\n throw new Error(`Cannot measure quality image ${absolute}: ${message(error)}`, { cause: error })\n }\n}\n\nexport function resolveQualityInputs(raw: unknown, inputsFilePath: string): ResolvedQualityInput[] {\n const parsed = z.array(QualityInputSchema).min(1).safeParse(raw)\n if (!parsed.success) {\n throw new Error(\n \"--inputs must be a non-empty JSON array of quality cases:\\n\" +\n parsed.error.issues.map((issue) => ` ${issue.path.join(\".\") || \"$\"}: ${issue.message}`).join(\"\\n\"),\n )\n }\n const ids = parsed.data.map((entry) => entry.id)\n if (new Set(ids).size !== ids.length) throw new Error(\"--inputs contains a duplicate quality case id.\")\n const root = path.dirname(path.resolve(inputsFilePath))\n return parsed.data.map((entry) => ({\n id: entry.id,\n file: path.resolve(root, entry.path),\n ...(entry.record ? { record: path.resolve(root, entry.record) } : {}),\n tolerances: QualityToleranceSchema.parse({\n ...DEFAULT_QUALITY_TOLERANCES,\n ...entry.tolerances,\n }),\n }))\n}\n\nfunction portableRelative(from: string, to: string): string {\n return path.relative(from, path.resolve(to)).split(path.sep).join(\"/\") || \".\"\n}\n\nasync function verifyRecordForImage(recordPath: string, imagePath: string): Promise<void> {\n const verification = await verifyArtifactBundle(recordPath)\n if (!verification.current) {\n const changed = [...verification.changedSources, ...verification.changedOutputs]\n throw new Error(\n `Quality record is not current: ${recordPath}` +\n (changed.length ? ` (${changed.join(\", \")})` : \"\"),\n )\n }\n const record = await readArtifactBundleManifest(recordPath)\n const options = record.options\n if (\n record.kind !== \"refine\" ||\n options === null ||\n typeof options !== \"object\" ||\n (options as { schema?: unknown }).schema !== \"pixelkiln-quality\"\n ) {\n throw new Error(`Quality record ${recordPath} is not a PixelKiln refinement record.`)\n }\n const outputs = record.outputs.map((output) => path.resolve(path.dirname(recordPath), output.path))\n if (!outputs.includes(path.resolve(imagePath))) {\n throw new Error(`Quality record ${recordPath} does not own ${imagePath}.`)\n }\n}\n\nexport async function snapshotQualityBaseline(\n inputs: ResolvedQualityInput[],\n baselinePath: string,\n options: { force?: boolean } = {},\n): Promise<QualitySnapshotResult> {\n if (!inputs.length) throw new Error(\"Cannot snapshot an empty quality baseline.\")\n const absolute = path.resolve(baselinePath)\n for (const input of inputs) {\n if (\n path.resolve(input.file) === absolute ||\n (input.record && path.resolve(input.record) === absolute)\n ) {\n throw new Error(`Quality baseline output would overwrite an input: ${absolute}.`)\n }\n }\n const root = path.dirname(absolute)\n const cases = []\n for (const input of [...inputs].sort((a, b) => a.id.localeCompare(b.id))) {\n const expected = await measureImageQuality(input.file)\n let record: { path: string; sha256: string } | undefined\n if (input.record) {\n await verifyRecordForImage(input.record, input.file)\n record = {\n path: portableRelative(root, input.record),\n sha256: await sha256File(input.record),\n }\n }\n cases.push({\n id: input.id,\n file: portableRelative(root, input.file),\n ...(record ? { record } : {}),\n expected,\n tolerances: input.tolerances,\n })\n }\n const baseline = QualityBaselineSchema.parse({\n $schema: \"https://unpkg.com/pixelkiln/schema/quality-baseline.schema.json\",\n format: \"pixelkiln-quality-baseline\",\n schemaVersion: 1,\n cases,\n })\n const data = Buffer.from(JSON.stringify(baseline, null, 2) + \"\\n\")\n if (existsSync(absolute) && !options.force) {\n const current = await readFile(absolute)\n if (!current.equals(data)) {\n throw new Error(`Quality baseline already exists with different content: ${absolute}. Pass --force to replace it.`)\n }\n }\n const result = await writeArtifactBundle([{ path: absolute, data }])\n return { baseline, path: absolute, changed: result.changed.length > 0 }\n}\n\nexport async function readQualityBaseline(baselinePath: string): Promise<QualityBaseline> {\n const absolute = path.resolve(baselinePath)\n let raw: unknown\n try {\n raw = JSON.parse(await readFile(absolute, \"utf8\"))\n } catch (error) {\n throw new Error(`Could not read quality baseline ${absolute}: ${message(error)}`, { cause: error })\n }\n const parsed = QualityBaselineSchema.safeParse(raw)\n if (!parsed.success) {\n throw new Error(\n `Invalid quality baseline ${absolute}:\\n` +\n parsed.error.issues.map((issue) => ` ${issue.path.join(\".\") || \"$\"}: ${issue.message}`).join(\"\\n\"),\n )\n }\n return parsed.data\n}\n\nfunction regressionViolations(\n expected: ImageQualityMetrics,\n actual: ImageQualityMetrics,\n tolerances: QualityTolerances,\n): { violations: string[]; warnings: string[] } {\n const violations: string[] = []\n const warnings: string[] = []\n const changed = actual.sha256 !== expected.sha256\n if (expected.width !== actual.width || expected.height !== actual.height) {\n violations.push(\n `dimensions changed from ${expected.width}x${expected.height} to ${actual.width}x${actual.height}`,\n )\n }\n if (changed && tolerances.requireExactHash) violations.push(\"image hash changed\")\n else if (changed) warnings.push(\"image hash changed; metric tolerances decide this case\")\n\n const colorIncrease = actual.colorCount - expected.colorCount\n if (colorIncrease > tolerances.maxColorCountIncrease) {\n violations.push(\n `color count increased by ${colorIncrease} (allowed ${tolerances.maxColorCountIncrease})`,\n )\n }\n const expectedColors = new Set(expected.colors)\n const newColors = actual.colors.filter((color) => !expectedColors.has(color))\n if (newColors.length > tolerances.maxNewColors) {\n violations.push(\n `${newColors.length} new color(s) exceed ${tolerances.maxNewColors}: ${newColors.slice(0, 8).join(\", \")}`,\n )\n }\n const transparencyDelta = Math.abs(actual.transparency - expected.transparency)\n if (transparencyDelta > tolerances.maxTransparencyDelta) {\n violations.push(\n `transparency changed by ${(transparencyDelta * 100).toFixed(2)} points ` +\n `(allowed ${(tolerances.maxTransparencyDelta * 100).toFixed(2)})`,\n )\n }\n const partialAlphaIncrease = actual.partialAlpha - expected.partialAlpha\n if (partialAlphaIncrease > tolerances.maxPartialAlphaIncrease) {\n violations.push(\n `partial-alpha pixels increased by ${(partialAlphaIncrease * 100).toFixed(2)} points ` +\n `(allowed ${(tolerances.maxPartialAlphaIncrease * 100).toFixed(2)})`,\n )\n }\n const edgeDensityDelta = Math.abs(actual.edgeDensity - expected.edgeDensity)\n if (edgeDensityDelta > tolerances.maxEdgeDensityDelta) {\n violations.push(\n `edge density changed by ${(edgeDensityDelta * 100).toFixed(2)} points ` +\n `(allowed ${(tolerances.maxEdgeDensityDelta * 100).toFixed(2)})`,\n )\n }\n const edgeContrastDrop = expected.meanEdgeContrast - actual.meanEdgeContrast\n if (edgeContrastDrop > tolerances.maxEdgeContrastDrop) {\n violations.push(\n `mean edge contrast dropped by ${(edgeContrastDrop * 100).toFixed(2)} points ` +\n `(allowed ${(tolerances.maxEdgeContrastDrop * 100).toFixed(2)})`,\n )\n }\n const isolatedIncrease = actual.isolatedPixelRatio - expected.isolatedPixelRatio\n if (isolatedIncrease > tolerances.maxIsolatedPixelIncrease) {\n violations.push(\n `isolated-pixel ratio increased by ${(isolatedIncrease * 100).toFixed(2)} points ` +\n `(allowed ${(tolerances.maxIsolatedPixelIncrease * 100).toFixed(2)})`,\n )\n }\n return { violations, warnings }\n}\n\nexport async function checkQualityBaseline(baselinePath: string): Promise<QualityRegressionReport> {\n const absolute = path.resolve(baselinePath)\n const baseline = await readQualityBaseline(absolute)\n const root = path.dirname(absolute)\n const cases: QualityRegressionCaseResult[] = []\n\n for (const entry of baseline.cases) {\n const file = path.resolve(root, entry.file)\n let actual: ImageQualityMetrics | null = null\n const violations: string[] = []\n const warnings: string[] = []\n try {\n actual = await measureImageQuality(file)\n const regression = regressionViolations(entry.expected, actual, entry.tolerances)\n violations.push(...regression.violations)\n warnings.push(...regression.warnings)\n } catch (error) {\n violations.push(message(error))\n }\n\n if (entry.record) {\n const recordPath = path.resolve(root, entry.record.path)\n try {\n const recordHash = await sha256File(recordPath)\n if (recordHash !== entry.record.sha256) violations.push(\"quality record hash changed\")\n await verifyRecordForImage(recordPath, file)\n } catch (error) {\n violations.push(message(error))\n }\n }\n\n cases.push({\n id: entry.id,\n file,\n status: violations.length ? \"fail\" : \"pass\",\n hashChanged: actual !== null && actual.sha256 !== entry.expected.sha256,\n expected: entry.expected,\n actual,\n violations,\n warnings,\n })\n }\n\n const failed = cases.filter((entry) => entry.status === \"fail\").length\n return {\n version: 1,\n safe: failed === 0,\n baseline: absolute,\n summary: {\n total: cases.length,\n passed: cases.length - failed,\n failed,\n changed: cases.filter((entry) => entry.hashChanged).length,\n },\n cases,\n }\n}\n"],"mappings":";;;AACA,OAAOA,YAAU;AACjB,SAAS,cAAAC,oBAAkB;AAC3B,SAAS,YAAAC,kBAAgB;;;ACHzB,SAAS,cAAc,kBAAkB;AACzC,OAAO,UAAU;AAYV,SAAS,aAAa,KAAuB;AAClD,QAAM,SAAmB,CAAC;AAI1B,aAAW,QAAQ,CAAC,cAAc,MAAM,GAAG;AACzC,UAAM,OAAO,KAAK,KAAK,KAAK,IAAI;AAChC,QAAI,CAAC,WAAW,IAAI,EAAG;AACvB,QAAI;AACF,eAAS,aAAa,MAAM,MAAM,CAAC;AACnC,aAAO,KAAK,IAAI;AAAA,IAClB,QAAQ;AAAA,IAGR;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,SAAS,UAAwB;AACxC,aAAW,WAAW,SAAS,MAAM,IAAI,GAAG;AAC1C,UAAM,OAAO,QAAQ,KAAK;AAC1B,QAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,EAAG;AAEnC,UAAM,KAAK,KAAK,QAAQ,GAAG;AAC3B,QAAI,MAAM,EAAG;AAEb,UAAM,MAAM,KAAK,MAAM,GAAG,EAAE,EAAE,QAAQ,cAAc,EAAE,EAAE,KAAK;AAC7D,QAAI,CAAC,OAAO,OAAO,QAAQ,IAAK;AAEhC,QAAI,QAAQ,KAAK,MAAM,KAAK,CAAC,EAAE,KAAK;AAEpC,UAAM,QAAQ,MAAM,CAAC;AACrB,SAAK,UAAU,OAAO,UAAU,QAAQ,MAAM,SAAS,KAAK,KAAK,MAAM,UAAU,GAAG;AAClF,cAAQ,MAAM,MAAM,GAAG,EAAE;AAAA,IAC3B;AACA,YAAQ,IAAI,GAAG,IAAI;AAAA,EACrB;AACF;;;AC3BO,SAAS,qBAAqB,YAAoB,OAA8B;AACrF,MAAI,CAAC,SAAS,OAAO,UAAU,UAAU;AACvC,UAAM,IAAI,MAAM,aAAa,UAAU,qCAAqC;AAAA,EAC9E;AACA,QAAM,WAAW;AACjB,MAAI,OAAO,SAAS,SAAS,YAAY,CAAC,SAAS,KAAK,KAAK,GAAG;AAC9D,UAAM,IAAI,MAAM,aAAa,UAAU,iCAAiC;AAAA,EAC1E;AACA,MAAI,CAAC,OAAO,SAAS,SAAS,MAAM,KAAK,SAAS,SAAU,GAAG;AAC7D,UAAM,IAAI,MAAM,aAAa,UAAU,mCAAmC;AAAA,EAC5E;AACA,MAAI,SAAS,SAAS,UAAU,SAAS,WAAW,GAAG;AACrD,UAAM,IAAI,MAAM,aAAa,UAAU,qDAAqD;AAAA,EAC9F;AACA,MAAI,CAAC,OAAO,UAAU,SAAS,UAAU,KAAK,SAAS,aAAc,GAAG;AACtE,UAAM,IAAI,MAAM,aAAa,UAAU,uCAAuC;AAAA,EAChF;AACA,SAAO;AACT;AAqHO,SAAS,qBACd,QACA,OACsB;AACtB,MACE,OAAO,SAAS,MAAM,QACtB,CAAC,OAAO,SAAS,OAAO,SAAS,KACjC,CAAC,OAAO,SAAS,MAAM,SAAS,EAChC,QAAO;AACT,QAAM,QAAQ,OAAO,YAAY,MAAM;AACvC,SAAO;AAAA,IACL,MAAM,OAAO;AAAA,IACb,QAAQ,OAAO;AAAA,IACf,OAAO,MAAM;AAAA,IACb,OAAO,KAAK,IAAI,GAAG,KAAK;AAAA,IACxB,UAAU,KAAK,IAAI,GAAG,CAAC,KAAK;AAAA,EAC9B;AACF;AAkBO,IAAM,qBAAgC,EAAE,WAAW,MAAM,aAAa,EAAE;AA0FxE,IAAM,6BAAN,cAAyC,MAAM;AAAA,EACpD,YAAY,YAAoB,YAAoB;AAClD;AAAA,MACE,aAAa,UAAU,sBAAsB,UAAU;AAAA,IAEzD;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAGO,SAAS,YAAY,UAAmD;AAC7E,MAAI,CAAC,SAAS,KAAM,OAAM,IAAI,2BAA2B,SAAS,IAAI,uBAAuB;AAC7F,SAAO,SAAS,KAAK,KAAK,QAAQ;AACpC;AAEO,SAAS,cAAc,UAAqD;AACjF,MAAI,CAAC,SAAS,OAAQ,OAAM,IAAI,2BAA2B,SAAS,IAAI,wBAAwB;AAChG,SAAO,SAAS,OAAO,KAAK,QAAQ;AACtC;AAEO,SAAS,uBACd,UAC0C;AAC1C,MAAI,CAAC,SAAS,iBAAiB;AAC7B,UAAM,IAAI,2BAA2B,SAAS,IAAI,qBAAqB;AAAA,EACzE;AACA,SAAO,SAAS,gBAAgB,KAAK,QAAQ;AAC/C;AAEO,SAAS,eAAe,UAAsD;AACnF,MAAI,CAAC,SAAS,QAAS,OAAM,IAAI,2BAA2B,SAAS,IAAI,iBAAiB;AAC1F,SAAO,SAAS,QAAQ,KAAK,QAAQ;AACvC;AAEO,SAAS,WAAW,MAAgB,QAAwB;AACjE,MAAI,SAAS,OAAQ,QAAO;AAC5B,MAAI,SAAS,MAAO,QAAO,IAAI,OAAO,QAAQ,CAAC,CAAC;AAChD,MAAI,SAAS,cAAe,QAAO,GAAG,MAAM,cAAc,WAAW,IAAI,KAAK,GAAG;AACjF,SAAO,GAAG,MAAM,IAAI,IAAI;AAC1B;;;ACpUA,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AACzB,OAAOC,WAAU;;;ACFjB,SAAS,kBAAkB;AAC3B,SAAS,wBAAwB;AAG1B,SAAS,OAAO,MAA+B;AACpD,SAAO,WAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AACvD;AAEA,eAAsB,WAAWC,QAA+B;AAC9D,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,OAAO,WAAW,QAAQ;AAChC,UAAM,SAAS,iBAAiBA,MAAI;AACpC,WAAO,GAAG,QAAQ,CAACC,WAAU,KAAK,OAAOA,MAAK,CAAC;AAC/C,WAAO,GAAG,SAAS,MAAM;AACzB,WAAO,GAAG,OAAO,MAAM,QAAQ,KAAK,OAAO,KAAK,CAAC,CAAC;AAAA,EACpD,CAAC;AACH;AAeO,SAAS,SACd,MACA,kBACA,yBAAkC,KAAK,iBACvC,wBAAiC,KAAK,kBAAkB,CAAC,GACjD;AACR,SAAO;AAAA,IACL,KAAK,UAAU;AAAA;AAAA;AAAA,MAGb,UAAU,KAAK,aAAa,aAAa,SAAY,KAAK;AAAA,MAC1D,iBACE,2BACC,OAAO,2BAA2B,YAAY,OAAO,KAAK,sBAAsB,EAAE,SAAS,KACxF,yBACA;AAAA,MACN,gBACE,0BACC,OAAO,0BAA0B,YAAY,OAAO,KAAK,qBAAqB,EAAE,SAAS,KACtF,wBACA;AAAA,MACN,WAAW,KAAK;AAAA,MAChB,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,SAAS,KAAK,WAAW;AAAA,MACzB,SAAS,KAAK,WAAW;AAAA,MACzB,QAAQ,KAAK,UAAU;AAAA,MACvB,MAAM,KAAK,QAAQ;AAAA,MACnB,SAAS,KAAK;AAAA;AAAA;AAAA;AAAA,MAId,cACE,KAAK,cAAc,aAAa,KAAK,aAAa,aAC9C,KAAK,eACL;AAAA,MACN,UAAU,KAAK;AAAA,MACf,UAAU,KAAK;AAAA,MACf,aAAa,KAAK;AAAA,MAClB,aAAa,KAAK;AAAA,MAClB,aAAa;AAAA,MACb,UAAU,KAAK,WACX;AAAA,QACE,MAAM,KAAK,SAAS;AAAA,QACpB,MAAM,KAAK,SAAS;AAAA,QACpB,cAAc,KAAK,SAAS;AAAA,QAC5B,YAAY,KAAK,SAAS;AAAA,QAC1B,UAAU,KAAK,SAAS;AAAA,MAC1B,IACA;AAAA,IACN,CAAC;AAAA,EACH;AACF;;;ACrFA,SAAS,aAAa,mBAAmB;AASzC,IAAM,YAAY,OAAO,KAAK,CAAC,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,EAAI,CAAC;AAC9E,IAAM,oBAAoB,MAAM,OAAO;AAUvC,IAAM,WAAW,oBAAI,IAAI;AAAA,EACvB,CAAC,GAAG,CAAC;AAAA;AAAA,EACL,CAAC,GAAG,CAAC;AAAA;AAAA,EACL,CAAC,GAAG,CAAC;AAAA;AAAA,EACL,CAAC,GAAG,CAAC;AAAA;AAAA,EACL,CAAC,GAAG,CAAC;AAAA;AACP,CAAC;AAED,IAAM,eAAe,oBAAI,IAAyB;AAAA,EAChD,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC;AAAA,EAC7B,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AAAA,EACpB,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;AAAA,EACzB,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AAAA,EACpB,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AACtB,CAAC;AAUM,SAAS,UAAU,KAAyB;AACjD,MAAI,IAAI,SAAS,KAAK,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,OAAO,SAAS,GAAG;AAC3D,UAAM,IAAI,MAAM,WAAW;AAAA,EAC7B;AAEA,MAAI,SAA2B;AAC/B,MAAI,UAAyB;AAC7B,MAAI,eAA8B;AAClC,MAAI,eAAe;AACnB,MAAI,SAAS;AACb,QAAM,OAAiB,CAAC;AAExB,MAAI,SAAS;AACb,SAAO,SAAS,IAAI,QAAQ;AAC1B,QAAI,SAAS,KAAK,IAAI,OAAQ,OAAM,IAAI,MAAM,4BAA4B;AAC1E,UAAM,SAAS,IAAI,aAAa,MAAM;AACtC,UAAM,OAAO,IAAI,SAAS,SAAS,SAAS,GAAG,SAAS,CAAC;AACzD,QAAI,CAAC,gBAAgB,KAAK,IAAI,KAAK,QAAQ,KAAK,KAAK,CAAC,CAAE,GAAG;AACzD,YAAM,IAAI,MAAM,iCAAiC,KAAK,UAAU,IAAI,CAAC,EAAE;AAAA,IACzE;AACA,UAAM,MAAM,SAAS,KAAK;AAC1B,QAAI,CAAC,OAAO,cAAc,GAAG,KAAK,MAAM,IAAI,QAAQ;AAClD,YAAM,IAAI,MAAM,uBAAuB,QAAQ,WAAW,EAAE;AAAA,IAC9D;AACA,UAAM,OAAO,IAAI,SAAS,SAAS,GAAG,SAAS,IAAI,MAAM;AACzD,UAAM,cAAc,IAAI,aAAa,SAAS,IAAI,MAAM;AACxD,UAAM,YAAY,MAAM,IAAI,SAAS,SAAS,GAAG,SAAS,IAAI,MAAM,CAAC,MAAM;AAC3E,QAAI,cAAc,YAAa,OAAM,IAAI,MAAM,aAAa,IAAI,0BAA0B;AAE1F,QAAI,CAAC,UAAU,SAAS,OAAQ,OAAM,IAAI,MAAM,uCAAuC;AAEvF,QAAI,SAAS,QAAQ;AACnB,UAAI,OAAQ,OAAM,IAAI,MAAM,kCAAkC;AAC9D,UAAI,KAAK,WAAW,GAAI,OAAM,IAAI,MAAM,+BAA+B;AACvE,YAAM,QAAQ,KAAK,aAAa,CAAC;AACjC,YAAM,SAAS,KAAK,aAAa,CAAC;AAClC,YAAM,WAAW,KAAK,CAAC;AACvB,YAAM,YAAY,KAAK,CAAC;AACxB,YAAM,WAAW,SAAS,IAAI,SAAS;AACvC,UAAI,CAAC,SAAS,CAAC,OAAQ,OAAM,IAAI,MAAM,iCAAiC;AACxE,UAAI,CAAC,YAAY,CAAC,aAAa,IAAI,SAAS,GAAG,IAAI,QAAQ,GAAG;AAC5D,cAAM,IAAI,MAAM,6BAA6B,QAAQ,cAAc,SAAS,EAAE;AAAA,MAChF;AACA,UAAI,KAAK,EAAE,MAAM,EAAG,OAAM,IAAI,MAAM,sCAAsC,KAAK,EAAE,CAAC,EAAE;AACpF,UAAI,KAAK,EAAE,MAAM,EAAG,OAAM,IAAI,MAAM,iCAAiC,KAAK,EAAE,CAAC,EAAE;AAC/E,UAAI,KAAK,EAAE,MAAM,EAAG,OAAM,IAAI,MAAM,6BAA6B;AACjE,eAAS,EAAE,OAAO,QAAQ,UAAU,WAAW,SAAS;AAAA,IAC1D,WAAW,SAAS,QAAQ;AAC1B,UAAI,aAAc,OAAM,IAAI,MAAM,sCAAsC;AACxE,UAAI,QAAS,OAAM,IAAI,MAAM,+BAA+B;AAC5D,UAAI,CAAC,KAAK,UAAU,KAAK,SAAS,MAAM,KAAK,KAAK,SAAS,MAAM,GAAG;AAClE,cAAM,IAAI,MAAM,4BAA4B;AAAA,MAC9C;AACA,gBAAU,OAAO,KAAK,IAAI;AAAA,IAC5B,WAAW,SAAS,QAAQ;AAC1B,UAAI,aAAc,OAAM,IAAI,MAAM,2CAA2C;AAC7E,UAAI,aAAc,OAAM,IAAI,MAAM,0CAA0C;AAC5E,qBAAe,OAAO,KAAK,IAAI;AAAA,IACjC,WAAW,SAAS,QAAQ;AAC1B,qBAAe;AACf,WAAK,KAAK,IAAI;AAAA,IAChB,WAAW,SAAS,QAAQ;AAC1B,UAAI,KAAK,WAAW,EAAG,OAAM,IAAI,MAAM,+BAA+B;AACtE,eAAS;AACT;AAAA,IACF,WAAW,SAAS,KAAK,IAAI,GAAG;AAC9B,YAAM,IAAI,MAAM,kCAAkC,IAAI,EAAE;AAAA,IAC1D;AACA,aAAS;AAAA,EACX;AAEA,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,yBAAyB;AACtD,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,uBAAuB;AACpD,MAAI,CAAC,KAAK,OAAQ,OAAM,IAAI,MAAM,uBAAuB;AACzD,kBAAgB,QAAQ,OAAO;AAC/B,uBAAqB,OAAO,WAAW,cAAc,OAAO;AAE5D,QAAM,eAAe,OAAO,WAAW,OAAO;AAC9C,QAAM,SAAS,KAAK,KAAM,OAAO,QAAQ,eAAgB,CAAC;AAC1D,QAAM,aAAa,SAAS,KAAK,OAAO;AACxC,QAAM,aAAa,OAAO,QAAQ,OAAO,SAAS;AAClD,MACE,CAAC,OAAO,cAAc,SAAS,KAC/B,CAAC,OAAO,cAAc,UAAU,KAChC,YAAY,qBACZ,aAAa,mBACb;AACA,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEA,MAAI;AACJ,MAAI;AACF,UAAM,YAAY,OAAO,OAAO,IAAI,GAAG,EAAE,iBAAiB,UAAU,CAAC;AAAA,EACvE,SAAS,KAAK;AACZ,UAAM,IAAI,MAAM,2BAA2B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,EAC/F;AACA,MAAI,IAAI,WAAW,WAAW;AAC5B,UAAM,IAAI,MAAM,2CAA2C,SAAS,SAAS,IAAI,MAAM,EAAE;AAAA,EAC3F;AAEA,QAAM,cAAc,KAAK,IAAI,GAAG,KAAK,KAAK,eAAe,CAAC,CAAC;AAC3D,QAAM,UAAU,SAAS,KAAK,QAAQ,OAAO,QAAQ,WAAW;AAChE,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd,QAAQ,OAAO;AAAA,IACf,QAAQ,OAAO,SAAS,QAAQ,QAAQ,SAAS,YAAY;AAAA,EAC/D;AACF;AAEA,SAAS,gBAAgB,QAAmB,SAA8B;AACxE,MAAI,OAAO,cAAc,KAAK,CAAC,QAAS,OAAM,IAAI,MAAM,4BAA4B;AACpF,OAAK,OAAO,cAAc,KAAK,OAAO,cAAc,MAAM,SAAS;AACjE,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,MAAI,OAAO,cAAc,KAAK,WAAW,QAAQ,SAAS,IAAI,KAAK,OAAO,UAAU;AAClF,UAAM,IAAI,MAAM,iEAAiE;AAAA,EACnF;AACF;AAMA,SAAS,SAAS,KAAa,QAAgB,QAAgB,KAAqB;AAClF,QAAM,MAAM,OAAO,MAAM,SAAS,MAAM;AAExC,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,UAAM,SAAS,IAAI,KAAK,SAAS,EAAE;AACnC,UAAM,MAAM,IAAI,SAAS,KAAK,SAAS,KAAK,GAAG,KAAK,SAAS,KAAK,IAAI,MAAM;AAC5E,UAAM,MAAM,IAAI,SAAS,IAAI,SAAS,IAAI,KAAK,MAAM;AACrD,UAAM,OAAO,IAAI,IAAI,IAAI,UAAU,IAAI,KAAK,QAAQ,IAAI,MAAM,IAAI;AAElE,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,YAAM,IAAI,KAAK,MAAM,IAAI,IAAI,GAAG,IAAK;AACrC,YAAM,IAAI,OAAO,KAAK,CAAC,IAAK;AAC5B,YAAM,IAAI,QAAQ,KAAK,MAAM,KAAK,IAAI,GAAG,IAAK;AAC9C,YAAM,IAAI,IAAI,CAAC;AACf,cAAQ,QAAQ;AAAA,QACd,KAAK;AAAG,cAAI,CAAC,IAAI;AAAG;AAAA,QACpB,KAAK;AAAG,cAAI,CAAC,IAAK,IAAI,IAAK;AAAM;AAAA,QACjC,KAAK;AAAG,cAAI,CAAC,IAAK,IAAI,IAAK;AAAM;AAAA,QACjC,KAAK;AAAG,cAAI,CAAC,IAAK,KAAM,IAAI,KAAM,KAAM;AAAM;AAAA,QAC9C,KAAK;AAAG,cAAI,CAAC,IAAK,IAAI,MAAM,GAAG,GAAG,CAAC,IAAK;AAAM;AAAA,QAC9C;AAAS,gBAAM,IAAI,MAAM,sBAAsB,MAAM,WAAW,CAAC,EAAE;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,qBACP,WACA,cACA,SACM;AACN,MAAI,CAAC,aAAc;AACnB,MAAI,cAAc,KAAK,aAAa,WAAW,GAAG;AAChD,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AACA,MAAI,cAAc,KAAK,aAAa,WAAW,GAAG;AAChD,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AACA,MAAI,cAAc,KAAK,aAAa,UAAU,SAAS,UAAU,KAAK,GAAG;AACvE,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,MAAI,cAAc,KAAK,cAAc,GAAG;AACtC,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACtE;AACF;AAEA,SAAS,OACP,SACA,QACA,QACA,SACA,cACQ;AACR,QAAM,MAAM,OAAO,MAAM,OAAO,QAAQ,OAAO,SAAS,CAAC;AACzD,QAAM,kBAAkB,OAAO,cAAc,KAAK,eAC9C,aAAa,aAAa,CAAC,IAC3B;AACJ,QAAM,iBAAiB,OAAO,cAAc,KAAK,eAC7C;AAAA,IACE,aAAa,aAAa,CAAC;AAAA,IAC3B,aAAa,aAAa,CAAC;AAAA,IAC3B,aAAa,aAAa,CAAC;AAAA,EAC7B,IACA;AAEJ,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,UAAM,MAAM,QAAQ,SAAS,IAAI,SAAS,IAAI,KAAK,MAAM;AACzD,aAAS,IAAI,GAAG,IAAI,OAAO,OAAO,KAAK;AACrC,YAAM,OAAO,IAAI,OAAO,QAAQ,KAAK;AACrC,UAAI,OAAO,cAAc,GAAG;AAC1B,cAAM,OAAO,OAAO,KAAK,GAAG,GAAG,OAAO,UAAU,OAAO,QAAQ;AAC/D,cAAM,OAAO,aAAa,MAAM,OAAO,QAAQ;AAC/C,YAAI,GAAG,IAAI;AACX,YAAI,MAAM,CAAC,IAAI;AACf,YAAI,MAAM,CAAC,IAAI;AACf,YAAI,MAAM,CAAC,IAAI,SAAS,kBAAkB,IAAI;AAAA,MAChD,WAAW,OAAO,cAAc,GAAG;AACjC,cAAM,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,YACzB,OAAO,KAAK,GAAG,SAAS,OAAO,UAAU,OAAO,QAAQ,CAAC;AAC3D,YAAI,GAAG,IAAI,aAAa,IAAI,CAAC,GAAI,OAAO,QAAQ;AAChD,YAAI,MAAM,CAAC,IAAI,aAAa,IAAI,CAAC,GAAI,OAAO,QAAQ;AACpD,YAAI,MAAM,CAAC,IAAI,aAAa,IAAI,CAAC,GAAI,OAAO,QAAQ;AACpD,YAAI,MAAM,CAAC,IAAI,kBAAkB,IAAI,MAAM,CAAC,OAAO,MAAM,UAAU,eAAe,CAAC,CAAC,IAChF,IACA;AAAA,MACN,WAAW,OAAO,cAAc,GAAG;AACjC,cAAM,QAAQ,OAAO,KAAK,GAAG,GAAG,GAAG,OAAO,QAAQ;AAClD,cAAM,gBAAgB,QAAQ;AAC9B,YAAI,CAAC,WAAW,gBAAgB,KAAK,QAAQ,QAAQ;AACnD,gBAAM,IAAI,MAAM,sDAAsD,KAAK,EAAE;AAAA,QAC/E;AACA,YAAI,GAAG,IAAI,QAAQ,aAAa;AAChC,YAAI,MAAM,CAAC,IAAI,QAAQ,gBAAgB,CAAC;AACxC,YAAI,MAAM,CAAC,IAAI,QAAQ,gBAAgB,CAAC;AACxC,YAAI,MAAM,CAAC,IAAI,eAAe,KAAK,KAAK;AAAA,MAC1C,WAAW,OAAO,cAAc,GAAG;AACjC,cAAM,OAAO,aAAa,OAAO,KAAK,GAAG,GAAG,GAAG,OAAO,QAAQ,GAAG,OAAO,QAAQ;AAChF,YAAI,GAAG,IAAI;AACX,YAAI,MAAM,CAAC,IAAI;AACf,YAAI,MAAM,CAAC,IAAI;AACf,YAAI,MAAM,CAAC,IAAI,aAAa,OAAO,KAAK,GAAG,GAAG,GAAG,OAAO,QAAQ,GAAG,OAAO,QAAQ;AAAA,MACpF,OAAO;AACL,YAAI,GAAG,IAAI,aAAa,OAAO,KAAK,GAAG,GAAG,GAAG,OAAO,QAAQ,GAAG,OAAO,QAAQ;AAC9E,YAAI,MAAM,CAAC,IAAI,aAAa,OAAO,KAAK,GAAG,GAAG,GAAG,OAAO,QAAQ,GAAG,OAAO,QAAQ;AAClF,YAAI,MAAM,CAAC,IAAI,aAAa,OAAO,KAAK,GAAG,GAAG,GAAG,OAAO,QAAQ,GAAG,OAAO,QAAQ;AAClF,YAAI,MAAM,CAAC,IAAI,aAAa,OAAO,KAAK,GAAG,GAAG,GAAG,OAAO,QAAQ,GAAG,OAAO,QAAQ;AAAA,MACpF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,OACP,KACA,GACA,SACA,UACA,UACQ;AACR,MAAI,aAAa,EAAG,QAAO,IAAI,IAAI,WAAW,OAAO;AACrD,MAAI,aAAa,GAAI,QAAO,IAAI,cAAc,IAAI,WAAW,WAAW,CAAC;AACzE,QAAM,YAAY,IAAI;AACtB,QAAM,QAAQ,IAAI,WAAY,YAAY;AAC1C,SAAQ,IAAI,KAAK,MAAM,YAAY,CAAC,CAAC,KAAM,SAAW,KAAK,YAAY;AACzE;AAEA,SAAS,aAAa,OAAe,UAA0B;AAC7D,MAAI,aAAa,EAAG,QAAO;AAC3B,MAAI,aAAa,GAAI,QAAO,KAAK,MAAM,QAAQ,GAAG;AAClD,SAAO,KAAK,MAAO,QAAQ,QAAS,KAAK,YAAY,EAAE;AACzD;AAEA,SAAS,MAAM,GAAW,GAAW,GAAmB;AACtD,QAAM,IAAI,IAAI,IAAI;AAClB,QAAM,KAAK,KAAK,IAAI,IAAI,CAAC;AACzB,QAAM,KAAK,KAAK,IAAI,IAAI,CAAC;AACzB,QAAM,KAAK,KAAK,IAAI,IAAI,CAAC;AACzB,MAAI,MAAM,MAAM,MAAM,GAAI,QAAO;AACjC,SAAO,MAAM,KAAK,IAAI;AACxB;AAiBO,SAAS,eAAe,KAAiB,OAAO,GAAG,iBAAiB,KAAqB;AAC9F,QAAM,SAAS,oBAAI,IAAoB;AACvC,MAAI,SAAS;AAEb,WAAS,IAAI,GAAG,IAAI,IAAI,OAAO,QAAQ,KAAK,GAAG;AAC7C,UAAM,QAAQ,IAAI,OAAO,IAAI,CAAC;AAC9B,QAAI,QAAQ,eAAgB;AAC5B;AACA,UAAM,MAAO,IAAI,OAAO,CAAC,KAAM,KAAO,IAAI,OAAO,IAAI,CAAC,KAAM,IAAK,IAAI,OAAO,IAAI,CAAC;AACjF,WAAO,IAAI,MAAM,OAAO,IAAI,GAAG,KAAK,KAAK,CAAC;AAAA,EAC5C;AACA,MAAI,WAAW,EAAG,QAAO,CAAC;AAE1B,SAAO,CAAC,GAAG,OAAO,QAAQ,CAAC,EACxB,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,MAAM,GAAG,IAAI,EACb,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO;AAAA,IAClB,GAAI,OAAO,KAAM;AAAA,IACjB,GAAI,OAAO,IAAK;AAAA,IAChB,GAAG,MAAM;AAAA,IACT,QAAQ,IAAI;AAAA,EACd,EAAE;AACN;AAGO,SAAS,kBAAkB,KAAiB,iBAAiB,KAAa;AAC/E,MAAI,QAAQ;AACZ,QAAM,QAAQ,IAAI,OAAO,SAAS;AAClC,WAAS,IAAI,GAAG,IAAI,IAAI,OAAO,QAAQ,KAAK,GAAG;AAC7C,QAAI,IAAI,OAAO,IAAI,CAAC,IAAK,eAAgB;AAAA,EAC3C;AACA,SAAO,UAAU,IAAI,IAAI,QAAQ;AACnC;AAGA,SAAS,MAAM,KAAqB;AAClC,MAAI,IAAI,CAAC;AACT,aAAW,QAAQ,KAAK;AACtB,SAAK;AACL,aAAS,IAAI,GAAG,IAAI,GAAG,IAAK,KAAK,MAAM,IAAM,aAAa,EAAE,IAAI;AAAA,EAClE;AACA,SAAO,CAAC;AACV;AAEA,SAAS,MAAM,MAAc,MAAsB;AACjD,QAAM,MAAM,OAAO,MAAM,CAAC;AAC1B,MAAI,cAAc,KAAK,MAAM;AAC7B,QAAM,OAAO,OAAO,OAAO,CAAC,OAAO,KAAK,MAAM,OAAO,GAAG,IAAI,CAAC;AAC7D,QAAM,MAAM,OAAO,MAAM,CAAC;AAC1B,MAAI,cAAc,MAAM,IAAI,MAAM,CAAC;AACnC,SAAO,OAAO,OAAO,CAAC,KAAK,MAAM,GAAG,CAAC;AACvC;AAMO,SAAS,aAAa,OAAe,QAAgB,KAAqB;AAC/E,MAAI,IAAI,WAAW,QAAQ,SAAS,GAAG;AACrC,UAAM,IAAI,MAAM,YAAY,QAAQ,SAAS,CAAC,sBAAsB,IAAI,MAAM,EAAE;AAAA,EAClF;AACA,QAAM,SAAS,QAAQ;AAEvB,QAAM,MAAM,OAAO,OAAO,SAAS,KAAK,MAAM;AAC9C,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,QAAI,KAAK,SAAS,EAAE,IAAI;AACxB,QAAI,KAAK,KAAK,KAAK,SAAS,KAAK,GAAG,IAAI,SAAS,IAAI,KAAK,MAAM;AAAA,EAClE;AACA,QAAM,OAAO,OAAO,MAAM,EAAE;AAC5B,OAAK,cAAc,OAAO,CAAC;AAC3B,OAAK,cAAc,QAAQ,CAAC;AAC5B,OAAK,CAAC,IAAI;AACV,OAAK,CAAC,IAAI;AACV,SAAO,OAAO,OAAO;AAAA,IACnB,OAAO,KAAK,CAAC,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,EAAI,CAAC;AAAA,IAC5D,MAAM,QAAQ,IAAI;AAAA,IAClB,MAAM,QAAQ,YAAY,GAAG,CAAC;AAAA,IAC9B,MAAM,QAAQ,OAAO,MAAM,CAAC,CAAC;AAAA,EAC/B,CAAC;AACH;AAUO,SAAS,cAAc,OAAe,QAAgB,MAAsB;AACjF,MAAI,KAAK,WAAW,QAAQ,SAAS,GAAG;AACtC,UAAM,IAAI,MAAM,YAAY,QAAQ,SAAS,CAAC,uBAAuB,KAAK,MAAM,EAAE;AAAA,EACpF;AACA,QAAM,SAAS,QAAQ;AAGvB,QAAM,MAAM,OAAO,OAAO,SAAS,KAAK,MAAM;AAC9C,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,QAAI,KAAK,SAAS,EAAE,IAAI;AACxB,SAAK,KAAK,KAAK,KAAK,SAAS,KAAK,GAAG,IAAI,SAAS,IAAI,KAAK,MAAM;AAAA,EACnE;AACA,QAAM,OAAO,OAAO,MAAM,EAAE;AAC5B,OAAK,cAAc,OAAO,CAAC;AAC3B,OAAK,cAAc,QAAQ,CAAC;AAC5B,OAAK,CAAC,IAAI;AACV,OAAK,CAAC,IAAI;AACV,SAAO,OAAO,OAAO;AAAA,IACnB,OAAO,KAAK,CAAC,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,EAAI,CAAC;AAAA,IAC5D,MAAM,QAAQ,IAAI;AAAA,IAClB,MAAM,QAAQ,YAAY,GAAG,CAAC;AAAA,IAC9B,MAAM,QAAQ,OAAO,MAAM,CAAC,CAAC;AAAA,EAC/B,CAAC;AACH;AASO,SAAS,cAAc,OAAiB,OAAO,IAAY;AAChE,QAAM,UAAU,MAAM,IAAI,QAAQ;AAClC,MAAI,CAAC,QAAQ,OAAQ,OAAM,IAAI,MAAM,kBAAkB;AACvD,QAAM,MAAM,OAAO,MAAM,OAAO,OAAO,CAAC;AACxC,QAAM,OAAO,KAAK,IAAI,GAAG,KAAK,MAAM,OAAO,QAAQ,MAAM,CAAC;AAC1D,WAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,aAAS,IAAI,GAAG,IAAI,MAAM,KAAK;AAC7B,YAAM,IAAI,QAAQ,KAAK,IAAI,QAAQ,SAAS,GAAG,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC;AACpE,YAAM,KAAK,IAAI,OAAO,KAAK;AAC3B,UAAI,CAAC,IAAI,EAAE;AACX,UAAI,IAAI,CAAC,IAAI,EAAE;AACf,UAAI,IAAI,CAAC,IAAI,EAAE;AAAA,IACjB;AAAA,EACF;AACA,SAAO,aAAa,MAAM,MAAM,GAAG;AACrC;AAEO,SAAS,SAASC,MAAkD;AACzE,QAAM,IAAI,qBAAqB,KAAKA,KAAI,KAAK,CAAC;AAC9C,MAAI,CAAC,EAAG,OAAM,IAAI,MAAM,uBAAuBA,IAAG,2BAAsB;AACxE,QAAM,IAAI,SAAS,EAAE,CAAC,GAAI,EAAE;AAC5B,SAAO,EAAE,GAAI,KAAK,KAAM,KAAM,GAAI,KAAK,IAAK,KAAM,GAAG,IAAI,IAAK;AAChE;;;ACjdO,IAAM,YAAY;AAAA,EACvB,KAAK;AAAA,EACL,KAAK;AACP;AAIA,IAAM,gBAAgB,OAAO,KAAK,CAAC,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,EAAI,CAAC;AAE3E,SAAS,eAAe,WAAuC;AACpE,SAAO,cAAc,UAAU,MAAM,SAAS;AAChD;AAEO,SAAS,uBAAuB,MAAgC;AACrE,QAAM,QAAQ,KAAK,YAAY;AAC/B,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO,UAAU;AAC7C,MAAI,MAAM,SAAS,MAAM,EAAG,QAAO,UAAU;AAC7C,SAAO;AACT;AAEO,SAAS,gBAAgB,OAAiC;AAC/D,MAAI,MAAM,SAAS,GAAG,cAAc,MAAM,EAAE,OAAO,aAAa,EAAG,QAAO,UAAU;AACpF,QAAM,SAAS,MAAM,SAAS,GAAG,CAAC,EAAE,SAAS,OAAO;AACpD,MAAI,WAAW,YAAY,WAAW,SAAU,QAAO,UAAU;AACjE,SAAO;AACT;AAGO,SAAS,cAAc,OAAe,UAAiC;AAC5E,QAAM,SAAS,gBAAgB,KAAK;AACpC,MAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,4CAA4C,MAAM,MAAM,SAAS;AAC9F,MAAI,YAAY,WAAW,UAAU;AACnC,UAAM,IAAI,MAAM,gBAAgB,MAAM,cAAc,QAAQ,EAAE;AAAA,EAChE;AACA,MAAI,WAAW,UAAU,KAAK;AAC5B,cAAU,KAAK;AAAA,EACjB,OAAO;AACL,gBAAY,KAAK;AAAA,EACnB;AACA,SAAO;AACT;AAGA,SAAS,YAAY,OAAqB;AACxC,MAAI,MAAM,SAAS,GAAI,OAAM,IAAI,MAAM,kDAAkD;AACzF,QAAM,QAAQ,MAAM,aAAa,CAAC;AAClC,QAAM,SAAS,MAAM,aAAa,CAAC;AACnC,MAAI,CAAC,SAAS,CAAC,OAAQ,OAAM,IAAI,MAAM,wCAAwC;AAE/E,QAAM,SAAS,MAAM,EAAE;AACvB,MAAI,SAAS;AACb,MAAI,SAAS,IAAM,WAAU,IAAI,OAAO,SAAS,KAAQ;AACzD,MAAI,SAAS,MAAM,OAAQ,OAAM,IAAI,MAAM,2CAA2C;AAEtF,MAAI,WAAW;AACf,SAAO,SAAS,MAAM,QAAQ;AAC5B,UAAM,SAAS,MAAM,MAAM;AAC3B,QAAI,WAAW,IAAM;AACnB,UAAI,CAAC,SAAU,OAAM,IAAI,MAAM,sCAAsC;AACrE;AAAA,IACF;AACA,QAAI,WAAW,IAAM;AACnB,UAAI,SAAS,KAAK,MAAM,OAAQ,OAAM,IAAI,MAAM,yCAAyC;AACzF,YAAM,cAAc,MAAM,SAAS,CAAC;AACpC,gBAAU;AACV,UAAI,cAAc,IAAM,WAAU,IAAI,OAAO,cAAc,KAAQ;AACnE,UAAI,UAAU,MAAM,OAAQ,OAAM,IAAI,MAAM,iCAAiC;AAC7E;AACA,eAAS,cAAc,OAAO,MAAM;AACpC,iBAAW;AACX;AAAA,IACF;AACA,QAAI,WAAW,IAAM;AACnB,UAAI,SAAS,IAAI,MAAM,OAAQ,OAAM,IAAI,MAAM,kCAAkC;AACjF,eAAS,cAAc,OAAO,SAAS,CAAC;AACxC;AAAA,IACF;AACA,UAAM,IAAI,MAAM,0CAA0C,OAAO,SAAS,EAAE,CAAC,EAAE;AAAA,EACjF;AACA,QAAM,IAAI,MAAM,8BAA8B;AAChD;AAEA,SAAS,cAAc,OAAe,OAAuB;AAC3D,MAAI,SAAS;AACb,aAAS;AACP,QAAI,UAAU,MAAM,OAAQ,OAAM,IAAI,MAAM,oCAAoC;AAChF,UAAM,OAAO,MAAM,MAAM;AACzB;AACA,QAAI,SAAS,EAAG,QAAO;AACvB,cAAU;AACV,QAAI,SAAS,MAAM,OAAQ,OAAM,IAAI,MAAM,mCAAmC;AAAA,EAChF;AACF;AAEO,SAAS,cAAc,MAAc,YAAuB,UAAU,KAAa;AACxF,SAAO,GAAG,IAAI,GAAG,eAAe,SAAS,CAAC;AAC5C;;;AH9EA,IAAM,mBAAmB;AAwEzB,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC/B;AAAA,EAAU;AAAA,EAAS;AAAA,EAAU;AAAA,EAAa;AAAA,EAAQ;AAAA,EAAe;AAAA,EAAa;AAChF,CAAC;AAED,IAAM,gBAAN,MAAoB;AAAA,EAGlB,YACE,UAAU,QAAQ,IAAI,oBAAoB,kBACzB,UAAwB,OACzC;AADiB;AAEjB,SAAK,UAAU,iBAAiB,OAAO;AAAA,EACzC;AAAA,EAHmB;AAAA,EAJV;AAAA,EAST,MAAM,kBAAiC;AACrC,UAAM,QAAQ,MAAM,KAAK,KAAK,cAAc;AAC5C,QAAI,CAAC,SAAS,KAAK,EAAG,OAAM,IAAI,MAAM,uCAAuC;AAAA,EAC/E;AAAA,EAEA,MAAM,OAAO,UAA0C;AACrD,UAAM,QAAQ,MAAM,KAAK,KAAK,UAAU;AAAA,MACtC,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,QAAQ,UAAU,WAAW,WAAW,EAAE,CAAC;AAAA,IACpE,CAAC;AACD,QAAI,CAAC,SAAS,KAAK,EAAG,OAAM,IAAI,MAAM,4CAA4C;AAClF,UAAM,WAAW,MAAM;AACvB,QAAI,OAAO,aAAa,YAAY,CAAC,UAAU;AAC7C,YAAM,QAAQ,SAAS,MAAM,WAAW,IAAI,OAAO,KAAK,MAAM,WAAW,IAAI,CAAC;AAC9E,YAAM,IAAI;AAAA,QACR,wCACG,MAAM,SAAS,+BAA+B,MAAM,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,KAAK;AAAA,MACpF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,YACJ,OACAC,SACA,QACiB;AACjB,UAAM,YAAY,WAAW,SAAS,QAAQ;AAC9C,UAAM,OAAO,IAAI,SAAS;AAC1B,SAAK;AAAA,MACH;AAAA,MACA,IAAI,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,GAAG,EAAE,MAAM,WAAW,SAAS,eAAe,YAAY,CAAC;AAAA,MAC1F,GAAGA,OAAM,IAAI,SAAS;AAAA,IACxB;AACA,SAAK,OAAO,QAAQ,OAAO;AAC3B,SAAK,OAAO,aAAa,WAAW;AACpC,SAAK,OAAO,aAAa,MAAM;AAC/B,UAAM,MAAM,KAAK,SAAS,cAAc;AACxC,UAAM,WAAW,MAAM,KAAK,QAAQ,KAAK,EAAE,QAAQ,QAAQ,MAAM,KAAK,CAAC;AACvE,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI,QAAiB;AACrB,QAAI;AACF,cAAQ,OAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IACpC,QAAQ;AACN,cAAQ;AAAA,IACV;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,IAAI;AAAA,QACR,gCAAgC,SAAS,MAAM,OAC5C,SAAS,KAAK,IAAI,KAAK,SAAS,KAAK,CAAC,KAAK;AAAA,MAChD;AAAA,IACF;AACA,QAAI,CAAC,SAAS,KAAK,KAAK,OAAO,MAAM,SAAS,YAAY,CAAC,MAAM,MAAM;AACrE,YAAM,IAAI,MAAM,mDAAmD;AAAA,IACrE;AACA,UAAM,YAAY,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAC1E,WAAO,YAAY,GAAG,UAAU,QAAQ,QAAQ,EAAE,CAAC,IAAI,MAAM,IAAI,KAAK,MAAM;AAAA,EAC9E;AAAA,EAEA,MAAM,QAAQ,UAAoC;AAChD,WAAO,KAAK,KAAK,WAAW,mBAAmB,QAAQ,CAAC,EAAE;AAAA,EAC5D;AAAA,EAEA,QAAQ,OAA2B;AACjC,UAAM,MAAM,KAAK,SAAS,MAAM;AAChC,QAAI,aAAa,IAAI,YAAY,MAAM,QAAQ;AAC/C,QAAI,aAAa,IAAI,aAAa,MAAM,SAAS;AACjD,QAAI,aAAa,IAAI,QAAQ,MAAM,IAAI;AACvC,WAAO,IAAI,SAAS;AAAA,EACtB;AAAA,EAEA,MAAM,SAAS,QAAiC;AAC9C,QAAI,SAAS;AACb,QAAI,OAAO,WAAW,YAAY,EAAG,UAAS,KAAK,QAAQ,YAAY,MAAM,CAAC;AAC9E,UAAM,WAAW,MAAM,KAAK,QAAQ,MAAM;AAC1C,QAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,4BAA4B,SAAS,MAAM,GAAG;AAChF,WAAO,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC;AAAA,EACjD;AAAA,EAEQ,SAAS,OAAoB;AACnC,WAAO,IAAI,IAAI,MAAM,QAAQ,QAAQ,EAAE,GAAG,GAAG,KAAK,OAAO,GAAG;AAAA,EAC9D;AAAA,EAEA,MAAc,KAAK,OAAe,OAAoB,CAAC,GAAqB;AAC1E,UAAM,MAAM,KAAK,SAAS,KAAK;AAC/B,UAAM,WAAW,MAAM,KAAK,QAAQ,KAAK;AAAA,MACvC,GAAG;AAAA,MACH,SAAS;AAAA,QACP,GAAI,KAAK,OAAO,EAAE,gBAAgB,mBAAmB,IAAI,CAAC;AAAA,QAC1D,GAAG,KAAK;AAAA,MACV;AAAA,IACF,CAAC;AACD,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI,QAAiB;AACrB,QAAI;AACF,cAAQ,OAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IACpC,QAAQ;AACN,UAAI,SAAS,GAAI,OAAM,IAAI,MAAM,sCAAsC,IAAI,QAAQ,EAAE;AACrF,cAAQ;AAAA,IACV;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,SAAS,SAAS,KAAK;AAC7B,YAAM,IAAI;AAAA,QACR,2BAA2B,SAAS,MAAM,QAAQ,IAAI,QAAQ,MAC3D,SAAS,KAAK,MAAM,KAAK;AAAA,MAC9B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAGO,IAAM,kBAAN,MAAM,iBAAoC;AAAA,EAG/C,YAA6B,SAAwB,IAAI,cAAc,GAAG;AAA7C;AAAA,EAA8C;AAAA,EAA9C;AAAA,EAFpB,KAAK;AAAA,EAId,OAAO,UAA2B;AAChC,WAAO,IAAI,iBAAgB;AAAA,EAC7B;AAAA,EAEA,OAAO,aAA8B;AACnC,WAAO,IAAI,iBAAgB,IAAI,cAAc,gBAAgB,CAAC;AAAA,EAChE;AAAA,EAEA,OAAO,eAAgC;AACrC,WAAO,IAAI,iBAAgB;AAAA,EAC7B;AAAA,EAEA,MAAM,eACJ,OACA,SACkC;AAClC,UAAM,UAAU,aAAa,KAAK;AAClC,UAAM,eAAeC,MAAK,QAAQ,QAAQ,MAAM,QAAQ,YAAY;AACpE,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,SAAS,cAAc,MAAM;AAAA,IAC3C,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,+BAA+B,QAAQ,OAAO,0BAA0B,YAAY,KAC/E,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MACvD;AAAA,IACF;AACA,QAAI;AACJ,QAAI;AACF,eAAS,KAAK,MAAM,GAAG;AAAA,IACzB,QAAQ;AACN,YAAM,IAAI,MAAM,+BAA+B,QAAQ,OAAO,wBAAwB,YAAY,EAAE;AAAA,IACtG;AACA,UAAM,WAAW,cAAc,QAAQ,YAAY;AACnD,6BAAyB,UAAU,OAAO;AAC1C,UAAM,iBAAiB,OAAO,KAAK,UAAU,UAAU,QAAQ,CAAC,CAAC;AACjE,UAAM,WAAmC,EAAE,GAAG,SAAS,UAAU,eAAe;AAChF,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,QACR,cAAc,QAAQ;AAAA,QACtB,WAAW,QAAQ;AAAA,QACnB,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,QACnD,UAAU,QAAQ;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,cACJ,OACA,SACiC;AACjC,UAAM,UAAU,aAAa,QAAQ,eAAe;AACpD,QAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,gBAAgB;AAChD,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC7E;AACA,UAAM,SAAkC,CAAC;AACzC,UAAM,WAAoC,CAAC;AAC3C,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,UAAI,iBAAiB,IAAI,IAAI,GAAG;AAC9B,cAAM,IAAI;AAAA,UACR,0BAA0B,IAAI,0CAA0C,IAAI;AAAA,QAC9E;AAAA,MACF;AACA,YAAM,UAAU,OAAO,OAAO,QAAQ,UAAU,IAAI,IAAI,QAAQ,SAAS,IAAI,IAAI;AACjF,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI;AAAA,UACR,0BAA0B,IAAI,6BAA6B,IAAI;AAAA,QACjE;AAAA,MACF;AACA,YAAM,eAAe,OACnB,MACA,UACmD;AACnD,cAAM,QAAQ,kBAAkB,IAAI,GAAG,SAAS,OAAO,KAAK,IAAI,KAAK,GAAG;AACxE,YAAI,eAAe,QAAQ,UAAW,OAAO,GAAG;AAC9C,cAAI,OAAO,SAAS,UAAU;AAC5B,kBAAM,IAAI,MAAM,WAAW,KAAK,+CAA+C;AAAA,UACjF;AACA,gBAAM,OAAOA,MAAK,QAAQ,QAAQ,MAAM,IAAI;AAC5C,cAAI;AACJ,cAAI;AACF,oBAAQ,MAAM,SAAS,IAAI;AAAA,UAC7B,SAAS,OAAO;AACd,kBAAM,IAAI;AAAA,cACR,WAAW,KAAK,yBAAyB,IAAI,KACxC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,YAC7D;AAAA,UACF;AACA,gBAAM,SAAS,iBAAiB,KAAK;AACrC,cAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,WAAW,KAAK,0BAA0B,IAAI,EAAE;AAC7E,gBAAM,OAAO,OAAO,KAAK;AACzB,iBAAO;AAAA,YACL,SAAS,EAAE,MAAM,SAAS,MAAM,MAAM,QAAQ,MAAM,OAAO;AAAA,YAC3D,QAAQ,EAAE,MAAM,SAAS,QAAQ,MAAM,OAAO;AAAA,UAChD;AAAA,QACF;AAEA,cAAM,UAAU,QAAQ,SAAU,QAAQ,MAAM,EAAG,OAAO,QAAQ,KAAK;AACvE,YAAI,OAAO,YAAY,YAAY,OAAO,YAAY,YAAY,OAAO,YAAY,WAAW;AAC9F,gBAAM,IAAI;AAAA,YACR,WAAW,KAAK,8BAA8B,QAAQ,MAAM,IAAI,QAAQ,KAAK;AAAA,UAC/E;AAAA,QACF;AACA,YAAI,OAAO,YAAY,OAAO,MAAM;AAClC,gBAAM,IAAI;AAAA,YACR,WAAW,KAAK,YAAY,OAAO,OAAO,aAAa,QAAQ,MAAM,IAAI,QAAQ,KAAK;AAAA,UACxF;AAAA,QACF;AACA,eAAO,EAAE,SAAS,MAAM,QAAQ,KAAK;AAAA,MACvC;AAEA,UAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,YAAI,CAAC,QAAQ,UAAU,SAAS,QAAQ,OAAO,MAAM;AACnD,gBAAM,IAAI;AAAA,YACR,0BAA0B,IAAI,mCACzB,QAAQ,SAAS,IAAI,QAAQ,OAAO,IAAI,MAAM,gBAAgB;AAAA,UACrE;AAAA,QACF;AACA,cAAM,WAAW,MAAM,QAAQ,IAAI,MAAM,IAAI,CAAC,MAAM,UAAU,aAAa,MAAM,KAAK,CAAC,CAAC;AACxF,eAAO,IAAI,IAAI,SAAS,IAAI,CAAC,SAAS,KAAK,OAAO;AAClD,iBAAS,IAAI,IAAI,SAAS,IAAI,CAAC,SAAS,KAAK,MAAM;AAAA,MACrD,OAAO;AACL,cAAM,WAAW,MAAM,aAAa,KAAK;AACzC,eAAO,IAAI,IAAI,SAAS;AACxB,iBAAS,IAAI,IAAI,SAAS;AAAA,MAC5B;AAAA,IACF;AACA,WAAO,EAAE,QAAQ,SAAS;AAAA,EAC5B;AAAA,EAEA,SAAS,WAA+B;AACtC,WAAO,cAAc,SAAS,cAAc;AAAA,EAC9C;AAAA,EAEA,iBAAiB,OAA8B;AAC7C,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,MAAkC;AACzC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,YAAY,KAAK,cAAc,WAAW,IAAI,gBAAgB,IAAI,EAAE;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,SAAS,MAAoB,aAAyC;AACpE,UAAM,UAAU,gBAAgB,IAAI;AAIpC,QAAI,KAAK,UAAU,CAAC,KAAK,UAAU;AACjC,UAAI,KAAK,cAAc,UAAU;AAC/B,cAAM,IAAI,MAAM,yEAAyE;AAAA,MAC3F;AACA;AAAA,IACF;AACA,QAAI,KAAK,QAAQ,MAAM,KAAK,SAAS,MAAM,KAAK,QAAQ,QAAQ,KAAK,SAAS,MAAM;AAClF,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAChF;AACA,QAAI,YAAY,QAAQ;AACtB,YAAM,IAAI,MAAM,gFAAgF;AAAA,IAClG;AACA,QAAI,KAAK,QAAQ,QAAQ;AACvB,YAAM,IAAI,MAAM,2FAA2F;AAAA,IAC7G;AACA,QAAI,KAAK,QAAQ,QAAQ,CAAC,QAAQ,SAAS,MAAM;AAC/C,YAAM,IAAI,MAAM,+DAA+D;AAAA,IACjF;AACA,QAAI,CAAC,QAAQ,SAAS,UAAU,CAAC,QAAQ,SAAS,QAAQ;AACxD,YAAM,IAAI,MAAM,6DAA6D;AAAA,IAC/E;AACA,QAAI,CAAC,KAAK,aAAa,CAAC,QAAQ,SAAS,SAAS,CAAC,QAAQ,SAAS,SAAS;AAC3E,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACvF;AACA,QAAI,QAAQ,YAAY,KAAK,CAAC,QAAQ,SAAS,WAAW;AACxD,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAChF;AACA,QAAI,KAAK,cAAc,UAAU;AAC/B,UAAI,CAAC,QAAQ,OAAQ,OAAM,IAAI,MAAM,mEAAmE;AACxG,UAAI,QAAQ,cAAc,EAAG,OAAM,IAAI,MAAM,iDAAiD;AAC9F,UAAI,KAAK,SAAU,OAAM,IAAI,MAAM,uDAAuD;AAC1F,YAAM,SAAS,KAAK,iBAAiB,QAAQ,OAAO,IAAI;AACxD,UAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS,KAAK,OAAO,SAAS,IAAI;AACrE,cAAM,IAAI;AAAA,UACR,wBAAwB,QAAQ,OAAO,IAAI;AAAA,QAC7C;AAAA,MACF;AACA,UAAI,QAAQ,OAAO,aAAa,MAAM,KAAK,QAAQ,QAAQ,CAAC,QAAQ,SAAS,OAAO;AAClF,cAAM,IAAI,MAAM,iEAAiE;AAAA,MACnF;AACA,UACE,KAAK,QAAQ,QACb,CAAC,OAAO,cAAc,KAAK,QAAQ,OAAO,SAAS,KAAK,QAAQ,OAAO,QAAQ,GAC/E;AACA,cAAM,IAAI,MAAM,qEAAqE;AAAA,MACvF;AAAA,IACF,WAAW,QAAQ,QAAQ;AACzB,YAAM,IAAI,MAAM,2DAA2D;AAAA,IAC7E;AACA,QAAI,KAAK,UAAU;AACjB,UAAI,CAAC,QAAQ,SAAS,aAAa;AACjC,cAAM,IAAI,MAAM,gDAAgD;AAAA,MAClE;AACA,UAAI,KAAK,SAAS,SAAS,aAAa,CAAC,QAAQ,SAAS,WAAW;AACnE,cAAM,IAAI,MAAM,sDAAsD;AAAA,MACxE;AACA,UAAI,KAAK,SAAS,YAAY,QAAQ,CAAC,QAAQ,SAAS,UAAU;AAChE,cAAM,IAAI,MAAM,sDAAsD;AAAA,MACxE;AACA,WACG,CAAC,QAAQ,SAAS,SAAS,CAAC,QAAQ,SAAS,WAC9C,KAAK,SAAS,eAAe,QAC7B,KAAK,SAAS,gBAAgB,SAC7B,KAAK,UAAU,KAAK,SAAS,eAAe,KAAK,WAAW,KAAK,SAAS,eAC3E;AACA,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,6BAAyB,QAAQ,UAAU,OAAO;AAAA,EACpD;AAAA,EAEA,YAAuB;AACrB,WAAO,EAAE,WAAW,GAAG,aAAa,EAAE;AAAA,EACxC;AAAA,EAEA,MAAM,OAAO,MAAoB,aAAgE;AAC/F,SAAK,SAAS,MAAM,WAAW;AAC/B,UAAM,UAAU,gBAAgB,IAAI;AACpC,UAAM,iBAAiB,oBAAI,IAAoB;AAC/C,UAAM,YAAY,OAChBC,WACA,MACA,UACkB;AAClB,YAAM,UAAU,OAAO,OAAO,QAAQ,UAAU,IAAI,IAAI,QAAQ,SAAS,IAAI,IAAI;AACjF,UAAI,CAAC,QAAS,OAAM,IAAI,MAAM,2BAA2B,IAAI,kBAAkB;AAC/E,UAAI,CAAC,kBAAkB,KAAK,GAAG;AAC7B,mBAAWA,WAAU,SAAS,KAAK;AACnC;AAAA,MACF;AACA,YAAM,QAAQ,MAAM,SAAS,MAAM,IAAI;AACvC,UAAI,OAAO,KAAK,MAAM,MAAM,QAAQ;AAClC,cAAM,IAAI,MAAM,2BAA2B,IAAI,yBAAyB;AAAA,MAC1E;AACA,UAAI,WAAW,eAAe,IAAI,MAAM,MAAM;AAC9C,UAAI,CAAC,UAAU;AACb,mBAAW,MAAM,KAAK,OAAO,YAAY,OAAO,MAAM,QAAQ,MAAM,MAAM;AAC1E,uBAAe,IAAI,MAAM,QAAQ,QAAQ;AAAA,MAC3C;AACA,iBAAWA,WAAU,SAAS,QAAQ;AAAA,IACxC;AACA,UAAM,gBAAgB,OAAO,eAAgD;AAC3E,YAAMA,YAAW,gBAAgB,QAAQ,QAAQ;AACjD,iBAAWA,WAAU,QAAQ,SAAS,QAAQ,KAAK,MAAM;AACzD,UAAI,QAAQ,SAAS,MAAO,YAAWA,WAAU,QAAQ,SAAS,OAAO,KAAK,KAAK;AACnF,UAAI,QAAQ,SAAS,OAAQ,YAAWA,WAAU,QAAQ,SAAS,QAAQ,KAAK,MAAM;AACtF,UAAI,QAAQ,SAAS,UAAW,YAAWA,WAAU,QAAQ,SAAS,WAAW,QAAQ,SAAS;AAClG,UAAI,KAAK,QAAQ,QAAQ,QAAQ,SAAS,MAAM;AAC9C,cAAM,OAAO,cAAc,OAAO,KAAK,OAAO,KAAK,OAAO,cAAc,QAAQ,QAAQ,YAAY;AACpG,mBAAWA,WAAU,QAAQ,SAAS,MAAM,IAAI;AAAA,MAClD;AACA,iBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,KAAK,kBAAkB,CAAC,CAAC,GAAG;AACrE,cAAM,WAAW,MAAM,QAAQ,KAAK,IAC/B,cAAc,OAAO,QAAQ,MAAM,UAAU,IAC9C;AACJ,cAAM,UAAUA,WAAU,MAAM,QAAQ;AAAA,MAC1C;AACA,aAAOA;AAAA,IACT;AAEA,UAAM,SAAS,wBAAwB,KAAK,cAAc;AAC1D,QAAI,KAAK,cAAc,UAAU;AAC/B,YAAM,SAAS,QAAQ;AACvB,YAAM,SAAS,KAAK,eAAgB,OAAO,IAAI;AAC/C,YAAM,YAAsB,CAAC;AAC7B,eAAS,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS;AAClD,kBAAU,KAAK,MAAM,KAAK,OAAO,OAAO,MAAM,cAAc,KAAK,CAAC,CAAC;AAAA,MACrE;AACA,aAAO;AAAA,QACL,OAAO,kBAAkB,EAAE,WAAW,cAAc,QAAQ,aAAa,CAAC;AAAA,QAC1E,UAAU;AAAA,UACR;AAAA,UACA,UAAU;AAAA,YACR,OAAO,OAAO;AAAA,YACd,MAAM,OAAO;AAAA,YACb,UAAU,OAAO;AAAA,YACjB,KAAK,KAAK,SAAS,OAAO;AAAA,YAC1B;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,cAAc;AACrC,QAAI,KAAK,UAAU;AACjB,UAAI,CAAC,KAAK,SAAS,gBAAgB,CAAC,KAAK,SAAS,cAAc;AAC9D,cAAM,IAAI,MAAM,sCAAsC;AAAA,MACxD;AACA,YAAM,cAAc,MAAM,SAAS,KAAK,SAAS,UAAU;AAC3D,UAAI,OAAO,WAAW,MAAM,KAAK,SAAS,cAAc;AACtD,cAAM,IAAI,MAAM,+CAA+C;AAAA,MACjE;AACA,YAAM,iBAAiB,MAAM,KAAK,OAAO;AAAA,QACvC;AAAA,QACA,KAAK,SAAS;AAAA,QACd,KAAK,SAAS;AAAA,MAChB;AACA,iBAAW,UAAU,QAAQ,SAAS,aAAc,cAAc;AAElE,UAAI,KAAK,SAAS,UAAU;AAC1B,YAAI,CAAC,KAAK,SAAS,cAAc,CAAC,KAAK,SAAS,YAAY;AAC1D,gBAAM,IAAI,MAAM,oCAAoC;AAAA,QACtD;AACA,cAAM,YAAY,MAAM,SAAS,KAAK,SAAS,QAAQ;AACvD,YAAI,OAAO,SAAS,MAAM,KAAK,SAAS,YAAY;AAClD,gBAAM,IAAI,MAAM,6CAA6C;AAAA,QAC/D;AACA,cAAM,eAAe,MAAM,KAAK,OAAO;AAAA,UACrC;AAAA,UACA,KAAK,SAAS;AAAA,UACd,KAAK,SAAS;AAAA,QAChB;AACA,mBAAW,UAAU,QAAQ,SAAS,WAAY,YAAY;AAAA,MAChE;AACA,UAAI,KAAK,SAAS,YAAY,MAAM;AAClC,mBAAW,UAAU,QAAQ,SAAS,UAAW,KAAK,SAAS,QAAQ;AAAA,MACzE;AAAA,IACF;AACA,UAAM,WAAW,MAAM,KAAK,OAAO,OAAO,QAAQ;AAClD,UAAM,WAAW;AAAA,MACf,GAAI,OAAO,KAAK,MAAM,EAAE,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC/C,GAAI,KAAK,WACL;AAAA,QACE,UAAU;AAAA,UACR,MAAM,KAAK,SAAS;AAAA,UACpB,eAAe,KAAK,SAAS;AAAA,UAC7B,cAAc,KAAK,SAAS;AAAA,UAC5B,GAAI,KAAK,SAAS,aAAa,EAAE,YAAY,KAAK,SAAS,WAAW,IAAI,CAAC;AAAA,QAC7E;AAAA,MACF,IACA,CAAC;AAAA,IACP;AACA,WAAO;AAAA,MACL,OAAO,UAAU,UAAU,QAAQ,YAAY;AAAA,MAC/C,GAAI,OAAO,KAAK,QAAQ,EAAE,SAAS,EAAE,SAAS,IAAI,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,OAAe,WAAsB,SAA0C;AACxF,QAAI,cAAc,UAAU;AAC1B,YAAM,WAAW,kBAAkB,KAAK;AACxC,YAAMC,UAAuB,CAAC;AAC9B,eAAS,QAAQ,GAAG,QAAQ,SAAS,UAAU,QAAQ,SAAS;AAC9D,cAAMC,YAAW,SAAS,UAAU,KAAK;AACzC,cAAMC,WAAU,MAAM,KAAK,OAAO,QAAQD,SAAQ;AAClD,cAAME,SAAQ,aAAaD,UAASD,SAAQ;AAC5C,YAAI,CAACE,OAAO,QAAO,EAAE,QAAQ,aAAa;AAC1C,cAAMC,UAAS,SAASD,OAAM,MAAM,IAAIA,OAAM,SAAS,CAAC;AACxD,YAAIC,QAAO,eAAe,SAAS;AACjC,iBAAO,EAAE,QAAQ,UAAU,OAAO,SAAS,KAAK,KAAK,aAAaA,OAAM,CAAC,GAAG;AAAA,QAC9E;AACA,YAAIA,QAAO,cAAc,MAAO,QAAO,EAAE,QAAQ,aAAa;AAC9D,cAAM,SAAS,aAAaD,QAAO,SAAS,YAAY;AACxD,YAAI,kBAAkB,OAAO;AAC3B,iBAAO,EAAE,QAAQ,UAAU,OAAO,SAAS,KAAK,KAAK,OAAO,OAAO,GAAG;AAAA,QACxE;AACA,YAAI,OAAO,WAAW,GAAG;AACvB,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,OAAO,SAAS,KAAK,sBAAsB,OAAO,MAAM;AAAA,UAC1D;AAAA,QACF;AACA,QAAAH,QAAO,KAAK,OAAO,CAAC,CAAE;AAAA,MACxB;AACA,YAAM,MAAM,SAAS,MAAM,SAAS,OAAO;AAC3C,YAAM,UAAUA,QAAO,IAAI,CAAC,OAAO,WAAW;AAAA,QAC5C,KAAK,UAAU,KAAK;AAAA,QACpB,MAAM,UAAU,KAAK;AAAA,QACrB,WAAW,UAAU;AAAA,MACvB,EAAE;AACF,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,WAAWA,QAAO,IAAI,CAAC,UAAU,KAAK,OAAO,QAAQ,KAAK,CAAC;AAAA,QAC3D;AAAA,QACA;AAAA,QACA,UAAU,SAAS,OACf,mBAAmB,QAAQ,MAAM,UAAUA,SAAQ,GAAG,IACtD,EAAE,UAAU,EAAE,OAAOA,QAAO,QAAQ,KAAK,WAAW,SAAS,UAAU,EAAE;AAAA,MAC/E;AAAA,IACF;AACA,UAAM,EAAE,UAAU,aAAa,IAAI,UAAU,KAAK;AAClD,UAAM,UAAU,MAAM,KAAK,OAAO,QAAQ,QAAQ;AAClD,UAAM,QAAQ,aAAa,SAAS,QAAQ;AAC5C,QAAI,CAAC,MAAO,QAAO,EAAE,QAAQ,aAAa;AAE1C,UAAM,SAAS,SAAS,MAAM,MAAM,IAAI,MAAM,SAAS,CAAC;AACxD,UAAM,aAAa,OAAO,OAAO,eAAe,WAAW,OAAO,aAAa;AAC/E,QAAI,eAAe,SAAS;AAC1B,aAAO,EAAE,QAAQ,UAAU,OAAO,aAAa,MAAM,EAAE;AAAA,IACzD;AACA,QAAI,OAAO,cAAc,MAAO,QAAO,EAAE,QAAQ,aAAa;AAE9D,UAAM,SAAS,aAAa,OAAO,YAAY;AAC/C,QAAI,kBAAkB,MAAO,QAAO,EAAE,QAAQ,UAAU,OAAO,OAAO,QAAQ;AAC9E,UAAM,WAAW,SAAS,OAAO,gBAAgB,QAAQ,IAAI,EAAE,YAAY;AAC3E,QAAI,YAAY,QAAQ,OAAO,WAAW,UAAU;AAClD,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO,wBAAwB,YAAY,cAAc,OAAO,MAAM,uBAAuB,QAAQ;AAAA,MACvG;AAAA,IACF;AACA,UAAM,WAAW,SAAS,OAAO,cAAc,QAAQ,MAAM,UAAU,cAAc,MAAM,IAAI;AAAA,MAC7F;AAAA,MACA;AAAA,MACA,aAAa,OAAO;AAAA,IACtB;AACA,QAAI,OAAO,SAAS,GAAG;AACrB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,eAAe,OAAO,IAAI,CAAC,UAAU,KAAK,OAAO,QAAQ,KAAK,CAAC;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AACA,UAAM,YAAY,UAAU,OAAO,CAAC,CAAE;AACtC,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,UAAU,GAAG,QAAQ,IAAI,YAAY;AAAA,MACrC;AAAA,MACA,SAAS,CAAC,EAAE,KAAK,WAAW,WAAW,UAAU,IAAI,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,OACA,OACyD;AACzD,UAAM,EAAE,UAAU,aAAa,IAAI,UAAU,KAAK;AAClD,UAAM,UAAU,MAAM,KAAK,OAAO,QAAQ,QAAQ;AAClD,UAAM,QAAQ,aAAa,SAAS,QAAQ;AAC5C,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kBAAkB,QAAQ,kBAAkB;AACxE,UAAM,SAAS,aAAa,OAAO,YAAY;AAC/C,QAAI,kBAAkB,MAAO,OAAM;AACnC,UAAM,QAAQ,OAAO,KAAK;AAC1B,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kBAAkB,QAAQ,8BAA8B,KAAK,EAAE;AAC3F,WAAO;AAAA,MACL,UAAU,GAAG,QAAQ,IAAI,YAAY,IAAI,KAAK;AAAA,MAC9C,WAAW,UAAU,KAAK;AAAA,IAC5B;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,KAA8B;AAC3C,WAAO,KAAK,OAAO,SAAS,GAAG;AAAA,EACjC;AAAA,EAEA,MAAM,kBAAiC;AACrC,UAAM,KAAK,OAAO,gBAAgB;AAAA,EACpC;AACF;AAEA,SAAS,aAAa,OAAwD;AAC5E,QAAM,UAAU,oBAAI,IAAI;AAAA,IACtB;AAAA,IAAgB;AAAA,IAAgB;AAAA,IAAa;AAAA,IAAU;AAAA,IAAY;AAAA,IAAY;AAAA,EACjF,CAAC;AACD,QAAM,QAAQ,OAAO,KAAK,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,IAAI,GAAG,CAAC;AAClE,MAAI,MAAM,OAAQ,OAAM,IAAI,MAAM,8BAA8B,MAAM,KAAK,IAAI,CAAC,EAAE;AAClF,QAAM,eAAe,eAAe,MAAM,cAAc,cAAc;AACtE,QAAM,eAAe,eAAe,MAAM,cAAc,cAAc;AACtE,QAAM,YAAY,MAAM,aAAa;AACrC,MAAI,CAAC,OAAO,UAAU,SAAS,KAAK,OAAO,SAAS,IAAI,KAAK,OAAO,SAAS,IAAI,IAAI;AACnF,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,MAAI,CAAC,SAAS,MAAM,QAAQ,EAAG,OAAM,IAAI,MAAM,oCAAoC;AACnF,QAAM,WAAW,OAAO;AAAA,IACtB,OAAO,QAAQ,MAAM,QAAQ,EAAE,IAAI,CAAC,CAAC,MAAM,OAAO,MAAM,CAAC,MAAM,aAAa,SAAS,IAAI,CAAC,CAAC;AAAA,EAC7F;AACA,MAAI,CAAC,SAAS,OAAQ,OAAM,IAAI,MAAM,2CAA2C;AACjF,QAAM,SAAS,MAAM,UAAU,OAAO,SAAY,YAAY,MAAM,MAAM;AAC1E,MAAI,QAAQ;AACV,QAAI,iBAAiB,IAAI,OAAO,IAAI,GAAG;AACrC,YAAM,IAAI,MAAM,wDAAwD,OAAO,IAAI,GAAG;AAAA,IACxF;AACA,QAAI,CAAC,OAAO,OAAO,UAAU,OAAO,IAAI,GAAG;AACzC,YAAM,IAAI,MAAM,wBAAwB,OAAO,IAAI,2BAA2B;AAAA,IAChF;AAAA,EACF;AACA,QAAM,WAAW,MAAM,YAAY,OAAO,SAAY,cAAc,MAAM,UAAU,YAAY;AAChG,QAAM,iBAAiB,MAAM,kBAAkB,OAC3C,SACA,eAAe,MAAM,gBAAgB,gBAAgB;AACzD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW,OAAO,SAAS;AAAA,IAC3B;AAAA,IACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/B,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;AAAA,EAC7C;AACF;AAEA,SAAS,YAAY,OAAoD;AACvE,MAAI,CAAC,SAAS,KAAK,EAAG,OAAM,IAAI,MAAM,kCAAkC;AACxE,QAAM,QAAQ,OAAO,KAAK,KAAK,EAAE,OAAO,CAAC,QAAQ,QAAQ,UAAU,QAAQ,UAAU;AACrF,MAAI,MAAM,OAAQ,OAAM,IAAI,MAAM,oCAAoC,MAAM,KAAK,IAAI,CAAC,EAAE;AACxF,QAAM,OAAO,eAAe,MAAM,MAAM,aAAa;AACrD,QAAM,WAAW,MAAM,YAAY;AACnC,MAAI,CAAC,OAAO,cAAc,QAAQ,KAAK,KAAK,IAAI,OAAO,QAAQ,CAAC,IAAI,KAAW;AAC7E,UAAM,IAAI,MAAM,yEAAyE;AAAA,EAC3F;AACA,SAAO,EAAE,MAAM,UAAU,OAAO,QAAQ,EAAE;AAC5C;AAEA,SAAS,gBAAgB,MAA4C;AACnE,QAAM,UAAU,aAAa,KAAK,eAAe;AACjD,MAAI,CAAC,QAAQ,YAAY,CAAC,QAAQ,gBAAgB;AAChD,UAAM,IAAI,MAAM,8DAA8D;AAAA,EAChF;AACA,SAAO;AACT;AAEA,SAAS,aAAa,OAAgB,MAA8B;AAClE,MAAI,CAAC,SAAS,KAAK,EAAG,OAAM,IAAI,MAAM,oBAAoB,IAAI,oBAAoB;AAClF,QAAM,QAAQ,OAAO,KAAK,KAAK,EAAE,OAAO,CAAC,QAAQ,QAAQ,YAAY,QAAQ,OAAO;AACpF,MAAI,MAAM,OAAQ,OAAM,IAAI,MAAM,4BAA4B,IAAI,cAAc,MAAM,KAAK,IAAI,CAAC,EAAE;AAClG,SAAO;AAAA,IACL,QAAQ,eAAe,MAAM,QAAQ,YAAY,IAAI,SAAS;AAAA,IAC9D,OAAO,eAAe,MAAM,OAAO,YAAY,IAAI,QAAQ;AAAA,EAC7D;AACF;AAEA,SAAS,cAAc,OAAgB,OAA8B;AACnE,MAAI,CAAC,SAAS,KAAK,KAAK,CAAC,OAAO,KAAK,KAAK,EAAE,QAAQ;AAClD,UAAM,IAAI,MAAM,0DAA0D,KAAK,EAAE;AAAA,EACnF;AACA,aAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAClD,QAAI,CAAC,SAAS,IAAI,KAAK,OAAO,KAAK,eAAe,YAAY,CAAC,SAAS,KAAK,MAAM,GAAG;AACpF,YAAM,IAAI,MAAM,0BAA0B,MAAM,sCAAsC;AAAA,IACxF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,yBAAyB,UAAyB,SAA+B;AACxF,QAAM,UAAU,oBAAI,IAAoB;AACxC,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,QAAQ,GAAG;AAC9D,QAAI,CAAC,QAAS;AACd,UAAM,OAAO,SAAS,QAAQ,MAAM;AACpC,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,WAAW,IAAI,oCAAoC,QAAQ,MAAM,GAAG;AAC/F,QAAI,CAAC,OAAO,OAAO,KAAK,QAAQ,QAAQ,KAAK,GAAG;AAC9C,YAAM,IAAI;AAAA,QACR,WAAW,IAAI,qCAAqC,QAAQ,KAAK,cAAc,QAAQ,MAAM;AAAA,MAC/F;AAAA,IACF;AACA,UAAM,SAAS,GAAG,QAAQ,MAAM,IAAI,QAAQ,KAAK;AACjD,UAAM,QAAQ,QAAQ,IAAI,MAAM;AAChC,QAAI,OAAO;AACT,YAAM,IAAI,MAAM,oBAAoB,IAAI,iBAAiB,KAAK,0BAA0B,MAAM,EAAE;AAAA,IAClG;AACA,YAAQ,IAAI,QAAQ,IAAI;AAAA,EAC1B;AACA,MAAI,CAAC,SAAS,QAAQ,YAAY,GAAG;AACnC,UAAM,IAAI,MAAM,gDAAgD,QAAQ,YAAY,GAAG;AAAA,EACzF;AACF;AAEA,SAAS,WAAW,UAAyB,SAAyB,OAAsB;AAC1F,QAAM,OAAO,SAAS,QAAQ,MAAM;AACpC,MAAI,CAAC,QAAQ,CAAC,OAAO,OAAO,KAAK,QAAQ,QAAQ,KAAK,GAAG;AACvD,UAAM,IAAI,MAAM,mBAAmB,QAAQ,MAAM,IAAI,QAAQ,KAAK,iBAAiB;AAAA,EACrF;AACA,OAAK,OAAO,QAAQ,KAAK,IAAI;AAC/B;AAEA,SAAS,aAAa,SAAkB,UAAqC;AAC3E,MAAI,CAAC,SAAS,OAAO,EAAG,OAAM,IAAI,MAAM,uCAAuC;AAC/E,QAAM,QAAQ,QAAQ,QAAQ;AAC9B,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,CAAC,SAAS,KAAK,EAAG,OAAM,IAAI,MAAM,+CAA+C,QAAQ,EAAE;AAC/F,SAAO;AACT;AAEA,SAAS,aAAa,OAAmB,cAA4C;AACnF,MAAI,CAAC,SAAS,MAAM,OAAO,EAAG,QAAO,IAAI,MAAM,4CAA4C;AAC3F,QAAM,SAAS,MAAM,QAAQ,YAAY;AACzC,MAAI,CAAC,SAAS,MAAM,KAAK,CAAC,MAAM,QAAQ,OAAO,MAAM,GAAG;AACtD,WAAO,IAAI,MAAM,wBAAwB,YAAY,sBAAsB;AAAA,EAC7E;AACA,QAAM,SAAuB,CAAC;AAC9B,aAAW,SAAS,OAAO,QAAQ;AACjC,QACE,CAAC,SAAS,KAAK,KACf,OAAO,MAAM,aAAa,YAC1B,OAAO,MAAM,cAAc,YAC3B,MAAM,SAAS,UACf;AACA,aAAO,IAAI,MAAM,wBAAwB,YAAY,oCAAoC;AAAA,IAC3F;AACA,WAAO,KAAK,EAAE,UAAU,MAAM,UAAU,WAAW,MAAM,WAAW,MAAM,SAAS,CAAC;AAAA,EACtF;AACA,MAAI,CAAC,OAAO,OAAQ,QAAO,IAAI,MAAM,wBAAwB,YAAY,sBAAsB;AAC/F,SAAO;AACT;AAEA,SAAS,cACP,MACA,UACA,cACA,QACY;AACZ,QAAM,UAAU,gBAAgB,IAAI;AACpC,QAAM,SAAS,wBAAwB,KAAK,cAAc;AAC1D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,aAAa,OAAO;AAAA,IACpB,cAAc,QAAQ;AAAA,IACtB,gBAAgB,QAAQ;AAAA,IACxB,OAAO,OAAO,IAAI,CAAC,WAAW,EAAE,GAAG,MAAM,EAAE;AAAA,IAC3C,GAAI,OAAO,KAAK,MAAM,EAAE,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC/C,GAAI,KAAK,WACL;AAAA,MACE,UAAU;AAAA,QACR,MAAM,KAAK,SAAS;AAAA,QACpB,eAAe,KAAK,SAAS;AAAA,QAC7B,cAAc,KAAK,SAAS;AAAA,QAC5B,GAAI,KAAK,SAAS,aACd,EAAE,YAAY,KAAK,SAAS,WAAW,IACvC,CAAC;AAAA,QACL,GAAI,KAAK,SAAS,YAAY,OAAO,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS,SAAS;AAAA,MAC/E;AAAA,IACF,IACA,CAAC;AAAA,EACP;AACF;AAEA,SAAS,mBACP,MACA,KACA,QACA,KACY;AACZ,QAAM,UAAU,gBAAgB,IAAI;AACpC,SAAO;AAAA,IACL,cAAc,QAAQ;AAAA,IACtB,gBAAgB,QAAQ;AAAA,IACxB,cAAc,IAAI;AAAA,IAClB,QAAQ,wBAAwB,KAAK,cAAc;AAAA,IACnD,UAAU;AAAA,MACR,OAAO,OAAO;AAAA,MACd,MAAM,QAAQ,OAAQ;AAAA,MACtB,UAAU,QAAQ,OAAQ;AAAA,MAC1B;AAAA,MACA,WAAW,IAAI;AAAA,MACf,QAAQ,OAAO,IAAI,CAAC,OAAO,WAAW,EAAE,MAAM,UAAU,KAAK,GAAG,GAAG,MAAM,EAAE;AAAA,IAC7E;AAAA,EACF;AACF;AAEA,SAAS,eAAe,UAAyB,SAAkC;AACjF,QAAM,OAAO,SAAS,QAAQ,MAAM;AACpC,SAAO,QAAQ,UAAU,YACtB,MAAM,eAAe,eAAe,MAAM,eAAe;AAC9D;AAEA,SAAS,kBAAkB,OAA4C;AACrE,SAAO,SAAS,KAAK,KACnB,MAAM,SAAS,WACf,OAAO,MAAM,SAAS,YACtB,OAAO,MAAM,WAAW,aACvB,MAAM,WAAW,SAAS,MAAM,WAAW;AAChD;AAEA,SAAS,wBACP,QACyB;AACzB,SAAO,OAAO,YAAY,OAAO,QAAQ,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM;AAAA,IAC5E;AAAA,IACA,MAAM,QAAQ,KAAK,IACf,EAAE,MAAM,YAAY,QAAQ,MAAM,IAAI,4BAA4B,EAAE,IACpE,6BAA6B,KAAK;AAAA,EACxC,CAAC,CAAC;AACJ;AAEA,SAAS,6BAA6B,OAAyB;AAC7D,SAAO,kBAAkB,KAAK,IAC1B,EAAE,MAAM,SAAS,QAAQ,MAAM,QAAQ,QAAQ,MAAM,OAAO,IAC5D,EAAE,MAAM,SAAS,OAAO,MAAM;AACpC;AAEA,SAAS,iBAAiB,OAAsC;AAC9D,MACE,MAAM,UAAU,MAChB,MAAM,aAAa,CAAC,MAAM,cAC1B,MAAM,aAAa,CAAC,MAAM,aAC1B,MAAM,SAAS,SAAS,IAAI,EAAE,MAAM,UACpC,MAAM,aAAa,EAAE,IAAI,KACzB,MAAM,aAAa,EAAE,IAAI,EACzB,QAAO;AAET,MAAI,MAAM,SAAS,KAAK,MAAM,CAAC,MAAM,OAAQ,MAAM,CAAC,MAAM,IAAM,QAAO;AACvE,MAAI,SAAS;AACb,SAAO,SAAS,IAAI,MAAM,QAAQ;AAChC,QAAI,MAAM,MAAM,MAAM,IAAM,QAAO;AACnC,WAAO,MAAM,MAAM,MAAM,IAAM;AAC/B,UAAM,SAAS,MAAM,QAAQ;AAC7B,QAAI,UAAU,QAAQ,WAAW,OAAQ,WAAW,IAAM;AAC1D,QAAI,WAAW,KAAS,UAAU,OAAQ,UAAU,IAAO;AAC3D,QAAI,SAAS,IAAI,MAAM,OAAQ,QAAO;AACtC,UAAM,SAAS,MAAM,aAAa,MAAM;AACxC,QAAI,SAAS,KAAK,SAAS,SAAS,MAAM,OAAQ,QAAO;AACzD,UAAM,iBAAiB,UAAU,OAAQ,UAAU,OAAQ,CAAC,CAAC,KAAM,KAAM,GAAI,EAAE,SAAS,MAAM;AAC9F,QAAI,gBAAgB;AAClB,UAAI,SAAS,EAAG,QAAO;AACvB,aAAO,MAAM,aAAa,SAAS,CAAC,IAAI,KAAK,MAAM,aAAa,SAAS,CAAC,IAAI,IAC1E,SACA;AAAA,IACN;AACA,cAAU;AAAA,EACZ;AACA,SAAO;AACT;AAEA,SAAS,UAAU,UAAkB,cAA8B;AACjE,SAAO,GAAG,QAAQ,IAAI,mBAAmB,YAAY,CAAC;AACxD;AAEA,SAAS,UAAU,OAAuB;AACxC,SAAO,SAAS,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC;AAChD;AAEA,SAAS,kBAAkB,KAA0B;AACnD,SAAO,UAAU,OAAO,KAAK,KAAK,UAAU,GAAG,CAAC,EAAE,SAAS,WAAW,CAAC;AACzE;AAEA,SAAS,kBAAkB,OAA4B;AACrD,MAAI,CAAC,MAAM,WAAW,SAAS,EAAG,OAAM,IAAI,MAAM,qCAAqC,KAAK,GAAG;AAC/F,MAAI;AACJ,MAAI;AACF,YAAQ,KAAK,MAAM,OAAO,KAAK,MAAM,MAAM,CAAC,GAAG,WAAW,EAAE,SAAS,MAAM,CAAC;AAAA,EAC9E,QAAQ;AACN,UAAM,IAAI,MAAM,qCAAqC,KAAK,GAAG;AAAA,EAC/D;AACA,MACE,CAAC,SAAS,KAAK,KACf,OAAO,MAAM,iBAAiB,YAC9B,CAAC,MAAM,gBACP,CAAC,MAAM,QAAQ,MAAM,SAAS,KAC9B,MAAM,UAAU,SAAS,KACzB,MAAM,UAAU,SAAS,MACzB,CAAC,MAAM,UAAU,MAAM,CAAC,OAAO,OAAO,OAAO,YAAY,GAAG,SAAS,CAAC,GACtE;AACA,UAAM,IAAI,MAAM,qCAAqC,KAAK,GAAG;AAAA,EAC/D;AACA,SAAO,EAAE,cAAc,MAAM,cAAc,WAAW,MAAM,UAAsB;AACpF;AAEA,SAAS,UAAU,OAA2D;AAC5E,QAAM,QAAQ,MAAM,YAAY,GAAG;AACnC,MAAI,QAAQ,KAAK,UAAU,MAAM,SAAS,EAAG,OAAM,IAAI,MAAM,2BAA2B,KAAK,GAAG;AAChG,SAAO;AAAA,IACL,UAAU,MAAM,MAAM,GAAG,KAAK;AAAA,IAC9B,cAAc,mBAAmB,MAAM,MAAM,QAAQ,CAAC,CAAC;AAAA,EACzD;AACF;AAEA,SAAS,UAAU,OAA2B;AAC5C,QAAM,MAAM,IAAI,IAAI,kBAAkB;AACtC,MAAI,aAAa,IAAI,YAAY,MAAM,QAAQ;AAC/C,MAAI,aAAa,IAAI,aAAa,MAAM,SAAS;AACjD,MAAI,aAAa,IAAI,QAAQ,MAAM,IAAI;AACvC,SAAO,IAAI,SAAS;AACtB;AAEA,SAAS,YAAY,QAA4B;AAC/C,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,MAAM;AAAA,EACtB,QAAQ;AACN,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AACA,QAAM,WAAW,IAAI,aAAa,IAAI,UAAU;AAChD,QAAM,YAAY,IAAI,aAAa,IAAI,WAAW;AAClD,QAAM,OAAO,IAAI,aAAa,IAAI,MAAM;AACxC,MAAI,IAAI,aAAa,cAAc,IAAI,aAAa,YAAY,CAAC,YAAY,aAAa,QAAQ,SAAS,UAAU;AACnH,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AACA,SAAO,EAAE,UAAU,WAAW,KAAK;AACrC;AAEA,SAAS,iBAAiB,OAAuB;AAC/C,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,KAAK;AAAA,EACrB,QAAQ;AACN,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,MAAI,IAAI,aAAa,WAAW,IAAI,aAAa,UAAU;AACzD,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AACA,MAAI,OAAO;AACX,MAAI,SAAS;AACb,SAAO,IAAI,SAAS,EAAE,QAAQ,OAAO,EAAE;AACzC;AAEA,SAAS,aAAa,QAA4B;AAChD,QAAM,WAAW,MAAM,QAAQ,OAAO,QAAQ,IAAI,OAAO,WAAW,CAAC;AACrE,aAAWK,YAAW,UAAU;AAC9B,QAAI,CAAC,MAAM,QAAQA,QAAO,KAAKA,SAAQ,CAAC,MAAM,qBAAqB,CAAC,SAASA,SAAQ,CAAC,CAAC,EAAG;AAC1F,UAAM,SAASA,SAAQ,CAAC,EAAE;AAC1B,QAAI,OAAO,WAAW,YAAY,OAAO,KAAK,GAAG;AAC/C,aAAO,6BAA6B,OAAO,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC;AAAA,IACjE;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,SAAS,OAA+B;AAC/C,MAAI,CAAC,SAAS,KAAK,EAAG,QAAO;AAC7B,QAAM,MAAM,OAAO,MAAM,UAAU,WAC/B,MAAM,QACN,SAAS,MAAM,KAAK,KAAK,OAAO,MAAM,MAAM,YAAY,WACtD,MAAM,MAAM,UACZ,OAAO,MAAM,YAAY,WACvB,MAAM,UACN;AACR,QAAM,QAAQ,SAAS,MAAM,WAAW,IAAI,OAAO,KAAK,MAAM,WAAW,IAAI,CAAC;AAC9E,MAAI,MAAM,QAAQ;AAChB,WAAO,GAAG,MAAM,GAAG,GAAG,OAAO,EAAE,6BAA6B,MAAM,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,EAC1F;AACA,SAAO,KAAK,KAAK,EAAE,MAAM,GAAG,GAAG,KAAK;AACtC;AAEA,SAAS,eAAe,OAAgB,MAAsB;AAC5D,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,EAAG,OAAM,IAAI,MAAM,WAAW,IAAI,6BAA6B;AAC5G,SAAO,MAAM,KAAK;AACpB;AAEA,SAAS,SAAS,OAAqC;AACrD,SAAO,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,UAAU,OAAyB;AAC1C,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,SAAS;AACpD,MAAI,CAAC,SAAS,KAAK,EAAG,QAAO;AAC7B,SAAO,OAAO;AAAA,IACZ,OAAO,KAAK,KAAK,EACd,KAAK,EACL,IAAI,CAAC,QAAQ,CAAC,KAAK,UAAU,MAAM,GAAG,CAAC,CAAC,CAAC;AAAA,EAC9C;AACF;;;AIvjCA,SAAS,WAAW,cAAAC,aAAY,gBAAAC,eAAc,qBAAqB;AACnE,SAAS,cAAAC,mBAAkB;AAC3B,OAAO,QAAQ;AACf,OAAOC,WAAU;;;ACFjB,SAAS,SAAS;AAYlB,IAAM,OAAO,QAAQ,IAAI,qBAAqB;AAEvC,IAAM,cAAc;AACpB,IAAM,qBAAqB,KAAK,OAAO;AAC9C,IAAM,QAAQ,CAAC,OAAe,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAE3D,SAAS,YAAY,QAAyB;AACnD,SAAO,WAAW,OAAO,WAAW,OAAO,UAAU;AACvD;AAGO,SAAS,UAAU,SAAyB;AACjD,QAAM,OAAO,KAAK,IAAI,MAAO,KAAK,SAAS,IAAM;AACjD,SAAO,OAAO,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAC9C;AAGO,SAAS,aAAa,OAAsB,MAAM,KAAK,IAAI,GAAkB;AAClF,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,UAAU,OAAO,KAAK;AAC5B,MAAI,OAAO,SAAS,OAAO,KAAK,WAAW,EAAG,QAAO,UAAU;AAC/D,QAAM,OAAO,KAAK,MAAM,KAAK;AAC7B,MAAI,CAAC,OAAO,SAAS,IAAI,EAAG,QAAO;AACnC,SAAO,KAAK,IAAI,GAAG,OAAO,GAAG;AAC/B;AAiDA,IAAM,wBAAwB,EAC3B,OAAO;AAAA,EACN,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY;AAAA,EACnD,cAAc,EACX,OAAO;AAAA,IACN,aAAa,EAAE,OAAO;AAAA,IACtB,OAAO,EAAE,OAAO;AAAA,IAChB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACvC,CAAC,EACA,YAAY;AACjB,CAAC,EACA,YAAY;AAEf,IAAM,qBAAqB,EACxB,OAAO;AAAA,EACN,mBAAmB,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACnC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC3B,QAAQ,EAAE,OAAO,EAAE,QAAQ,QAAQ;AAAA,EACnC,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAClC,CAAC,EACA,YAAY;AACf,IAAM,kBAAkB,EACrB,OAAO;AAAA,EACN,mBAAmB,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACnC,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC3B,QAAQ,EAAE,OAAO,EAAE,QAAQ,YAAY;AACzC,CAAC,EACA,YAAY;AACf,IAAM,oBAAoB,EACvB,OAAO;AAAA,EACN,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACzB,mBAAmB,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACnC,QAAQ,EAAE,QAAQ,YAAY,EAAE,QAAQ,YAAY;AACtD,CAAC,EACA,YAAY;AACf,IAAM,iBAAiB,EACpB,OAAO;AAAA,EACN,cAAc,EAAE,OAAO,EAAE,OAAO,CAAC;AAAA,EACjC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EACxC,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAS;AACxD,CAAC,EACA,YAAY;AACf,IAAM,uBAAuB,EAC1B,OAAO;AAAA,EACN,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACpB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EACxC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE;AAAA,EAC7B,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,GAAG,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AAAA,EAC1F,YAAY,EAAE,OAAO,EAAE,QAAQ,CAAC;AAAA,EAChC,YAAY,EAAE,OAAO;AAAA,EACrB,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EACxC,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC5C,eAAe,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EACnE,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EACpD,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EACpC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EAC1C,kBAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACjD,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAC9C,CAAC,EACA,YAAY;AACf,IAAM,kBAAkB,EACrB,OAAO;AAAA,EACN,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC3B,QAAQ,EAAE,OAAO;AAAA,EACjB,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EAC/C,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EACzC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EAC1C,cAAc,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAClD,CAAC,EACA,YAAY;AACf,IAAM,mBAAmB,EACtB,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,GAAG,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,EACjF,YAAY;AACf,IAAM,wBAAwB,EAC3B,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,YAAY,GAAG,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EACtG,YAAY;AACf,IAAM,qBAAqB,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,YAAY;AAE7F,SAAS,iBACP,QACA,KACA,WACa;AACb,QAAM,SAAS,OAAO,UAAU,GAAG;AACnC,MAAI,OAAO,QAAS,QAAO,OAAO;AAClC,QAAM,SAAS,OAAO,MAAM,OACzB,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,MAAM,GAAG,EAAE,KAAK,KAAK,GAAG,KAAK,UAAU,KAAK,EAAE,OAAO,EAAE,EAC5D,KAAK,IAAI;AACZ,QAAM,IAAI,MAAM,iCAAiC,SAAS,KAAK,MAAM,EAAE;AACzE;AAEO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YACEC,UACS,QACA,MACT;AACA,UAAMA,QAAO;AAHJ;AACA;AAGT,SAAK,OAAO;AAAA,EACd;AAAA,EALW;AAAA,EACA;AAKb;AAEO,IAAM,iBAAN,MAAqB;AAAA,EAC1B,YACmB,QACA,YAAY,MAC7B;AAFiB;AACA;AAEjB,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,8BAA8B;AAAA,EAC7D;AAAA,EAJmB;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcnB,MAAc,QAAWC,QAAc,MAAoB,UAAU,GAAe;AAClF,UAAM,OAAO,KAAK,OAAO,WAAW,SAAS,IAAI,KAAK,SAAS,UAAU,KAAK,MAAM;AACpF,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,MAAM,GAAG,IAAI,GAAGA,MAAI,IAAI;AAAA,QAClC,GAAG;AAAA,QACH,QAAQ,MAAM,UAAU,YAAY,QAAQ,KAAK,SAAS;AAAA,QAC1D,SAAS;AAAA,UACP,eAAe;AAAA,UACf,gBAAgB;AAAA,UAChB,GAAI,MAAM,WAAW,CAAC;AAAA,QACxB;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,UAAU,aAAa;AACzB,cAAM,MAAM,UAAU,OAAO,CAAC;AAC9B,eAAO,KAAK,QAAWA,QAAM,MAAM,UAAU,CAAC;AAAA,MAChD;AACA,YAAM;AAAA,IACR;AAEA,QAAI,CAAC,IAAI,MAAM,YAAY,IAAI,MAAM,KAAK,UAAU,aAAa;AAE/D,YAAM,SAAS,aAAa,IAAI,QAAQ,IAAI,aAAa,CAAC,KAAK,UAAU,OAAO;AAChF,YAAM,MAAM,MAAM;AAClB,aAAO,KAAK,QAAWA,QAAM,MAAM,UAAU,CAAC;AAAA,IAChD;AAEA,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,cAAc,GAAG,MAAM,UAAU,KAAK,IAAIA,MAAI,WAAM,IAAI,MAAM,IAAI,IAAI,QAAQ,IAAI;AAAA,IAC9F;AACA,QAAI,CAAC,KAAM,QAAO,CAAC;AACnB,QAAI;AACF,aAAO,KAAK,MAAM,IAAI;AAAA,IACxB,QAAQ;AACN,YAAM,IAAI,MAAM,GAAG,MAAM,UAAU,KAAK,IAAIA,MAAI,wBAAwB;AAAA,IAC1E;AAAA,EACF;AAAA,EAEA,MAAM,UAA4B;AAChC,UAAM,MAAM,iBAAiB,uBAAuB,MAAM,KAAK,QAAiB,UAAU,GAAG,SAAS;AACtG,WAAO;AAAA,MACL,KAAK,IAAI,SAAS,OAAO;AAAA,MACzB,aAAa,IAAI,cAAc,eAAe;AAAA,MAC9C,OAAO,IAAI,cAAc,SAAS;AAAA,MAClC,MAAM,IAAI,cAAc,QAAQ;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,iBAAiB,MAM8C;AACnE,UAAM,OAAgC,EAAE,aAAa,KAAK,YAAY;AACtE,QAAI,KAAK,aAAa,QAAQ;AAC5B,WAAK,eAAe,KAAK,YAAY,IAAI,CAAC,EAAE,QAAQ,OAAO,OAAO;AAAA,QAChE,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF,EAAE;AAAA,IACJ,WAAW,KAAK,QAAQ,MAAM;AAC5B,WAAK,OAAO,KAAK;AAAA,IACnB;AACA,QAAI,KAAK,KAAM,MAAK,OAAO,KAAK;AAChC,QAAI,KAAK,kBAAkB,OAAQ,MAAK,oBAAoB,KAAK;AACjE,UAAM,MAAM,MAAM,KAAK,QAAiB,8BAA8B;AAAA,MACpE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,UAAM,SAAS,iBAAiB,oBAAoB,KAAK,2BAA2B;AACpF,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,gBAAgB,MAS6B;AACjD,UAAM,OAAgC;AAAA,MACpC,aAAa,KAAK;AAAA,MAClB,YAAY,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,IACvD;AACA,QAAI,KAAK,KAAM,MAAK,OAAO,KAAK;AAChC,QAAI,KAAK,QAAS,MAAK,UAAU,KAAK;AACtC,QAAI,KAAK,QAAS,MAAK,UAAU,KAAK;AACtC,QAAI,KAAK,OAAQ,MAAK,SAAS,KAAK;AACpC,QAAI,KAAK,QAAQ,KAAM,MAAK,OAAO,KAAK;AACxC,WAAO;AAAA,MACL;AAAA,MACA,MAAM,KAAK,QAAiB,gBAAgB,EAAE,QAAQ,QAAQ,MAAM,KAAK,UAAU,IAAI,EAAE,CAAC;AAAA,MAC1F;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,eAAe,MASuD;AAC1E,UAAM,OAAgC,EAAE,aAAa,KAAK,YAAY;AACtE,QAAI,KAAK,YAAY,KAAM,MAAK,YAAY,KAAK;AACjD,QAAI,KAAK,SAAU,MAAK,YAAY,KAAK;AACzC,QAAI,KAAK,SAAU,MAAK,YAAY,KAAK;AACzC,QAAI,KAAK,YAAa,MAAK,eAAe,KAAK;AAC/C,QAAI,KAAK,YAAa,MAAK,eAAe,KAAK;AAC/C,QAAI,KAAK,QAAQ,KAAM,MAAK,OAAO,KAAK;AACxC,QAAI,KAAK,aAAa,OAAQ,MAAK,eAAe,KAAK;AACvD,WAAO;AAAA,MACL;AAAA,MACA,MAAM,KAAK,QAAiB,qBAAqB,EAAE,QAAQ,QAAQ,MAAM,KAAK,UAAU,IAAI,EAAE,CAAC;AAAA,MAC/F;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,YAAY,QAAmC;AACnD,WAAO;AAAA,MACL;AAAA,MACA,MAAM,KAAK,QAAiB,cAAc,MAAM,EAAE;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mBAAmB,MAOoB;AAC3C,UAAM,OAAgC;AAAA,MACpC,aAAa,KAAK;AAAA,MAClB,YAAY,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,MACrD,eAAe,KAAK,gBAAgB;AAAA,IACtC;AACA,QAAI,KAAK,qBAAqB;AAC5B,WAAK,cAAc,EAAE,MAAM,UAAU,QAAQ,KAAK,qBAAqB,QAAQ,MAAM;AAAA,IACvF;AACA,QAAI,KAAK,QAAQ,KAAM,MAAK,OAAO,KAAK;AAExC,UAAM,MAAM;AAAA,MACV;AAAA,MACA,MAAM,KAAK,QAAiB,yBAAyB;AAAA,QACnD,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,IAAI;AAAA,MAC3B,CAAC;AAAA,MACD;AAAA,IACF;AACA,UAAM,MAAM,IAAI,MAAM;AACtB,WAAO,EAAE,KAAK,OAAO,KAAK,KAAK,QAAQ,GAAG,OAAO,IAAI,MAAM;AAAA,EAC7D;AAAA,EAEA,MAAM,UAAU,UAA2C;AACzD,WAAO;AAAA,MACL;AAAA,MACA,MAAM,KAAK,QAAiB,YAAY,QAAQ,EAAE;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,UAAsC;AACvD,WAAO;AAAA,MACL;AAAA,MACA,MAAM,KAAK,QAAiB,gBAAgB,QAAQ,EAAE;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,QAAQ,IAAI,SAAS,GAA0D;AAC/F,WAAO;AAAA,MACL;AAAA,MACA,MAAM,KAAK,QAAiB,kBAAkB,KAAK,WAAW,MAAM,EAAE;AAAA,MACtE;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,eAAe,WAAW,KAAqC;AACpE,QAAI,SAAS;AACb,eAAS;AACP,YAAM,OAAO,MAAM,KAAK,YAAY,UAAU,MAAM;AACpD,iBAAW,OAAO,KAAK,QAAS,OAAM;AACtC,gBAAU,KAAK,QAAQ;AACvB,UAAI,KAAK,QAAQ,WAAW,KAAK,UAAU,KAAK,MAAO;AAAA,IACzD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aACJ,UACA,SACA,WAC4C;AAC5C,UAAM,MAAM,MAAM,KAAK,QAAiB,YAAY,QAAQ,kBAAkB;AAAA,MAC5E,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,YAAY,EAAE,SAAS,YAAY,UAAU,IAAI,EAAE,QAAQ,CAAC;AAAA,IACnF,CAAC;AACD,WAAO,iBAAiB,oBAAoB,KAAK,eAAe;AAAA,EAClE;AAAA;AAAA,EAGA,aAAa,UAAoC;AAC/C,WAAO,KAAK,QAAQ,YAAY,QAAQ,IAAI,EAAE,QAAQ,SAAS,CAAC;AAAA,EAClE;AAAA,EAEA,cAAc,UAAoC;AAChD,WAAO,KAAK,QAAQ,YAAY,QAAQ,mBAAmB,EAAE,QAAQ,OAAO,CAAC;AAAA,EAC/E;AAAA;AAAA,EAGA,QAAQ,UAAkB,MAAkC;AAC1D,WAAO,KAAK,QAAQ,YAAY,QAAQ,SAAS,EAAE,QAAQ,SAAS,MAAM,KAAK,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;AAAA,EACtG;AAAA;AAAA,EAGA,MAAM,SAAS,KAA8B;AAC3C,UAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,YAAY,QAAQ,KAAK,SAAS,EAAE,CAAC;AAC5E,QAAI,CAAC,IAAI,GAAI,OAAM,IAAI,cAAc,YAAY,GAAG,WAAM,IAAI,MAAM,IAAI,IAAI,QAAQ,EAAE;AACtF,UAAM,WAAW,OAAO,IAAI,QAAQ,IAAI,gBAAgB,CAAC;AACzD,QAAI,OAAO,SAAS,QAAQ,KAAK,WAAW,oBAAoB;AAC9D,YAAM,IAAI,MAAM,YAAY,GAAG,gBAAgB,kBAAkB,oBAAoB;AAAA,IACvF;AACA,UAAM,MAAM,OAAO,KAAK,MAAM,IAAI,YAAY,CAAC;AAC/C,QAAI,IAAI,SAAS,oBAAoB;AACnC,YAAM,IAAI,MAAM,YAAY,GAAG,gBAAgB,kBAAkB,oBAAoB;AAAA,IACvF;AACA,WAAO;AAAA,EACT;AACF;AAEO,SAAS,gBAAgC;AAC9C,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO,IAAI,eAAe,GAAG;AAC/B;;;AC/eA,SAAS,KAAAC,UAAS;AAElB,IAAM,kBAAkBA,GAAE,KAAK,CAAC,aAAa,WAAW,CAAC;AAiClD,IAAM,kBAAkBA,GAAE,KAAK,CAAC,QAAQ,OAAO,WAAW,SAAS,aAAa,QAAQ,CAAC;AAGzF,IAAM,uBAAuBA,GAAE,KAAK,CAAC,OAAO,UAAU,MAAM,CAAC;AAG7D,IAAM,qBAAqBA,GAAE,KAAK,CAAC,kBAAkB,WAAW,UAAU,CAAC;AAwC3E,SAAS,mBAAmB,cAA8B;AAC/D,SAAO,KAAK,IAAI,GAAG,YAAY,IAAI;AACrC;AAGO,SAAS,uBAAuB,SAA4C;AACjF,MAAI,YAAY,QAAS,QAAO;AAChC,MAAI,YAAY,UAAW,QAAO;AAGlC,SAAO;AACT;AAOO,SAAS,0BAA0B,QAAwB;AAChE,UAAQ,OAAO,MAAM,gBAAgB,KAAK,CAAC,GAAG;AAChD;AAGO,SAAS,eAAe,MAAsB;AACnD,MAAI,QAAQ,GAAI,QAAO;AACvB,MAAI,QAAQ,GAAI,QAAO;AACvB,MAAI,QAAQ,IAAK,QAAO;AACxB,SAAO;AACT;AAyBO,SAAS,eACd,OACA,QACA,YAAuB,OACf;AACR,MAAI,cAAc,SAAS,cAAc,UAAW,QAAO;AAC3D,QAAM,KAAK,QAAQ;AACnB,MAAI,MAAM,KAAM,QAAO;AACvB,MAAI,MAAM,KAAM,QAAO;AACvB,SAAO;AACT;AAaO,SAAS,UAAU,UAAkB,YAA4B;AACtE,QAAM,KAAK,WAAW,WAAW,KAAK,IAAI,GAAG,UAAU;AACvD,MAAI,MAAM,KAAM,QAAO;AACvB,MAAI,MAAM,KAAM,QAAO;AACvB,SAAO;AACT;AAEA,IAAM,mBAAmBA,GAAE,OAAO;AAAA;AAAA,EAEhC,MAAMA,GAAE,OAAO;AACjB,CAAC;AAED,IAAM,iBAAiBA,GAAE,OAAO,EAAE,MAAM,oBAAoB,iCAAiC;AAG7F,IAAM,6BAA6BA,GAChC,OAAO;AAAA;AAAA,EAEN,QAAQA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAExB,SAASA,GAAE,MAAM,cAAc,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA;AAAA,EAE/C,mBAAmB,qBAAqB,QAAQ,MAAM;AAAA;AAAA,EAEtD,iBAAiBA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA,EAEnD,eAAeA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA,EAE1C,aAAaA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA,EAExC,KAAKA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,SAAS;AAChD,CAAC,EACA,OAAO;AAEH,IAAM,uBAAuB,2BACjC;AAAA,EACC,CAAC,YACC,IAAI,IAAI,QAAQ,QAAQ,IAAI,CAAC,UAAU,MAAM,QAAQ,MAAM,EAAE,EAAE,YAAY,CAAC,CAAC,EAAE,SAC/E,QAAQ,QAAQ;AAAA,EAClB,EAAE,SAAS,yCAAyC,MAAM,CAAC,SAAS,EAAE;AACxE;AAgBK,IAAM,iBAAiBA,GAC3B,OAAO;AAAA;AAAA,EAEN,MAAM;AAAA;AAAA,EAEN,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAEtB,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA,EAEjC,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAC9C,CAAC,EACA,OAAO,EACP,YAAY,CAAC,UAAU,YAAY;AAClC,MAAI,SAAS,SAAS,aAAa,CAAC,SAAS,MAAM;AACjD,YAAQ,SAAS;AAAA,MACf,MAAMA,GAAE,aAAa;AAAA,MACrB,SAAS;AAAA,MACT,MAAM,CAAC,MAAM;AAAA,IACf,CAAC;AAAA,EACH;AACA,MAAI,SAAS,SAAS,aAAa,SAAS,MAAM;AAChD,YAAQ,SAAS;AAAA,MACf,MAAMA,GAAE,aAAa;AAAA,MACrB,SAAS,GAAG,SAAS,IAAI;AAAA,MACzB,MAAM,CAAC,MAAM;AAAA,IACf,CAAC;AAAA,EACH;AACF,CAAC;AAyBH,IAAM,oBAAoBA,GACvB,OAAO;AAAA;AAAA,EAEN,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA,EAGrC,WAAW,gBAAgB,QAAQ,KAAK;AAAA;AAAA,EAExC,MAAMA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,EAAE,SAAS;AAAA,EAClD,MAAMA,GAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE1B,cAAcA,GAAE,OAAO,EAAE,QAAQ,EAAE;AAAA;AAAA,EAEnC,cAAcA,GAAE,OAAO,EAAE,QAAQ,EAAE;AAAA;AAAA,EAEnC,aAAaA,GAAE,MAAM,gBAAgB,EAAE,QAAQ,CAAC,CAAC;AAAA;AAAA,EAEjD,QAAQA,GAAE,OAAO;AAAA;AAAA,EAEjB,SAASA,GAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,SAASA,GAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,QAAQA,GAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ5B,UAAUA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA;AAAA,EAErD,UAAUA,GACP,KAAK,CAAC,OAAO,cAAc,aAAa,WAAW,WAAW,gBAAgB,CAAC,EAC/E,SAAS;AAAA;AAAA,EAEZ,UAAUA,GAAE,KAAK,CAAC,YAAY,iBAAiB,gBAAgB,MAAM,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcjF,aAAaA,GAAE,KAAK,CAAC,SAAS,WAAW,UAAU,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAc/D,aAAaA,GAAE,KAAK,CAAC,WAAW,cAAc,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAY1D,cAAcA,GAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA;AAAA,EAEtC,MAAMA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWhC,SAASA,GACN,MAAM,cAAc,EACpB,QAAQ,CAAC,CAAC;AAAA;AAAA,EAEb,SAAS,qBAAqB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWvC,OAAOA,GACJ,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAON,MAAMA,GAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,WAAWA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,IACrC,YAAYA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA;AAAA,IAEtC,KAAKA,GAAE,OAAO;AAAA,EAChB,CAAC,EACA,OAAO,EACP,SAAS;AAAA;AAAA,EAEZ,MAAMA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA;AAAA,EAEpC,iBAAiBA,GAAE,OAAOA,GAAE,OAAOA,GAAE,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAC7D,CAAC,EACA,OAAO;AAEH,IAAM,cAAc,kBASxB,OAAO,CAAC,MAAM,EAAE,EAAE,eAAe,EAAE,YAAY,SAAS;AAAA,EACvD,SACE;AAAA,EAEF,MAAM,CAAC,aAAa;AACtB,CAAC,EACA,YAAY,CAAC,OAAO,QAAQ;AAC3B,MAAI,MAAM,YAAY,MAAM,cAAc,WAAW,MAAM,cAAc,cAAc;AACrF,QAAI,SAAS;AAAA,MACX,MAAMA,GAAE,aAAa;AAAA,MACrB,SAAS;AAAA,MACT,MAAM,CAAC,SAAS;AAAA,IAClB,CAAC;AAAA,EACH;AACF,CAAC;AAMI,IAAM,uBAAuB,kBAAkB,QAAQ,EAC3D,OAAO;AAAA,EACN,SAASA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAEzB,QAAQA,GAAE,OAAO;AAAA;AAAA,EAEjB,SAAS,2BAA2B,QAAQ,EAAE,SAAS;AACzD,CAAC,EACA,OAAO;AAEH,IAAM,mBAAmBA,GAAE,MAAM,CAAC,aAAa,oBAAoB,CAAC;AAGpE,IAAM,cAAcA,GACxB,OAAO;AAAA;AAAA,EAEN,QAAQA,GAAE,OAAO;AAAA;AAAA,EAEjB,UAAUA,GAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE9B,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,EAAE,SAAS;AAAA,EACnD,QAAQA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,IAAI,EAAE,SAAS;AAAA;AAAA,EAEpD,MAAMA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA;AAAA,EAEjD,MAAMA,GAAE,OAAO,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS1B,MAAMA,GAAE,MAAM,CAACA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,GAAGA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiB3E,QAAQA,GAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EAE5B,UAAU,eAAe,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMlC,YAAYA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACvC,MAAMA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA;AAAA,EAEpC,QAAQA,GAAE,MAAMA,GAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWtC,eAAeA,GAAE,OAAOA,GAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM9C,gBAAgBA,GACb,OAAOA,GAAE,MAAM;AAAA,IACdA,GAAE,OAAO;AAAA,IACTA,GAAE,OAAO,EAAE,OAAO;AAAA,IAClBA,GAAE,QAAQ;AAAA,IACVA,GAAE,MAAMA,GAAE,MAAM,CAACA,GAAE,OAAO,GAAGA,GAAE,OAAO,EAAE,OAAO,GAAGA,GAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,EAChF,CAAC,CAAC,EACD,QAAQ,CAAC,CAAC;AACf,CAAC,EACA,OAAO,EACP,YAAY,CAAC,OAAO,YAAY;AAC/B,MAAI,MAAM,UAAU,MAAM,UAAU;AAClC,YAAQ,SAAS;AAAA,MACf,MAAMA,GAAE,aAAa;AAAA,MACrB,SAAS;AAAA,MACT,MAAM,CAAC,UAAU;AAAA,IACnB,CAAC;AAAA,EACH;AACF,CAAC;AAEI,IAAM,iBAAiBA,GAC3B,OAAO;AAAA,EACN,SAASA,GAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,MAAMA,GAAE,OAAO;AAAA;AAAA,EAEf,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,UAAU;AAAA,EAC9C,QAAQA,GAAE,OAAO,WAAW;AAAA,EAC5B,QAAQA,GAAE,OAAO,WAAW;AAC9B,CAAC,EACA,OAAO;AAGH,IAAM,sBAAsBA,GAChC,OAAO;AAAA,EACN,SAASA,GAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,MAAMA,GAAE,OAAO;AAAA,EACf,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,UAAU;AAAA,EAC9C,QAAQA,GAAE,OAAO,gBAAgB;AAAA,EACjC,QAAQA,GAAE,OAAO,WAAW;AAC9B,CAAC,EACA,OAAO;AAYH,IAAM,kBAAkBA,GAAE,OAAO;AAAA,EACtC,SAASA,GAAE,OAAO;AAAA,EAClB,SAASA,GAAE,OAAO;AAAA;AAAA,EAElB,UAAUA,GAAE,OAAO;AAAA,EACnB,WAAW;AAAA;AAAA,EAEX,aAAaA,GAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA;AAAA,EAE/C,QAAQA,GAAE,OAAO;AAAA,EACjB,OAAOA,GAAE,OAAO,EAAE,IAAI;AAAA,EACtB,QAAQA,GAAE,OAAO,EAAE,IAAI;AAAA;AAAA,EAEvB,UAAUA,GACP,OAAO;AAAA,IACN,MAAM;AAAA,IACN,eAAeA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IAC/B,cAAcA,GAAE,OAAO,EAAE,MAAM,gBAAgB;AAAA,IAC/C,YAAYA,GAAE,OAAO,EAAE,MAAM,gBAAgB,EAAE,SAAS;AAAA,IACxD,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC9C,CAAC,EACA,OAAO,EACP,SAAS,EACT,QAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,EAMf,mBAAmBA,GAChB;AAAA,IACCA,GAAE,OAAO;AAAA,MACP,MAAMA,GAAE,OAAO;AAAA,MACf,QAAQA,GAAE,OAAO;AAAA,MACjB,MAAMA,GAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,WAAW,gBAAgB,SAAS;AAAA,IACtC,CAAC;AAAA,EACH,EACC,SAAS;AAAA;AAAA,EAGZ,OAAOA,GAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA;AAAA,EAEzC,gBAAgBA,GAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA;AAAA,EAElD,UAAUA,GAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EAC5C,gBAAgBA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EAExD,QAAQA,GACL,KAAK;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC,EACA,QAAQ,SAAS;AAAA,EACpB,OAAOA,GAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EAEzC,WAAWA,GAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA;AAAA,EAE7C,YAAYA,GACT;AAAA,IACCA,GAAE,OAAO;AAAA,MACP,KAAKA,GAAE,OAAO;AAAA,MACd,MAAMA,GAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,WAAW,gBAAgB,SAAS;AAAA,IACtC,CAAC;AAAA,EACH,EACC,QAAQ,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUb,SAASA,GACN;AAAA,IACCA,GAAE,OAAO;AAAA,MACP,MAAMA,GAAE,OAAO;AAAA,MACf,QAAQA,GAAE,OAAO;AAAA,MACjB,MAAMA,GAAE,OAAO,EAAE,SAAS;AAAA,MAC1B,WAAW,gBAAgB,SAAS;AAAA,IACtC,CAAC;AAAA,EACH,EACC,QAAQ,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOb,kBAAkBA,GAAE,OAAOA,GAAE,OAAOA,GAAE,QAAQ,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EAE5D,aAAaA,GAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA,EAC/C,cAAcA,GAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAAA;AAAA,EAEhD,MAAMA,GAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,CAAC;AAAA;AAAA,EAEjD,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,aAAa;AAAA;AAAA,EAEjD,UAAUA,GAAE,OAAO,EAAE,QAAQ,UAAU;AACzC,CAAC;AAEM,IAAM,aAAaA,GAAE,OAAO;AAAA,EACjC,SAASA,GAAE,QAAQ,CAAC;AAAA,EACpB,SAASA,GAAE,OAAO,eAAe;AACnC,CAAC;AAcM,SAAS,UAAU,KAAoB;AAC5C,QAAM,SAAS,WAAW,UAAU,GAAG;AACvC,MAAI,OAAO,QAAS,QAAO,OAAO;AAClC,QAAM,IAAI;AAAA,IACR;AAAA,EAA8B,OAAO,MAAM,OACxC,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,MAAM,KAAK,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAChD,KAAK,IAAI,CAAC;AAAA,EACf;AACF;AAQO,SAAS,QAAQ,SAAiB,SAAyB;AAChE,SAAO,GAAG,OAAO,IAAI,OAAO;AAC9B;;;AFjqBO,IAAM,mBAAN,MAAM,kBAAqC;AAAA,EAGhD,YAA6B,QAAwB;AAAxB;AAAA,EAAyB;AAAA,EAAzB;AAAA,EAFpB,KAAK;AAAA,EAId,OAAO,UAA4B;AACjC,WAAO,IAAI,kBAAiB,cAAc,CAAC;AAAA,EAC7C;AAAA;AAAA,EAGA,OAAO,eAAiC;AACtC,WAAO,kBAAiB,WAAW;AAAA,EACrC;AAAA;AAAA,EAGA,OAAO,aAA+B;AACpC,WAAO,IAAI,kBAAiB,IAAI,eAAe,eAAe,CAAC;AAAA,EACjE;AAAA,EAEA,SAAS,WAA+B;AACtC,WACE,cAAc,UACd,cAAc,SACd,cAAc,aACd,cAAc;AAAA,EAElB;AAAA;AAAA;AAAA;AAAA,EAKA,YAAuB;AACrB,WAAO,EAAE,WAAW,MAAM,aAAa,EAAE;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,OAAe,WAAmB;AAChC,UAAM,MAAMC,MAAK,KAAK,GAAG,OAAO,GAAG,mBAAmB;AACtD,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAClC,WAAO;AAAA,EACT;AAAA,EAEA,SAAS,MAAkC;AAGzC,QAAI,KAAK,cAAc,SAAS;AAC9B,aAAO,EAAE,MAAM,eAAe,QAAQ,KAAK,MAAM,YAAY,KAAK,WAAW;AAAA,IAC/E;AACA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,eAAe,KAAK,OAAO,KAAK,QAAQ,KAAK,SAAS;AAAA,MAC9D,YAAY,KAAK,cAAc,SAAS,eAAe,KAAK,IAAI,IAAI;AAAA,IACtE;AAAA,EACF;AAAA,EAEA,SAAS,MAAoB,aAAyC;AACpE,QAAI,KAAK,cAAc,WAAW,KAAK,QAAQ,MAAM,KAAK,QAAQ,MAAM;AACtE,YAAM,IAAI,MAAM,4DAA4D;AAAA,IAC9E;AACA,SACG,KAAK,cAAc,SAAS,KAAK,cAAc,eAC/C,KAAK,QAAQ,MAAM,KAAK,SAAS,MAAM,KAAK,QAAQ,OAAO,KAAK,SAAS,MAC1E;AACA,YAAM,IAAI,MAAM,YAAY,KAAK,SAAS,+CAA+C;AAAA,IAC3F;AACA,QAAI,KAAK,cAAc,OAAO;AAC5B,4BAAsB,QAAQ,KAAK,MAAM,CAAC,gBAAgB,iBAAiB,MAAM,CAAC;AAClF,4BAAsB,WAAW,KAAK,SAAS;AAAA,QAC7C;AAAA,QAAwB;AAAA,QAAqB;AAAA,MAC/C,CAAC;AACD,4BAAsB,WAAW,KAAK,SAAS;AAAA,QAC7C;AAAA,QAAgB;AAAA,QAAiB;AAAA,QAAkB;AAAA,MACrD,CAAC;AACD,4BAAsB,UAAU,KAAK,QAAQ;AAAA,QAC3C;AAAA,QAAc;AAAA,QAAiB;AAAA,MACjC,CAAC;AAAA,IACH;AACA,SAAK,KAAK,cAAc,SAAS,KAAK,cAAc,cAAc,YAAY,QAAQ;AACpF,YAAM,IAAI,MAAM,YAAY,KAAK,SAAS,gCAAgC;AAAA,IAC5E;AACA,eAAW,SAAS,aAAa;AAC/B,UAAI,MAAM,QAAQ,OAAO,MAAM,SAAS,KAAK;AAC3C,cAAM,IAAI;AAAA,UACR,iDAAiD,MAAM,KAAK,IAAI,MAAM,MAAM;AAAA,QAC9E;AAAA,MACF;AAAA,IACF;AACA,QAAI,KAAK,KAAK,SAAS,IAAI;AACzB,YAAM,IAAI;AAAA,QACR,GAAG,KAAK,OAAO,IAAI,KAAK,OAAO,gBAAgB,KAAK,KAAK,MAAM;AAAA,MAEjE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,MAAoB,aAA+D;AAC9F,SAAK,SAAS,MAAM,WAAW;AAC/B,QAAI,KAAK,cAAc,WAAW;AAChC,YAAM,SAAS,KAAK,QAAQ,SACxB,cAAc,KAAK,OAAO,EAAE,SAAS,QAAQ,IAC7C;AACJ,YAAM,EAAE,IAAI,IAAI,MAAM,KAAK,OAAO,mBAAmB;AAAA,QACnD,aAAa,KAAK;AAAA,QAClB,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,QACb,cAAc,KAAK;AAAA,QACnB,qBAAqB;AAAA,QACrB,MAAM,KAAK;AAAA,MACb,CAAC;AACD,YAAM,QAAQC,YAAW;AACzB,oBAAcD,MAAK,KAAK,kBAAiB,SAAS,GAAG,GAAG,KAAK,MAAM,GAAG,GAAG;AACzE,aAAO,EAAE,MAAM;AAAA,IACjB;AAEA,QAAI,KAAK,cAAc,SAAS;AAC9B,YAAME,OAAM,MAAM,KAAK,OAAO,eAAe;AAAA,QAC3C,aAAa,KAAK;AAAA,QAClB,UAAU,KAAK;AAAA,QACf,UAAU,KAAK;AAAA,QACf,UAAU,KAAK;AAAA,QACf,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK;AAAA,QAClB,MAAM,KAAK;AAAA;AAAA;AAAA,QAGX,aAAa,YAAY,IAAI,CAAC,EAAE,QAAQ,OAAO,OAAO,OAAO,EAAE,QAAQ,OAAO,OAAO,EAAE;AAAA,MACzF,CAAC;AACD,aAAO,EAAE,OAAOA,KAAI,QAAQ;AAAA,IAC9B;AAEA,QAAI,KAAK,cAAc,QAAQ;AAC7B,YAAMA,OAAM,MAAM,KAAK,OAAO,iBAAiB;AAAA,QAC7C,aAAa,KAAK;AAAA,QAClB,MAAM,KAAK;AAAA,QACX,MAAM,KAAK,SAAS,iBAAiB,iBAAiB;AAAA,QACtD;AAAA,MACF,CAAC;AACD,aAAO,EAAE,OAAOA,KAAI,UAAU;AAAA,IAChC;AACA,UAAM,MAAM,MAAM,KAAK,OAAO,gBAAgB;AAAA,MAC5C,aAAa,KAAK;AAAA,MAClB,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,MACX,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,QAAQ,KAAK;AAAA,MACb,MAAM,KAAK;AAAA,IACb,CAAC;AACD,WAAO,EAAE,OAAO,IAAI,UAAU;AAAA,EAChC;AAAA,EAEA,MAAM,KAAK,OAAe,WAAsB,SAA0C;AACxF,QAAI,cAAc,WAAW;AAC3B,YAAM,OAAOF,MAAK,KAAK,kBAAiB,SAAS,GAAG,GAAG,KAAK,MAAM;AAClE,UAAIG,YAAW,IAAI,GAAG;AACpB,cAAM,YAAY,UAAU,IAAI;AAChC,eAAO,EAAE,QAAQ,SAAS,UAAU,OAAO,WAAW,SAAS,CAAC,EAAE,KAAK,UAAU,CAAC,EAAE;AAAA,MACtF;AAGA,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO;AAAA,MACT;AAAA,IACF;AACA,QAAI,cAAc,MAAO,QAAO,KAAK,QAAQ,KAAK;AAClD,QAAI,cAAc,QAAS,QAAO,KAAK,UAAU,OAAO,QAAQ,SAAS,WAAW,CAAC;AAErF,UAAM,MAAM,MAAM,KAAK,OAAO,UAAU,KAAK;AAC7C,QAAI,IAAI,WAAW,UAAU;AAC3B,aAAO,EAAE,QAAQ,UAAU,eAAe,IAAI,cAAc,CAAC,EAAE;AAAA,IACjE;AACA,QAAI,IAAI,WAAW,aAAa;AAC9B,YAAM,MAAM,SAAS,IAAI,aAAa,KAAK,IAAI,eAAe;AAC9D,aAAO,EAAE,QAAQ,SAAS,UAAU,IAAI,IAAI,WAAW,KAAK,SAAS,MAAM,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE;AAAA,IAC5F;AACA,QAAI,IAAI,WAAW,SAAU,QAAO,EAAE,QAAQ,UAAU,OAAO,6BAA6B;AAC5F,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,iBAAiB,IAAI,oBAAoB;AAAA,MACzC,YAAY,IAAI,eAAe;AAAA,IACjC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,QAAQ,OAAkC;AACtD,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,OAAO,aAAa,KAAK;AAChD,UAAI,IAAI,WAAW,eAAe,IAAI,cAAc;AAClD,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,WAAW,IAAI;AAAA,UACf,SAAS,CAAC,EAAE,KAAK,IAAI,aAAa,CAAC;AAAA,QACrC;AAAA,MACF;AACA,UAAI,IAAI,WAAW,SAAU,QAAO,EAAE,QAAQ,UAAU,OAAO,6BAA6B;AAC5F,aAAO,EAAE,QAAQ,aAAa;AAAA,IAChC,SAAS,KAAK;AACZ,UAAI,EAAE,eAAe,kBAAkB,IAAI,WAAW,IAAK,OAAM;AACjE,YAAM,WAAW,MAAM,KAAK,OAAO,UAAU,KAAK,EAAE,MAAM,MAAM,IAAI;AACpE,YAAM,MAAM,SAAS,UAAU,aAAa,KAAK,UAAU,eAAe;AAC1E,UAAI,UAAU,WAAW,eAAe,KAAK;AAC3C,eAAO,EAAE,QAAQ,SAAS,UAAU,SAAS,IAAI,WAAW,KAAK,SAAS,CAAC,EAAE,IAAI,CAAC,EAAE;AAAA,MACtF;AACA,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,OAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,UAAU,QAAgB,aAAyC;AAC/E,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,OAAO,YAAY,MAAM;AAChD,YAAM,QAAQ,kBAAkB,IAAI,YAAY;AAChD,UAAI,CAAC,MAAM,OAAQ,QAAO,EAAE,QAAQ,UAAU,OAAO,qCAAqC;AAC1F,UAAI,CAAC,YAAa,QAAO,EAAE,QAAQ,UAAU,eAAe,MAAM,IAAI,CAAC,SAAS,KAAK,GAAG,EAAE;AAC1F,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,WAAW,MAAM,CAAC,GAAG,OAAO;AAAA,QAC5B,SAAS,MAAM,IAAI,CAAC,UAAU;AAAA,UAC5B,KAAK,KAAK;AAAA,UACV,MAAM,QAAQ,OAAO,KAAK,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,QACnD,EAAE;AAAA,QACF,UAAU;AAAA,UACR,UAAU,IAAI;AAAA,UACd,GAAI,IAAI,aAAa,EAAE,WAAW,IAAI,WAAW,IAAI,CAAC;AAAA,QACxD;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,eAAe,iBAAiB,IAAI,WAAW,IAAK,QAAO,EAAE,QAAQ,aAAa;AACtF,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,OACA,OACA,WACA,WACyD;AAIzD,QAAI,cAAc,SAAS;AACzB,YAAM,MAAM,MAAM,KAAK,OAAO,YAAY,KAAK;AAC/C,YAAM,MAAM,kBAAkB,IAAI,YAAY,EAAE,KAAK,GAAG;AACxD,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,aAAa,KAAK,8BAA8B,KAAK,EAAE;AACjF,aAAO,EAAE,UAAU,GAAG,KAAK,IAAI,KAAK,IAAI,WAAW,IAAI;AAAA,IACzD;AACA,UAAM,WAAW,MAAM,KAAK,OAAO,aAAa,OAAO,CAAC,KAAK,GAAG,SAAS;AACzE,UAAM,WAAW,SAAS,qBAAqB,CAAC;AAChD,QAAI,CAAC,UAAU;AAGb,YAAM,IAAI,MAAM,wDAAwD,KAAK,EAAE;AAAA,IACjF;AACA,UAAM,MAAM,MAAM,KAAK,OAAO,UAAU,QAAQ,EAAE,MAAM,MAAM,IAAI;AAClE,WAAO,EAAE,UAAU,WAAW,SAAS,KAAK,aAAa,KAAK,KAAK,eAAe,KAAK;AAAA,EACzF;AAAA,EAEA,MAAM,SAAS,KAA8B;AAC3C,QAAI,IAAI,WAAW,SAAS,EAAG,QAAOC,cAAa,IAAI,MAAM,UAAU,MAAM,CAAC;AAC9E,WAAO,KAAK,OAAO,SAAS,GAAG;AAAA,EACjC;AAAA,EAEA,MAAM,UAAgC;AACpC,UAAM,IAAI,MAAM,KAAK,OAAO,QAAQ;AACpC,WAAO,EAAE,MAAM,eAAe,WAAW,EAAE,aAAa,OAAO,EAAE,OAAO,MAAM,EAAE,KAAK;AAAA,EACvF;AAAA,EAEA,MAAM,QAAQ,UAAkB,MAA+B;AAC7D,UAAM,KAAK,OAAO,QAAQ,UAAU,KAAK,MAAM,GAAG,EAAE,CAAC;AAAA,EACvD;AAAA,EAEA,OAAO,OAAoC;AACzC,qBAAiB,OAAO,KAAK,OAAO,eAAe,GAAG,GAAG;AACvD,YAAM;AAAA,QACJ,IAAI,IAAI;AAAA,QACR,QAAQ,IAAI,UAAU;AAAA,QACtB,OAAO,IAAI,KAAK;AAAA,QAChB,QAAQ,IAAI,KAAK;AAAA,QACjB,WAAW,IAAI;AAAA,QACf,YAAY,IAAI,eAAe;AAAA,QAC/B,MAAM,IAAI,QAAQ,CAAC;AAAA,QACnB,QAAQ,IAAI,UAAU;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,SAAgC;AAC3C,UAAM,KAAK,OAAO,aAAa,OAAO;AAAA,EACxC;AACF;AAEA,SAAS,sBACP,MACA,OACA,SACM;AACN,MAAI,SAAS,QAAQ,CAAC,QAAQ,SAAS,KAAK,GAAG;AAC7C,UAAM,IAAI,MAAM,gBAAgB,IAAI,oBAAoB,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,EAC9E;AACF;AAOA,SAAS,kBAAkB,MAAqE;AAC9F,SAAO,OAAO,QAAQ,IAAI,EACvB,IAAI,CAAC,CAAC,KAAK,GAAG,OAAO,EAAE,OAAO,OAAO,IAAI,QAAQ,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,EACvE,OAAO,CAAC,SAAS,OAAO,SAAS,KAAK,KAAK,CAAC,EAC5C,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AACrC;AAEA,SAAS,SAAS,MAAuE;AACvF,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,OAAO,OAAO,IAAI,EAAE,KAAK,CAAC,MAAmB,OAAO,MAAM,QAAQ,KAAK;AAChF;;;AGjWA,IAAMC,oBAAmB;AACzB,IAAM,kBAAkB;AAiCxB,IAAM,uBAAN,MAA2B;AAAA,EACzB,YACmB,OACA,UAAUA,mBACV,UAAwB,OACzC;AAHiB;AACA;AACA;AAAA,EAChB;AAAA,EAHgB;AAAA,EACA;AAAA,EACA;AAAA,EAGnB,MAAM,OAAO,MAAgD;AAC3D,UAAM,WAAW,MAAM,KAAK,KAAK,eAAe,EAAE,QAAQ,QAAQ,MAAM,KAAK,UAAU,IAAI,EAAE,CAAC;AAC9F,UAAM,SAAU,SAAmC;AACnD,QAAI,OAAO,WAAW,YAAY,CAAC,QAAQ;AACzC,YAAM,IAAI,MAAM,iDAAiD;AAAA,IACnE;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,MAAM,MAAgD;AAC1D,UAAM,WAAW,MAAM,KAAK,KAAK,eAAe;AAAA,MAC9C,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,GAAG,MAAM,YAAY,KAAK,CAAC;AAAA,IACpD,CAAC;AACD,UAAM,SAAU,SAAwC;AACxD,QAAI,OAAO,WAAW,YAAY,CAAC,OAAO,SAAS,MAAM,KAAK,SAAS,GAAG;AACxE,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,IAAmC;AAC5C,WAAQ,MAAM,KAAK,KAAK,qBAAqB,mBAAmB,EAAE,CAAC,EAAE;AAAA,EACvE;AAAA,EAEA,MAAM,UAA2B;AAC/B,UAAM,WAAW,MAAM,KAAK,KAAK,qBAAqB;AACtD,UAAM,UAAW,SAAmC;AACpD,QAAI,OAAO,YAAY,YAAY,CAAC,OAAO,SAAS,OAAO,GAAG;AAC5D,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,KAAKC,QAAc,OAAoB,CAAC,GAAqB;AACzE,QAAI,CAAC,KAAK,MAAO,OAAM,IAAI,MAAM,uBAAuB;AACxD,UAAM,WAAW,MAAM,KAAK,QAAQ,GAAG,KAAK,OAAO,GAAGA,MAAI,IAAI;AAAA,MAC5D,GAAG;AAAA,MACH,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,cAAc,KAAK;AAAA,QACnB,GAAG,KAAK;AAAA,MACV;AAAA,IACF,CAAC;AACD,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI,QAAiB;AACrB,QAAI;AACF,cAAQ,OAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IACpC,QAAQ;AACN,cAAQ;AAAA,IACV;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,SAAS,QAAQ,IAAI,aAAa;AAChD,YAAM,SAAS,WAAW,KAAK;AAC/B,YAAM,IAAI;AAAA,QACR,mCAAmC,SAAS,MAAM,MAAM,MAAM,MAC3D,QAAQ,iBAAiB,KAAK,MAAM;AAAA,MACzC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAGO,IAAM,yBAAN,MAAM,wBAA2C;AAAA,EAGtD,YAA6B,QAA8B;AAA9B;AAAA,EAA+B;AAAA,EAA/B;AAAA,EAFpB,KAAK;AAAA,EAId,OAAO,UAAkC;AACvC,WAAO,IAAI,wBAAuB,IAAI,qBAAqB,QAAQ,IAAI,UAAU,CAAC;AAAA,EACpF;AAAA,EAEA,OAAO,aAAqC;AAC1C,WAAO,IAAI,wBAAuB,IAAI,qBAAqB,MAAS,CAAC;AAAA,EACvE;AAAA,EAEA,OAAO,eAAuC;AAI5C,WAAO,IAAI,wBAAuB,IAAI,qBAAqB,QAAQ,IAAI,UAAU,CAAC;AAAA,EACpF;AAAA,EAEA,SAAS,WAA+B;AACtC,WAAO,cAAc,SAAS,cAAc,aAC1C,cAAc,WAAW,cAAc;AAAA,EAC3C;AAAA,EAEA,SAAS,MAAkC;AACzC,UAAM,UAAU,aAAa,IAAI;AACjC,UAAM,QAAQ,oBAAoB,MAAM,OAAO;AAC/C,UAAM,QAAQ,QAAQ,aAAa;AACnC,UAAM,SAAS,KAAK,QAAQ,KAAK;AACjC,QAAI;AACJ,QAAI,MAAM,WAAW,yBAAyB,GAAG;AAC/C,aAAO,qCAAqC,KAAK,KAAK,IAAI,OAAO;AAAA,IACnE,WAAW,MAAM,WAAW,gBAAgB,GAAG;AAC7C,aAAO,sCAAsC,KAAK,KAAK,IAAI,OAAO;AAAA,IACpE,WAAW,mCAAmC,KAAK,KAAK,GAAG;AACzD,aAAO;AAAA,IACT,WAAW,MAAM,WAAW,UAAU,GAAG;AACvC,aAAO;AAAA,IACT,WAAW,MAAM,WAAW,WAAW,GAAG;AACxC,aAAO,KAAK,IAAI,QAAQ,SAAS,OAAW,GAAS;AAAA,IACvD,WAAW,qBAAqB,KAAK,GAAG;AACtC,aAAO,KAAK,IAAI,OAAO,SAAS,SAAU,GAAO;AAAA,IACnD,OAAO;AACL,aAAO,KAAK,IAAI,QAAQ,SAAS,OAAU,GAAS;AAAA,IACtD;AACA,WAAO,EAAE,MAAM,OAAO,QAAQ,iBAAiB,OAAO,KAAK,GAAG,YAAY,MAAM;AAAA,EAClF;AAAA,EAEA,SAAS,MAAoB,aAAyC;AACpE,UAAM,UAAU,aAAa,IAAI;AACjC,UAAM,cAAc,oBAAoB,MAAM,OAAO;AACrD,UAAM,QAAQ,QAAQ,aAAa;AACnC,UAAM,cAAc,8CAA8C,KAAK,WAAW;AAClF,UAAM,SAAS,YAAY,WAAW,WAAW;AACjD,QACE,CAAC,eACA,KAAK,cAAc,eAAe,CAAC,eACnC,KAAK,cAAc,WAAW,CAAC,UAC/B,KAAK,cAAc,eAAe,KAAK,cAAc,YAAY,eAAe,SACjF;AACA,YAAM,IAAI;AAAA,QACR,0BAA0B,WAAW,+BAA+B,KAAK,SAAS;AAAA,MACpF;AAAA,IACF;AACA,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,IAAI;AACvD,YAAM,IAAI,MAAM,+DAA+D;AAAA,IACjF;AACA,QAAI,KAAK,QAAQ,MAAM,KAAK,SAAS,MAAM,KAAK,QAAQ,OAAO,KAAK,SAAS,KAAK;AAChF,YAAM,IAAI,MAAM,qEAAqE;AAAA,IACvF;AACA,QAAI,YAAY,SAAS,GAAG;AAC1B,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AACA,QAAI,KAAK,cAAc,aAAa;AAClC,UAAI,UAAU,EAAG,OAAM,IAAI,MAAM,2DAA2D;AAC5F,wBAAkB,aAAa,MAAM,aAAa,OAAO;AAAA,IAC3D,WAAW,KAAK,cAAc,SAAS;AACrC,mBAAa,aAAa,MAAM,aAAa,OAAO,OAAO;AAAA,IAC7D,WAAW,YAAY,UAAU,CAAC,uBAAuB,KAAK,WAAW,GAAG;AAC1E,YAAM,IAAI;AAAA,QACR,0BAA0B,WAAW;AAAA,MAEvC;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,MAAoB,aAA+D;AAC9F,SAAK,SAAS,MAAM,WAAW;AAC/B,UAAM,UAAU,aAAa,IAAI;AACjC,UAAM,cAAc,oBAAoB,MAAM,OAAO;AACrD,UAAM,YAAY,KAAK,cAAc;AACrC,UAAM,QAAQ,KAAK,cAAc;AACjC,UAAM,OAAgC;AAAA,MACpC,QAAQ,KAAK;AAAA,MACb,cAAc;AAAA,MACd,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,YAAY,QAAQ,aAAa;AAAA,MACjC,GAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,WAAW,QAAQ,YAAY,KAAK,aAAa,IAAI,CAAC;AAAA,MACnF,GAAI,KAAK,QAAQ,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,MAC/C,GAAI,aAAa,QACb,YAAY,CAAC,IACX,EAAE,aAAa,YAAY,CAAC,EAAE,OAAO,IACrC,CAAC,IACH,YAAY,SACV,EAAE,kBAAkB,YAAY,IAAI,CAAC,UAAU,MAAM,MAAM,EAAE,IAC7D,CAAC;AAAA,MACP,GAAI,SAAS,YAAY,CAAC,IAAI,EAAE,mBAAmB,YAAY,CAAC,EAAE,OAAO,IAAI,CAAC;AAAA,MAC9E,GAAI,SAAS,QAAQ,cAAc,EAAE,cAAc,QAAQ,YAAY,IAAI,CAAC;AAAA,MAC5E,GAAI,aAAa,QAAQ,iBAAiB,EAAE,iBAAiB,QAAQ,eAAe,IAAI,CAAC;AAAA,MACzF,GAAI,aAAa,QAAQ,oBAAoB,EAAE,oBAAoB,KAAK,IAAI,CAAC;AAAA,MAC7E,GAAI,CAAC,aAAa,QAAQ,SAAS,OAAO,EAAE,QAAQ,QAAQ,MAAM,IAAI,CAAC;AAAA,MACvE,GAAI,CAAC,aAAa,QAAQ,SAAS,OAAO,EAAE,QAAQ,QAAQ,MAAM,IAAI,CAAC;AAAA,MACvE,GAAI,KAAK,QAAQ,SACb,EAAE,eAAe,cAAc,KAAK,OAAO,EAAE,SAAS,QAAQ,EAAE,IAChE,CAAC;AAAA,IACP;AACA,UAAM,SAAS,MAAM,KAAK,OAAO,MAAM,IAAI;AAC3C,UAAM,YAAY,KAAK,SAAS,IAAI,EAAE;AACtC,QAAI,SAAS,YAAY,MAAU;AACjC,YAAM,IAAI;AAAA,QACR,2BAA2B,OAAO,QAAQ,CAAC,CAAC,iCACtC,UAAU,QAAQ,CAAC,CAAC;AAAA,MAC5B;AAAA,IACF;AACA,WAAO;AAAA,MACL,OAAO,MAAM,KAAK,OAAO,OAAO,EAAE,GAAG,MAAM,OAAO,MAAM,gBAAgB,KAAK,CAAC;AAAA,IAChF;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,OAAe,WAAsB,SAA0C;AACxF,UAAM,OAAO,MAAM,KAAK,OAAO,KAAK,KAAK;AACzC,QAAI,KAAK,WAAW,aAAa,KAAK,WAAW,UAAW,QAAO,EAAE,QAAQ,aAAa;AAC1F,QAAI,KAAK,WAAW,SAAU,QAAO,EAAE,QAAQ,UAAU,OAAO,WAAW,KAAK,KAAK,EAAE;AACvF,QAAI,KAAK,WAAW,aAAa;AAC/B,aAAO,EAAE,QAAQ,UAAU,OAAO,iDAAiD,OAAO,KAAK,MAAM,CAAC,IAAI;AAAA,IAC5G;AAEA,UAAM,UAAU,SAAS,OAAO,aAAa,QAAQ,IAAI,IAAI,CAAC;AAC9D,UAAM,YAAY,cAAc,eAAe,CAAC,QAAQ,oBACpD,UAAU,MACV,UAAU;AACd,UAAM,UAAU,cAAc,KAAK,QAAQ,SAAS;AACpD,UAAM,OAAO,QAAQ,IAAI,CAAC,WAAW,OAAO,GAAG;AAC/C,QAAI,CAAC,KAAK,OAAQ,QAAO,EAAE,QAAQ,UAAU,OAAO,0CAA0C;AAC9F,QAAI,KAAK,SAAS,EAAG,QAAO,EAAE,QAAQ,UAAU,eAAe,KAAK;AACpE,UAAM,iBAAiB,QAAQ,IAAI,CAAC,QAAQ,WAAW;AAAA,MACrD,GAAG;AAAA,MACH,KAAKC,WAAU,OAAO,OAAO,SAAS;AAAA,IACxC,EAAE;AACF,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,UAAU,GAAG,KAAK;AAAA,MAClB,WAAW,eAAe,CAAC,EAAG;AAAA,MAC9B,SAAS;AAAA,MACT,UAAU;AAAA,QACR,aAAa,KAAK,QAAQ,gBAAgB;AAAA,QAC1C,kBAAkB,KAAK,QAAQ,qBAAqB;AAAA,QACpD;AAAA,QACA,MAAM,cAAc,cAAc,cAAc,cAAc,UAAU,YAAY;AAAA,QACpF,GAAI,SAAS,OACT;AAAA,UACE,aAAa,oBAAoB,QAAQ,MAAM,OAAO;AAAA,UACtD,OAAO,QAAQ,KAAK;AAAA,UACpB,QAAQ,QAAQ,KAAK;AAAA,QACvB,IACA,CAAC;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,OACA,OACyD;AACzD,UAAM,OAAO,MAAM,KAAK,OAAO,KAAK,KAAK;AACzC,QAAI,KAAK,WAAW,YAAa,OAAM,IAAI,MAAM,wBAAwB,KAAK,eAAe;AAC7F,UAAM,MAAM,cAAc,KAAK,QAAQ,UAAU,GAAG,EAAE,KAAK,GAAG;AAC9D,QAAI,CAAC,IAAK,OAAM,IAAI,MAAM,wBAAwB,KAAK,8BAA8B,KAAK,EAAE;AAC5F,WAAO,EAAE,UAAU,GAAG,KAAK,IAAI,KAAK,IAAI,WAAWA,WAAU,OAAO,OAAO,UAAU,GAAG,EAAE;AAAA,EAC5F;AAAA,EAEA,MAAM,SAAS,KAA8B;AAC3C,QAAI,IAAI,WAAW,GAAG,eAAe,IAAI,GAAG;AAC1C,YAAM,YAAY,eAAe,GAAG;AACpC,YAAM,OAAO,MAAM,KAAK,OAAO,KAAK,UAAU,KAAK;AACnD,UAAI,KAAK,WAAW,aAAa;AAC/B,cAAM,IAAI,MAAM,wBAAwB,UAAU,KAAK,eAAe;AAAA,MACxE;AACA,YAAM,SAAS,cAAc,KAAK,QAAQ,UAAU,SAAS,EAAE,UAAU,KAAK,GAAG;AACjF,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI;AAAA,UACR,wBAAwB,UAAU,KAAK,2BAA2B,UAAU,KAAK;AAAA,QACnF;AAAA,MACF;AACA,aAAO,KAAK,iBAAiB,MAAM;AAAA,IACrC;AACA,WAAO,KAAK,iBAAiB,GAAG;AAAA,EAClC;AAAA,EAEA,MAAc,iBAAiB,KAA8B;AAC3D,UAAM,OAAO,2BAA2B,KAAK,GAAG,IAAI,CAAC;AACrD,QAAI,KAAM,QAAO,OAAO,KAAK,MAAM,QAAQ;AAC3C,UAAM,WAAW,MAAM,MAAM,GAAG;AAChC,QAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,oCAAoC,SAAS,MAAM,GAAG;AACxF,WAAO,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC;AAAA,EACjD;AAAA,EAEA,MAAM,UAAgC;AACpC,WAAO,EAAE,MAAM,OAAO,WAAW,MAAM,KAAK,OAAO,QAAQ,EAAE;AAAA,EAC/D;AACF;AAEA,SAASA,WAAU,OAAe,OAAe,WAA8B;AAC7E,QAAM,MAAM,IAAI,IAAI,yBAAyB;AAC7C,MAAI,aAAa,IAAI,OAAO,KAAK;AACjC,MAAI,aAAa,IAAI,SAAS,OAAO,KAAK,CAAC;AAC3C,MAAI,aAAa,IAAI,aAAa,SAAS;AAC3C,SAAO,IAAI;AACb;AAEA,SAAS,eAAe,OAAuE;AAC7F,QAAM,MAAM,IAAI,IAAI,KAAK;AACzB,QAAM,QAAQ,IAAI,aAAa,IAAI,KAAK;AACxC,QAAM,QAAQ,OAAO,IAAI,aAAa,IAAI,OAAO,CAAC;AAClD,QAAM,eAAe,IAAI,aAAa,IAAI,WAAW;AACrD,MACE,IAAI,aAAa,mBACjB,IAAI,aAAa,YACjB,CAAC,SACD,CAAC,OAAO,UAAU,KAAK,KACvB,QAAQ,KACP,iBAAiB,UAAU,OAAO,iBAAiB,UAAU,KAC9D;AACA,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,SAAO,EAAE,OAAO,OAAO,WAAW,aAAa;AACjD;AAEA,SAAS,aAAa,MAA2C;AAC/D,SAAO,KAAK;AACd;AAEA,SAAS,cACP,QACA,WAC8C;AAC9C,QAAM,UAAU,QAAQ,eAAe,CAAC,GACrC,OAAO,CAAC,QAAuB,OAAO,QAAQ,YAAY,IAAI,SAAS,CAAC,EACxE,IAAI,CAAC,SAAS,EAAE,KAAK,UAAU,EAAE;AACpC,MAAI,OAAO,OAAQ,QAAO;AAC1B,UAAQ,QAAQ,iBAAiB,CAAC,GAC/B,OAAO,CAAC,SAAyB,OAAO,SAAS,YAAY,KAAK,SAAS,CAAC,EAC5E,IAAI,CAAC,UAAU;AAAA,IACd,KAAK,QAAQ,SAAS,WAAW,IAAI;AAAA,IACrC;AAAA,EACF,EAAE;AACN;AAEA,SAAS,oBAAoB,MAAoB,SAAwC;AACvF,SAAO,QAAQ,gBACZ,KAAK,cAAc,cAChB,gCACA,KAAK,cAAc,UACjB,qBACA;AACV;AAEA,SAAS,kBACP,OACA,MACA,aACA,SACM;AACN,MAAI,KAAK,UAAU,KAAK,OAAQ,OAAM,IAAI,MAAM,2CAA2C;AAC3F,MAAI,MAAM,WAAW,yBAAyB,GAAG;AAC/C,QAAI,YAAY,WAAW,GAAG;AAC5B,YAAM,IAAI,MAAM,6CAA6C,KAAK,4BAA4B;AAAA,IAChG;AACA,QAAI,KAAK,QAAQ,MAAM,KAAK,QAAQ,KAAK;AACvC,YAAM,IAAI,MAAM,8EAA8E;AAAA,IAChG;AAAA,EACF,WAAW,YAAY,SAAS,GAAG;AACjC,UAAM,IAAI,MAAM,kEAAkE;AAAA,EACpF;AACA,QAAM,QAAQ,MAAM,SAAS,oBAAoB,IAAI,KACjD,MAAM,SAAS,iBAAiB,IAAI,KAClC,MAAM,SAAS,iBAAiB,IAAI,KAClC,MAAM,SAAS,iBAAiB,IAAI,MAClC,MAAM,SAAS,kBAAkB,IAAI,KACnC;AACZ,MAAI,SAAS,KAAK,UAAU,OAAO;AACjC,UAAM,IAAI,MAAM,0BAA0B,KAAK,cAAc,KAAK,IAAI,KAAK,aAAa;AAAA,EAC1F;AACA,MAAI,MAAM,SAAS,OAAO,MAAM,KAAK,QAAQ,MAAM,KAAK,QAAQ,KAAK;AACnE,UAAM,IAAI,MAAM,wEAAwE;AAAA,EAC1F;AACA,MAAI,QAAQ,kBAAkB,QAAQ,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,SAAS,QAAQ,cAAc,GAAG;AAC7F,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AACF;AAEA,SAAS,aACP,OACA,MACA,aACA,OACA,SACM;AACN,MAAI,KAAK,UAAU,KAAK,OAAQ,OAAM,IAAI,MAAM,sCAAsC;AACtF,QAAM,OAAO,KAAK;AAClB,MAAI,mCAAmC,KAAK,KAAK,GAAG;AAClD,QAAI,OAAO,MAAM,OAAO,GAAI,OAAM,IAAI,MAAM,qDAAgD;AAC5F,QAAI,UAAU,EAAG,OAAM,IAAI,MAAM,+CAA+C;AAAA,EAClF,WAAW,UAAU,2BAA2B,OAAO,MAAM,OAAO,KAAK;AACvE,UAAM,IAAI,MAAM,sEAAsE;AAAA,EACxF,WAAW,UAAU,2BAA2B;AAC9C,QAAI,OAAO,MAAM,OAAO,IAAK,OAAM,IAAI,MAAM,6DAAwD;AACrG,QAAI,YAAY,WAAW,EAAG,OAAM,IAAI,MAAM,yDAAyD;AAAA,EACzG,WAAW,UAAU,2BAA2B,OAAO,MAAM,OAAO,KAAK;AACvE,UAAM,IAAI,MAAM,sEAAsE;AAAA,EACxF,WAAW,UAAU,4BAA4B,OAAO,MAAM,OAAO,MAAM;AACzE,UAAM,IAAI,MAAM,6EAA6E;AAAA,EAC/F;AACA,MAAI,UAAU,sBAAsB,YAAY,SAAS,GAAG;AAC1D,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AACA,MAAI,UAAU,6BAA6B;AACzC,QAAI,YAAY,SAAS,EAAG,OAAM,IAAI,MAAM,mEAAmE;AAC/G,QAAI,CAAC,QAAQ,eAAe,YAAY,SAAS,GAAG;AAClD,YAAM,IAAI,MAAM,+EAA+E;AAAA,IACjG;AAAA,EACF;AACF;AAEA,SAAS,qBAAqB,OAAwB;AACpD,SAAO,0DAA0D,KAAK,KAAK;AAC7E;AAEA,SAAS,iBAAiB,OAAuB;AAI/C,SAAO,KAAK,MAAM,QAAQ,QAAQ,GAAK,IAAI;AAC7C;AAEA,SAAS,WAAW,OAAwB;AAC1C,MAAI,OAAO,UAAU,SAAU,QAAO,SAAS;AAC/C,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,SAAS;AACf,MAAI,OAAO,OAAO,YAAY,SAAU,QAAO,OAAO;AACtD,MAAI,OAAO,OAAO,WAAW,SAAU,QAAO,OAAO;AACrD,MAAI,MAAM,QAAQ,OAAO,MAAM,GAAG;AAChC,UAAM,UAAU,OAAO,OACpB,IAAI,CAAC,SAAS;AACb,UAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO,OAAO,IAAI;AACzD,YAAM,SAAS;AACf,aAAO,OAAO,OAAO,QAAQ,WAAW,OAAO,MAAM,KAAK,UAAU,IAAI;AAAA,IAC1E,CAAC,EACA,OAAO,OAAO;AACjB,QAAI,QAAQ,OAAQ,QAAO,QAAQ,KAAK,IAAI;AAAA,EAC9C;AACA,MAAI,OAAO,UAAU,OAAO,OAAO,WAAW,UAAU;AACtD,UAAMC,WAAW,OAAO,OAAmC;AAC3D,QAAI,OAAOA,aAAY,SAAU,QAAOA;AAAA,EAC1C;AACA,SAAO,KAAK,UAAU,KAAK;AAC7B;;;ACtdA,IAAMC,oBAAmB;AACzB,IAAMC,mBAAkB;AACxB,IAAM,uBAAuB,oBAAI,IAAI;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AA6CD,IAAM,iBAAN,MAAqB;AAAA,EACnB,YACmB,QACA,WACA,UAAUD,mBACV,UAAwB,OACzC;AAJiB;AACA;AACA;AACA;AAAA,EAChB;AAAA,EAJgB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAGnB,MAAM,MAAM,SAAiB,MAA+B,WAA4C;AACtG,UAAM,WAAW,MAAM,KAAK;AAAA,MAC1B,oBAAoB,mBAAmB,OAAO,CAAC;AAAA,MAC/C,EAAE,QAAQ,QAAQ,MAAM,KAAK,UAAU,IAAI,EAAE;AAAA,MAC7C,EAAE,QAAQ,QAAQ,UAAU;AAAA,IAC9B;AACA,UAAM,oBAAoB;AAAA,MACvB,UAA8C;AAAA,MAC/C;AAAA,IACF;AACA,UAAM,cAAc,cAAe,UAAwC,WAAW;AACtF,UAAM,kBAAkB;AAAA,MACrB,UAAmE,aAChE;AAAA,MACJ;AAAA,IACF;AACA,WAAO;AAAA,MACL,OAAO,oBAAoB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,OACJ,SACA,MACA,WACiB;AACjB,UAAM,WAAW,MAAM,KAAK;AAAA,MAC1B,oBAAoB,mBAAmB,OAAO,CAAC;AAAA,MAC/C,EAAE,QAAQ,QAAQ,MAAM,KAAK,UAAU,IAAI,EAAE;AAAA,MAC7C,EAAE,UAAU;AAAA,IACd;AACA,UAAM,MAAO,UAAgC;AAC7C,UAAM,QAAQ,UAAU,GAAG;AAC3B,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,yCAAyC;AACrE,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,IAAI,IAAY,WAA0C;AAC9D,UAAM,WAAW,MAAM,KAAK,KAAK,SAAS,mBAAmB,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC;AACrF,UAAM,MAAO,UAAgC;AAC7C,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,OAAM,IAAI,MAAM,kCAAkC;AACvF,UAAM,SAAS;AACf,UAAM,QAAQ,UAAU,GAAG;AAC3B,QAAI,CAAC,SAAS,OAAO,OAAO,WAAW,UAAU;AAC/C,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AACA,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,OAAO;AAAA,MACf,GAAI,OAAO,OAAO,aAAa,WAAW,EAAE,UAAU,OAAO,SAAS,IAAI,CAAC;AAAA,MAC3E,GAAI,OAAO,YAAY,OAAO,OAAO,aAAa,WAC9C,EAAE,UAAU,OAAO,SAAoC,IACvD,CAAC;AAAA,MACL,GAAI,OAAO,WAAW,OAAO,OAAO,YAAY,WAC5C,EAAE,SAAS,OAAO,QAAkC,IACpD,CAAC;AAAA,IACP;AAAA,EACF;AAAA,EAEA,MAAM,MAAM,IAAY,WAA4C;AAClE,UAAM,WAAW,MAAM,KAAK;AAAA,MAC1B,WAAW,mBAAmB,EAAE,CAAC;AAAA,MACjC,CAAC;AAAA,MACD,EAAE,gBAAgB,QAAQ,UAAU;AAAA,IACtC;AACA,UAAM,MAAO,UAAkC;AAC/C,QAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,OAAM,IAAI,MAAM,sCAAsC,EAAE,EAAE;AAC/F,UAAM,QAAQ;AACd,UAAM,UAAU,OAAO,MAAM,OAAO,YAAY,MAAM,KAAK,MAAM,KAAK;AACtE,UAAM,MAAM,OAAO,MAAM,QAAQ,WAAW,MAAM,MAAM;AACxD,UAAM,kBAAkB,OAAO,MAAM,oBAAoB,WACrD,MAAM,kBACN;AACJ,QAAI,CAAC,mBAAmB,CAAC,IAAK,OAAM,IAAI,MAAM,kBAAkB,OAAO,sBAAsB;AAC7F,UAAM,WAAW,SAAS,MAAM,QAAQ,IAAI,MAAM,WAAW,CAAC;AAC9D,UAAM,iBAAiB,MAAM,eAAe,SAAS;AACrD,UAAM,cAAc,OAAO,UAAU,cAAc,KAAK,OAAO,cAAc,KAAK,IAC9E,OAAO,cAAc,IACrB,OAAO;AACX,UAAM,mBAAmB,OAAO,MAAM,qBAAqB,WACvD,MAAM,mBACN,OAAO,MAAM,aAAa,WACxB,MAAM,WACN;AACN,WAAO;AAAA,MACL,IAAI;AAAA,MACJ;AAAA,MACA,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,MAC7C,GAAI,mBAAmB,EAAE,iBAAiB,IAAI,CAAC;AAAA,MAC/C;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,KAA8B;AAC3C,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAI,OAAO,aAAa,WAAW,OAAO,aAAa,UAAU;AAC/D,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AACA,UAAM,WAAW,MAAM,KAAK,QAAQ,MAAM;AAC1C,QAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,6BAA6B,SAAS,MAAM,GAAG;AACjF,UAAM,WAAW,OAAO,SAAS,QAAQ,IAAI,gBAAgB,CAAC;AAC9D,QAAI,OAAO,SAAS,QAAQ,KAAK,WAAW,oBAAoB;AAC9D,YAAM,IAAI,MAAM,iCAAiC,kBAAkB,oBAAoB;AAAA,IACzF;AACA,UAAM,QAAQ,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC;AACtD,QAAI,MAAM,SAAS,oBAAoB;AACrC,YAAM,IAAI,MAAM,iCAAiC,kBAAkB,oBAAoB;AAAA,IACzF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,kBAAiC;AACrC,UAAM,KAAK,KAAK,WAAW,CAAC,GAAG,EAAE,UAAU,IAAI,CAAC;AAAA,EAClD;AAAA,EAEA,MAAc,KACZ,UACA,OAAoB,CAAC,GACrB,QAA4C,CAAC,GAC3B;AAClB,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,WAAW;AACnC,YAAM,UAAU;AAAA,QACd,CAAC,KAAK,SAAS,yBAAyB;AAAA,QACxC,CAAC,KAAK,YAAY,4BAA4B;AAAA,MAChD,EAAE,OAAO,OAAO;AAChB,YAAM,IAAI,MAAM,GAAG,QAAQ,KAAK,OAAO,CAAC,IAAI,QAAQ,SAAS,IAAI,QAAQ,IAAI,UAAU;AAAA,IACzF;AACA,UAAM,MAAM,IAAI,IAAI,GAAG,KAAK,QAAQ,QAAQ,OAAO,EAAE,CAAC,GAAG,QAAQ,EAAE;AACnE,eAAW,CAAC,KAAKE,MAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAChD,UAAIA,UAAS,KAAM,KAAI,aAAa,IAAI,KAAKA,MAAK;AAAA,IACpD;AACA,UAAM,OAAO,OAAO,KAAK,GAAG,KAAK,MAAM,IAAI,KAAK,SAAS,EAAE,EAAE,SAAS,QAAQ;AAC9E,UAAM,WAAW,MAAM,KAAK,QAAQ,KAAK;AAAA,MACvC,GAAG;AAAA,MACH,SAAS;AAAA,QACP,QAAQ;AAAA,QACR,eAAe,SAAS,IAAI;AAAA,QAC5B,GAAI,KAAK,OAAO,EAAE,gBAAgB,mBAAmB,IAAI,CAAC;AAAA,QAC1D,GAAG,KAAK;AAAA,MACV;AAAA,IACF,CAAC;AACD,UAAM,OAAO,MAAM,SAAS,KAAK;AACjC,QAAI,QAAiB;AACrB,QAAI;AACF,cAAQ,OAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IACpC,QAAQ;AACN,cAAQ;AAAA,IACV;AACA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,QAAQ,SAAS,QAAQ,IAAI,aAAa;AAChD,YAAM,SAAS,oBAAoB,OAAO,CAAC,KAAK,QAAQ,KAAK,WAAW,IAAI,CAAC;AAC7E,YAAM,IAAI;AAAA,QACR,4BAA4B,SAAS,MAAM,MAAM,MAAM,MACpD,QAAQ,iBAAiB,KAAK,MAAM;AAAA,MACzC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAGO,IAAM,mBAAN,MAAM,kBAAqC;AAAA,EAGhD,YAA6B,QAAwB;AAAxB;AAAA,EAAyB;AAAA,EAAzB;AAAA,EAFpB,KAAK;AAAA,EAId,OAAO,UAA4B;AACjC,WAAO,IAAI,kBAAiB,IAAI;AAAA,MAC9B,QAAQ,IAAI;AAAA,MACZ,QAAQ,IAAI;AAAA,MACZ,gBAAgB,QAAQ,IAAI,yBAAyBF,iBAAgB;AAAA,IACvE,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,aAA+B;AACpC,WAAO,IAAI,kBAAiB,IAAI,eAAe,QAAW,MAAS,CAAC;AAAA,EACtE;AAAA,EAEA,OAAO,eAAiC;AACtC,WAAO,kBAAiB,QAAQ;AAAA,EAClC;AAAA,EAEA,SAAS,WAA+B;AACtC,WAAO,cAAc;AAAA,EACvB;AAAA,EAEA,SAAS,MAAkC;AACzC,UAAM,UAAU,gBAAgB,IAAI;AACpC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,QAAQ,QAAQ;AAAA,MAChB,YAAY,QAAQ,cAAc;AAAA,IACpC;AAAA,EACF;AAAA,EAEA,SAAS,MAAoB,aAAyC;AACpE,UAAM,UAAU,gBAAgB,IAAI;AACpC,QAAI,OAAO,QAAQ,YAAY,YAAY,CAAC,QAAQ,QAAQ,KAAK,GAAG;AAClE,YAAM,IAAI,MAAM,8BAA8B;AAAA,IAChD;AACA,QAAI,CAAC,OAAO,SAAS,QAAQ,eAAe,KAAK,QAAQ,mBAAmB,GAAG;AAC7E,YAAM,IAAI,MAAM,oDAAoD;AAAA,IACtE;AACA,UAAM,QAAQ,QAAQ,cAAc;AACpC,QAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,QAAQ,GAAG;AACtD,YAAM,IAAI,MAAM,wDAAwD;AAAA,IAC1E;AACA,QACE,KAAK,QAAQ,OAAO,KAAK,QAAQ,QAAQ,KAAK,QAAQ,OAAO,KAC7D,KAAK,SAAS,OAAO,KAAK,SAAS,QAAQ,KAAK,SAAS,OAAO,GAChE;AACA,YAAM,IAAI,MAAM,oEAAoE;AAAA,IACtF;AACA,QAAI,YAAY,QAAQ;AACtB,YAAM,IAAI,MAAM,2EAA2E;AAAA,IAC7F;AACA,QAAI,QAAQ,aAAa,SAAS,OAAO,QAAQ,cAAc,YAAY,CAAC,QAAQ,UAAU,KAAK,IAAI;AACrG,YAAM,IAAI,MAAM,+CAA+C;AAAA,IACjE;AACA,uBAAmB,QAAQ,cAAc,CAAC,CAAC;AAAA,EAC7C;AAAA,EAEA,YAAuB;AACrB,WAAO,EAAE,WAAW,KAAM,aAAa,EAAE;AAAA,EAC3C;AAAA,EAEA,MAAM,OAAO,MAAoB,aAAgE;AAC/F,SAAK,SAAS,MAAM,WAAW;AAC/B,UAAM,UAAU,gBAAgB,IAAI;AACpC,UAAM,OAAO,YAAY,MAAM,OAAO;AACtC,UAAM,QAAQ,MAAM,KAAK,OAAO,MAAM,QAAQ,SAAS,MAAM,QAAQ,SAAS;AAC9E,QAAI,MAAM,QAAQ,QAAQ,kBAAkB,OAAO,SAAS;AAC1D,YAAM,IAAI;AAAA,QACR,mBAAmB,MAAM,KAAK,yCACzB,QAAQ,eAAe;AAAA,MAC9B;AAAA,IACF;AACA,UAAM,WAAW,MAAM,KAAK,OAAO,OAAO,QAAQ,SAAS,MAAM,QAAQ,SAAS;AAClF,WAAO;AAAA,MACL,OAAO,OAAO,UAAU,QAAQ,SAAS;AAAA,MACzC,UAAU;AAAA,QACR,SAAS,QAAQ;AAAA,QACjB,WAAW,QAAQ,aAAa;AAAA,QAChC,iBAAiB,QAAQ;AAAA,QACzB,oBAAoB,MAAM;AAAA,QAC1B,mBAAmB,MAAM;AAAA,QACzB,aAAa,MAAM;AAAA,QACnB,iBAAiB,MAAM;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,cAAsB,YAAuB,SAA0C;AAChG,UAAM,YAAY,YAAY,YAAY;AAC1C,UAAM,MAAM,MAAM,KAAK,OAAO,IAAI,UAAU,OAAO,UAAU,SAAS;AACtE,UAAM,WAAW,YAAY,KAAK,SAAS,OAAO,gBAAgB,QAAQ,IAAI,IAAI,MAAS;AAC3F,QAAI,CAAC,WAAW,UAAU,cAAc,eAAe,cAAc,YAAY,EAAE,SAAS,IAAI,MAAM,GAAG;AACvG,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,iBAAiB,cAAc,IAAI,QAAQ;AAAA,MAC7C;AAAA,IACF;AACA,QAAI,CAAC,WAAW,UAAU,UAAU,EAAE,SAAS,IAAI,MAAM,GAAG;AAC1D,aAAO,EAAE,QAAQ,UAAU,OAAO,iBAAiB,GAAG,EAAE;AAAA,IAC1D;AACA,QAAI,IAAI,WAAW,WAAW;AAC5B,aAAO,EAAE,QAAQ,UAAU,OAAO,yCAAyC,IAAI,MAAM,IAAI;AAAA,IAC3F;AACA,UAAM,WAAW,iBAAiB,GAAG;AACrC,QAAI,CAAC,SAAS,OAAQ,QAAO,EAAE,QAAQ,UAAU,OAAO,qCAAqC;AAC7F,UAAM,SAAS,MAAM,KAAK,OAAO,UAAU,UAAU,SAAS;AAC9D,QAAI,OAAO,SAAS,GAAG;AACrB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,eAAe,OAAO,IAAI,gBAAgB;AAAA,QAC1C,UAAU,EAAE,GAAG,UAAU,UAAU,OAAO,IAAI,CAACG,WAAUA,OAAM,EAAE,EAAE;AAAA,MACrE;AAAA,IACF;AACA,UAAM,QAAQ,OAAO,CAAC;AACtB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,UAAU,MAAM;AAAA,MAChB,WAAW,SAAS,MAAM,IAAI,UAAU,SAAS;AAAA,MACjD,SAAS,CAAC,EAAE,KAAK,SAAS,MAAM,IAAI,UAAU,SAAS,GAAG,WAAW,UAAU,IAAI,CAAC;AAAA,MACpF,UAAU;AAAA,QACR,GAAG;AAAA,QACH,SAAS,MAAM;AAAA,QACf,aAAa,MAAM,gBAAgB,OAAO,mBAAmB,OAAO,MAAM;AAAA,MAC5E;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBAAgB,cAAsB,OAA4C;AACtF,UAAM,YAAY,YAAY,YAAY;AAC1C,UAAM,MAAM,MAAM,KAAK,OAAO,IAAI,UAAU,OAAO,UAAU,SAAS;AACtE,QAAI,IAAI,WAAW,UAAW,OAAM,IAAI,MAAM,gBAAgB,UAAU,KAAK,eAAe;AAC5F,UAAM,SAAS,MAAM,KAAK,OAAO,iBAAiB,GAAG,GAAG,UAAU,SAAS;AAC3E,UAAM,QAAQ,OAAO,KAAK;AAC1B,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,gBAAgB,UAAU,KAAK,8BAA8B,KAAK,EAAE;AAChG,WAAO;AAAA,MACL,UAAU,MAAM;AAAA,MAChB,WAAW,SAAS,MAAM,IAAI,UAAU,SAAS;AAAA,MACjD,UAAU;AAAA,QACR,GAAG,YAAY,GAAG;AAAA,QAClB,SAAS,MAAM;AAAA,QACf,aAAa,MAAM,gBAAgB,OAAO,mBAAmB,OAAO,MAAM;AAAA,MAC5E;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,SAAS,QAAiC;AAC9C,QAAI,CAAC,OAAO,WAAW,GAAGF,gBAAe,IAAI,EAAG,QAAO,KAAK,OAAO,SAAS,MAAM;AAClF,UAAM,YAAY,cAAc,MAAM;AACtC,UAAM,QAAQ,MAAM,KAAK,OAAO,MAAM,UAAU,SAAS,UAAU,SAAS;AAC5E,mBAAe,KAAK;AACpB,WAAO,KAAK,OAAO,SAAS,iBAAiB,KAAK,CAAC;AAAA,EACrD;AAAA,EAEA,MAAM,kBAAiC;AACrC,UAAM,KAAK,OAAO,gBAAgB;AAAA,EACpC;AAAA,EAEA,MAAc,OAAO,KAAe,WAA8C;AAChF,UAAM,SAAS,MAAM,QAAQ,IAAI,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO,MAAM,IAAI,SAAS,CAAC,CAAC;AAClF,UAAM,WAAW,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,CAAC;AAC5D,eAAW,SAAS,OAAQ,gBAAe,KAAK;AAChD,WAAO,OAAO,KAAK,CAAC,MAAM,UACxB,KAAK,cAAc,MAAM,gBACxB,SAAS,IAAI,KAAK,EAAE,KAAK,OAAO,qBAC9B,SAAS,IAAI,MAAM,EAAE,KAAK,OAAO,qBACpC,KAAK,GAAG,cAAc,MAAM,EAAE,CAAC;AAAA,EACnC;AACF;AAEA,SAAS,gBAAgB,MAAqC;AAC5D,SAAO,KAAK;AACd;AAEA,SAAS,gBAAgB,OAAuB;AAC9C,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,KAAK;AAAA,EACrB,QAAQ;AACN,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,MAAI,IAAI,aAAa,WAAW,IAAI,aAAa,UAAU;AACzD,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO,IAAI,KAAK,QAAQ,OAAO,EAAE;AACnC;AAEA,SAAS,YAAY,MAAoB,SAAmD;AAC1F,SAAO;AAAA,IACL,GAAI,QAAQ,cAAc,CAAC;AAAA,IAC3B,QAAQ,KAAK;AAAA,IACb,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,YAAY,QAAQ,cAAc;AAAA,IAClC,GAAI,KAAK,QAAQ,OAAO,EAAE,MAAM,KAAK,KAAK,IAAI,CAAC;AAAA,EACjD;AACF;AAEA,SAAS,mBAAmB,YAA2C;AACrE,MAAI,CAAC,cAAc,OAAO,eAAe,YAAY,MAAM,QAAQ,UAAU,GAAG;AAC9E,UAAM,IAAI,MAAM,2CAA2C;AAAA,EAC7D;AACA,aAAW,OAAO,OAAO,KAAK,UAAU,GAAG;AACzC,QAAI,qBAAqB,IAAI,GAAG,GAAG;AACjC,YAAM,IAAI,MAAM,uBAAuB,GAAG,mDAAmD;AAAA,IAC/F;AAAA,EACF;AACA,kBAAgB,YAAY,qBAAqB;AACnD;AAEA,SAAS,gBAAgB,OAAgB,OAAe,OAAO,oBAAI,IAAY,GAAS;AACtF,MAAI,SAAS,QAAQ,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW;AAC9E,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,CAAC,OAAO,SAAS,KAAK,EAAG,OAAM,IAAI,MAAM,GAAG,KAAK,+BAA+B;AACpF;AAAA,EACF;AACA,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,MAAM,GAAG,KAAK,gCAAgC;AACvF,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,UAAM,YAAY,OAAO,eAAe,KAAK;AAC7C,QAAI,cAAc,OAAO,aAAa,cAAc,MAAM;AACxD,YAAM,IAAI,MAAM,GAAG,KAAK,uCAAuC;AAAA,IACjE;AAAA,EACF;AACA,MAAI,KAAK,IAAI,KAAK,EAAG,OAAM,IAAI,MAAM,GAAG,KAAK,4BAA4B;AACzE,OAAK,IAAI,KAAK;AACd,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,UAAM,QAAQ,CAAC,MAAM,UAAU,gBAAgB,MAAM,GAAG,KAAK,IAAI,KAAK,KAAK,IAAI,CAAC;AAAA,EAClF,OAAO;AACL,eAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC/C,sBAAgB,MAAM,GAAG,KAAK,IAAI,GAAG,IAAI,IAAI;AAAA,IAC/C;AAAA,EACF;AACA,OAAK,OAAO,KAAK;AACnB;AAEA,SAAS,OAAO,OAAe,WAA4B;AACzD,QAAM,MAAM,IAAI,IAAI,gBAAgB;AACpC,MAAI,aAAa,IAAI,MAAM,KAAK;AAChC,MAAI,UAAW,KAAI,aAAa,IAAI,aAAa,SAAS;AAC1D,SAAO,IAAI;AACb;AAEA,SAAS,YAAY,OAAsD;AACzE,MAAI,CAAC,MAAM,WAAW,GAAGA,gBAAe,IAAI,EAAG,QAAO,EAAE,OAAO,MAAM;AACrE,QAAM,MAAM,IAAI,IAAI,KAAK;AACzB,QAAM,QAAQ,IAAI,aAAa,IAAI,IAAI;AACvC,MAAI,IAAI,aAAaA,oBAAmB,IAAI,aAAa,SAAS,CAAC,OAAO;AACxE,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,QAAM,YAAY,IAAI,aAAa,IAAI,WAAW,KAAK;AACvD,SAAO,EAAE,OAAO,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC,EAAG;AACtD;AAEA,SAAS,SAAS,SAAiB,WAA4B;AAC7D,QAAM,MAAM,IAAI,IAAI,kBAAkB;AACtC,MAAI,aAAa,IAAI,MAAM,OAAO;AAClC,MAAI,UAAW,KAAI,aAAa,IAAI,aAAa,SAAS;AAC1D,SAAO,IAAI;AACb;AAEA,SAAS,cAAc,OAAwD;AAC7E,QAAM,MAAM,IAAI,IAAI,KAAK;AACzB,QAAM,UAAU,IAAI,aAAa,IAAI,IAAI;AACzC,MAAI,IAAI,aAAaA,oBAAmB,IAAI,aAAa,WAAW,CAAC,SAAS;AAC5E,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AACA,QAAM,YAAY,IAAI,aAAa,IAAI,WAAW,KAAK;AACvD,SAAO,EAAE,SAAS,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC,EAAG;AACxD;AAEA,SAAS,UAAU,OAA+B;AAChD,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,MAAM;AACZ,QAAM,KAAK,IAAI,SAAS,IAAI;AAC5B,SAAO,OAAO,OAAO,YAAY,KAAK,KAAK;AAC7C;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,iBAAiB,KAA4B;AACpD,QAAM,MAAM,IAAI,UAAU;AAC1B,SAAO,MAAM,QAAQ,GAAG,IACpB,CAAC,GAAG,IAAI,IAAI,IAAI,OAAO,CAAC,OAAqB,OAAO,OAAO,YAAY,GAAG,SAAS,CAAC,CAAC,CAAC,IACtF,CAAC;AACP;AAEA,SAAS,iBAAiB,OAA8B;AACtD,SAAO,MAAM,mBAAmB,MAAM;AACxC;AAEA,SAAS,eAAe,OAA4B;AAClD,MAAI,MAAM,oBAAoB,MAAM,qBAAqB,UAAU,KAAK;AACtE,UAAM,IAAI;AAAA,MACR,kBAAkB,MAAM,EAAE,OAAO,MAAM,gBAAgB;AAAA,IACzD;AAAA,EACF;AACF;AAEA,SAAS,YAAY,KAAkB,SAA6C;AAClF,QAAM,UAAU,IAAI;AACpB,QAAM,aAAa,0BAA0B,SAAS,QAAQ,0CAA0C;AACxG,QAAM,eAAe,OAAO,OAAO,cAAc,SAAS,aAAa,CAAC,EACrE,OAAO,CAAC,KAAK,WAAW,MAAM,QAAQ,CAAC;AAC1C,SAAO;AAAA,IACL,GAAI,UACA;AAAA,MACE,SAAS,QAAQ;AAAA,MACjB,WAAW,QAAQ,aAAa;AAAA,MAChC,iBAAiB,QAAQ;AAAA,IAC3B,IACA,CAAC;AAAA,IACL,UAAU,IAAI;AAAA,IACd,oBAAoB,aAAa;AAAA,IACjC,SAAS,WAAW;AAAA,EACtB;AACF;AAEA,SAAS,iBAAiB,KAA0B;AAClD,QAAM,MAAM,IAAI,UAAU;AAC1B,QAAM,SAAS,OAAO,QAAQ,WAC1B,MACA,OAAO,OAAO,QAAQ,YAAY,OAAQ,IAA8B,YAAY,WAClF,OAAQ,IAA4B,OAAO,IAC3C;AACN,SAAO,gBAAgB,IAAI,MAAM,KAAK,OAAO,MAAM,GAAG,GAAG,CAAC;AAC5D;AAEA,SAAS,cAAc,UAA6C;AAClE,MAAI,OAAO,aAAa,YAAY,CAAC,OAAO,SAAS,QAAQ,KAAK,WAAW,KAAK,WAAW,GAAG;AAC9F,WAAO;AAAA,EACT;AACA,SAAO,KAAK,MAAM,WAAW,GAAG;AAClC;AAEA,SAAS,kBAAkB,OAAgBG,UAAyB;AAClE,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,EAAG,OAAM,IAAI,MAAMA,QAAO;AAC9F,SAAO;AACT;AAEA,SAAS,0BAA0B,OAAgBA,UAAyB;AAC1E,MAAI,SAAS,KAAM,QAAO;AAC1B,SAAO,kBAAkB,OAAOA,QAAO;AACzC;AAEA,SAAS,cAAc,OAAwC;AAC7D,MAAI,SAAS,KAAM,QAAO,CAAC;AAC3B,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC/D,UAAM,IAAI,MAAM,wCAAwC;AAAA,EAC1D;AACA,QAAM,MAA8B,CAAC;AACrC,aAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,KAAK,GAAG;AACjD,QAAI,GAAG,IAAI,kBAAkB,QAAQ,0CAA0C,GAAG,GAAG;AAAA,EACvF;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,OAAgB,SAA2B;AACtE,MAAI;AACJ,MAAI,OAAO,UAAU,SAAU,UAAS;AAAA,WAC/B,SAAS,OAAO,UAAU,UAAU;AAC3C,UAAM,SAAS;AACf,UAAM,SAAS,OAAO,SAAS,OAAO,OAAO,UAAU,WAClD,OAAO,MAAkC,UAC1C;AACJ,aAAS,OAAO,OAAO,YAAY,WAC/B,OAAO,UACP,OAAO,WAAW,WAChB,SACA,OAAO,OAAO,WAAW,WACvB,OAAO,SACP;AAAA,EACV,MAAO,UAAS;AAChB,aAAW,UAAU,SAAS;AAC5B,QAAI,OAAQ,UAAS,OAAO,MAAM,MAAM,EAAE,KAAK,YAAY;AAAA,EAC7D;AACA,SAAO,OAAO,MAAM,GAAG,GAAG;AAC5B;;;AC7lBO,SAAS,uBAAuB,SAA6C;AAClF,SAAO,QAAQ,mBAAmB,QAAQ,gBAAgB,CAAC,QAAQ,aAAa,IAAI,CAAC;AACvF;AAEA,IAAM,YAAY,oBAAI,IAA6B;AAG5C,SAAS,iBAAiB,SAAgC;AAC/D,QAAM,KAAK,QAAQ,GAAG,KAAK;AAC3B,MAAI,CAAC,GAAI,OAAM,IAAI,MAAM,6BAA6B;AACtD,MAAI,UAAU,IAAI,EAAE,EAAG,OAAM,IAAI,MAAM,aAAa,EAAE,yBAAyB;AAC/E,YAAU,IAAI,IAAI,OAAO;AAC3B;AAEO,SAAS,gBAAgB,IAA6B;AAC3D,QAAM,UAAU,UAAU,IAAI,EAAE;AAChC,MAAI,CAAC,SAAS;AACZ,UAAM,YAAY,CAAC,GAAG,UAAU,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,IAAI,KAAK;AAC7D,UAAM,IAAI,MAAM,qBAAqB,EAAE,2BAA2B,SAAS,EAAE;AAAA,EAC/E;AACA,SAAO;AACT;AAEO,SAAS,eAAe,IAAYC,OAA8B;AACvE,SAAO,gBAAgB,EAAE,EAAE,OAAOA,KAAI;AACxC;AAMA,iBAAiB;AAAA,EACf,IAAI;AAAA,EACJ,eAAe;AAAA,EACf,OAAOC,OAAM;AACX,QAAIA,UAAS,SAAU,QAAO,iBAAiB,QAAQ;AACvD,QAAIA,UAAS,YAAa,QAAO,iBAAiB,aAAa;AAC/D,WAAO,iBAAiB,WAAW;AAAA,EACrC;AACF,CAAC;AAED,iBAAiB;AAAA,EACf,IAAI;AAAA,EACJ,eAAe;AAAA,EACf,OAAOA,OAAM;AACX,QAAIA,UAAS,SAAU,QAAO,uBAAuB,QAAQ;AAC7D,QAAIA,UAAS,YAAa,QAAO,uBAAuB,aAAa;AACrE,WAAO,uBAAuB,WAAW;AAAA,EAC3C;AACF,CAAC;AAED,iBAAiB;AAAA,EACf,IAAI;AAAA,EACJ,OAAOA,OAAM;AACX,QAAIA,UAAS,SAAU,QAAO,gBAAgB,QAAQ;AACtD,QAAIA,UAAS,YAAa,QAAO,gBAAgB,aAAa;AAC9D,WAAO,gBAAgB,WAAW;AAAA,EACpC;AACF,CAAC;AAED,iBAAiB;AAAA,EACf,IAAI;AAAA,EACJ,gBAAgB,CAAC,wBAAwB,yBAAyB;AAAA,EAClE,OAAOA,OAAM;AACX,QAAIA,UAAS,SAAU,QAAO,iBAAiB,QAAQ;AACvD,QAAIA,UAAS,YAAa,QAAO,iBAAiB,aAAa;AAC/D,WAAO,iBAAiB,WAAW;AAAA,EACrC;AACF,CAAC;;;ACtFD,SAAS,YAAAC,iBAAgB;AACzB,SAAS,cAAAC,mBAAkB;AAC3B,OAAOC,WAAU;;;ACFjB,OAAOC,WAAU;;;ACAjB,SAAS,YAAAC,WAAU,WAAW,QAAQ,OAAO,OAAO,IAAI,YAAY;AACpE,SAAS,cAAAC,mBAAkB;AAC3B,OAAOC,WAAU;AAUjB,eAAsB,SAAS,UAAiC;AAC9D,MAAI,CAACC,YAAW,QAAQ,EAAG,QAAO,EAAE,SAAS,GAAG,SAAS,CAAC,EAAE;AAC5D,MAAI;AACF,WAAO,UAAU,KAAK,MAAM,MAAMC,UAAS,UAAU,MAAM,CAAC,CAAC;AAAA,EAC/D,SAAS,KAAK;AACZ,UAAM,IAAI;AAAA,MACR,eAAe,QAAQ;AAAA,EAAmB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC5F;AAAA,EACF;AACF;AAWA,IAAM,aAAa,oBAAI,IAA2B;AAClD,IAAM,eAAe,oBAAI,QAA+C;AACxE,IAAM,eAAe,oBAAI,QAA2B;AAG7C,SAAS,SAAS,UAAkB,MAA2B;AACpE,QAAM,WAAWC,MAAK,QAAQ,QAAQ;AACtC,QAAM,WAAW,WAAW,IAAI,QAAQ,KAAK,QAAQ,QAAQ;AAC7D,QAAM,OAAO,SACV,MAAM,MAAM;AAAA,EAAC,CAAC,EACd,KAAK,MAAM,aAAa,UAAU,IAAI,CAAC;AAC1C,aAAW,IAAI,UAAU,IAAI;AAE7B,QAAM,UAAU,MAAM;AACpB,QAAI,WAAW,IAAI,QAAQ,MAAM,KAAM,YAAW,OAAO,QAAQ;AAAA,EACnE;AAIA,OAAK,KAAK,KAAK,SAAS,OAAO;AAC/B,SAAO;AACT;AAEA,eAAe,aAAa,UAAkB,MAA2B;AACvE,QAAM,MAAMA,MAAK,QAAQA,MAAK,QAAQ,QAAQ,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;AACrE,QAAM,UAAU,MAAM,gBAAgB,QAAQ;AAC9C,MAAI;AACF,UAAM,mBAAmB,UAAU,IAAI;AAAA,EACzC,UAAE;AACA,UAAM,QAAQ;AAAA,EAChB;AACF;AAEA,eAAe,mBAAmB,MAAc,MAA2B;AACzE,MAAI,OAAa,EAAE,SAAS,GAAG,SAAS,CAAC,EAAE;AAC3C,MAAIF,YAAW,IAAI,GAAG;AACpB,QAAI;AACF,aAAO,UAAU,KAAK,MAAM,MAAMC,UAAS,MAAM,MAAM,CAAC,CAAC;AAAA,IAC3D,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,+CAA+C,IAAI,KAC9C,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,aAAa,IAAI,IAAI,KAAK,oBAAI,IAAgC;AAC5E,QAAM,WAAW,oBAAI,IAAgC;AACrD,aAAW,CAAC,KAAK,KAAK,KAAK,MAAO,UAAS,IAAI,KAAK,EAAE,GAAG,MAAM,CAAC;AAEhE,QAAM,SAA0B,EAAE,GAAG,KAAK,QAAQ;AAClD,aAAW,CAAC,KAAK,KAAK,KAAK,UAAU;AACnC,UAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,QAAI,CAAC,MAAO;AACZ,WAAO,GAAG,IAAI,OAAO,GAAG,IAAK,EAAE,GAAG,OAAO,GAAG,GAAG,GAAG,MAAM,IAAkB;AAAA,EAC5E;AAGA,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACvD,QAAI,CAAC,OAAO,GAAG,EAAG,QAAO,GAAG,IAAI;AAAA,EAClC;AAOA,QAAM,UAAU,aAAa,IAAI,IAAI;AACrC,QAAM,iBAAiB,UAAU,IAAI,IAAI,OAAO,IAAI,oBAAI,IAAY;AACpE,aAAW,OAAO,eAAgB,QAAO,OAAO,GAAG;AAEnD,QAAM,SAA0B,CAAC;AACjC,aAAW,OAAO,OAAO,KAAK,MAAM,EAAE,KAAK,GAAG;AAC5C,WAAO,GAAG,IAAI,OAAO,GAAG;AAAA,EAC1B;AACA,QAAM,MAAM,GAAG,IAAI,IAAI,QAAQ,GAAG,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AACzE,MAAI;AACF,UAAM,UAAU,KAAK,KAAK,UAAU,EAAE,SAAS,GAAG,SAAS,OAAO,GAAG,MAAM,CAAC,IAAI,IAAI;AACpF,UAAM,OAAO,KAAK,IAAI;AAAA,EACxB,UAAE;AACA,UAAM,GAAG,KAAK,EAAE,OAAO,KAAK,CAAC;AAAA,EAC/B;AAIA,QAAM,eAAe,aAAa,IAAI,IAAI;AAC1C,MAAI,cAAc;AAChB,eAAW,CAAC,KAAK,KAAK,KAAK,UAAU;AACnC,YAAM,UAAU,aAAa,IAAI,GAAG;AACpC,UAAI,CAAC,QAAS;AACd,iBAAW,CAAC,OAAO,KAAK,KAAK,OAAO,QAAQ,KAAK,GAAG;AAClD,YAAI,OAAO,GAAG,QAAQ,KAAwB,GAAG,KAAK,GAAG;AACvD,iBAAO,QAAQ,KAAwB;AAAA,QACzC;AAAA,MACF;AACA,UAAI,OAAO,KAAK,OAAO,EAAE,WAAW,EAAG,cAAa,OAAO,GAAG;AAAA,IAChE;AAAA,EACF;AAEA,QAAM,aAAa,aAAa,IAAI,IAAI;AACxC,MAAI,YAAY;AACd,eAAW,OAAO,eAAgB,YAAW,OAAO,GAAG;AACvD,QAAI,WAAW,SAAS,EAAG,cAAa,OAAO,IAAI;AAAA,EACrD;AAEA,QAAM,kBAAkB,KAAK;AAC7B,OAAK,UAAU,EAAE,GAAG,OAAO;AAC3B,aAAW,CAAC,KAAK,KAAK,KAAK,gBAAgB,CAAC,GAAG;AAC7C,UAAM,OAAO,KAAK,QAAQ,GAAG,KAAK,gBAAgB,GAAG;AACrD,QAAI,KAAM,MAAK,QAAQ,GAAG,IAAI,EAAE,GAAG,MAAM,GAAG,MAAM;AAAA,EACpD;AACF;AAEO,SAAS,OAAO,MAAY,KAAa,OAAsC;AAGpF,eAAa,IAAI,IAAI,GAAG,OAAO,GAAG;AAClC,QAAM,WAAW,KAAK,QAAQ,GAAG;AACjC,QAAM,OAAO,EAAE,GAAG,UAAU,GAAG,MAAM;AACrC,OAAK,QAAQ,GAAG,IAAI;AACpB,MAAI,QAAQ,aAAa,IAAI,IAAI;AACjC,MAAI,CAAC,OAAO;AACV,YAAQ,oBAAI,IAAI;AAChB,iBAAa,IAAI,MAAM,KAAK;AAAA,EAC9B;AACA,QAAM,IAAI,KAAK,EAAE,GAAI,MAAM,IAAI,GAAG,KAAK,CAAC,GAAI,GAAG,MAAM,CAAC;AACtD,SAAO;AACT;AAUO,SAAS,OAAO,MAAY,KAAsB;AACvD,MAAI,CAAC,KAAK,QAAQ,GAAG,EAAG,QAAO;AAC/B,SAAO,KAAK,QAAQ,GAAG;AACvB,QAAM,UAAU,aAAa,IAAI,IAAI;AACrC,MAAI,SAAS;AACX,YAAQ,OAAO,GAAG;AAClB,QAAI,QAAQ,SAAS,EAAG,cAAa,OAAO,IAAI;AAAA,EAClD;AACA,MAAI,UAAU,aAAa,IAAI,IAAI;AACnC,MAAI,CAAC,SAAS;AACZ,cAAU,oBAAI,IAAI;AAClB,iBAAa,IAAI,MAAM,OAAO;AAAA,EAChC;AACA,UAAQ,IAAI,GAAG;AACf,SAAO;AACT;AAEA,IAAM,uBAAuB;AAC7B,IAAM,qBAAqB,IAAI,KAAK;AAEpC,eAAe,gBAAgB,MAA4C;AACzE,QAAM,UAAU,GAAG,IAAI;AACvB,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,aAAS;AACP,QAAI;AACF,YAAM,MAAM,OAAO;AACnB,aAAO,YAAY;AACjB,cAAM,MAAM,OAAO,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MACrC;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,OAAQ,IAA8B;AAC5C,UAAI,SAAS,SAAU,OAAM;AAC7B,UAAI;AACF,cAAM,MAAM,KAAK,IAAI,KAAK,MAAM,KAAK,OAAO,GAAG;AAC/C,YAAI,MAAM,oBAAoB;AAC5B,gBAAM,MAAM,OAAO;AACnB;AAAA,QACF;AAAA,MACF,SAAS,SAAS;AAChB,YAAK,QAAkC,SAAS,SAAU;AAAA,MAC5D;AACA,UAAI,KAAK,IAAI,KAAK,UAAU;AAC1B,cAAM,IAAI,MAAM,yCAAyC,OAAO,EAAE;AAAA,MACpE;AACA,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,CAAC,CAAC;AAAA,IACzF;AAAA,EACF;AACF;AAGO,SAAS,YAAY,MAAsC;AAChE,QAAM,SAAmC,EAAE,aAAa,GAAG,KAAK,GAAG,MAAM,EAAE;AAC3E,aAAW,SAAS,OAAO,OAAO,KAAK,OAAO,GAAG;AAC/C,UAAM,OAAO,MAAM,YAAY;AAC/B,WAAO,IAAI,KAAK,OAAO,IAAI,KAAK,MAAM,MAAM,QAAQ;AAAA,EACtD;AACA,SAAO;AACT;;;ADnNO,SAAS,mBAAmB,MAAc,aAA6B;AAC5E,QAAM,OAAOE,MAAK,QAAQ,WAAW;AACrC,QAAM,WAAWA,MAAK,WAAW,IAAI,IAAIA,MAAK,UAAU,IAAI,IAAIA,MAAK,QAAQ,MAAM,IAAI;AACvF,QAAM,WAAWA,MAAK,SAAS,MAAM,QAAQ;AAI7C,QAAM,QAAQA,MAAK,WAAW,QAAQ,IAAI,WAAW;AACrD,SAAO,MAAM,MAAMA,MAAK,GAAG,EAAE,KAAK,GAAG;AACvC;AAGO,SAAS,kBAAkB,cAAsB,aAA6B;AACnF,MAAIA,MAAK,WAAW,YAAY,EAAG,QAAOA,MAAK,UAAU,YAAY;AAGrE,MAAIA,MAAK,MAAM,WAAW,YAAY,EAAG,QAAO;AAChD,SAAOA,MAAK,QAAQ,aAAa,aAAa,MAAM,OAAO,EAAE,KAAKA,MAAK,GAAG,CAAC;AAC7E;AAGO,SAAS,mBACd,MACA,MACA,OACA,OACA,WACQ;AACR,QAAM,cAAcA,MAAK,QAAQ,KAAK,OAAO;AAC7C,QAAM,MAAM,YAAY,eAAe,SAAS,IAAK,eAAe;AACpE,QAAM,OAAO,cAAc,KAAK,QAAQ,MAAM,GAAG,CAAC,YAAY,MAAM,IAAI,KAAK;AAC7E,MAAI,UAAU,EAAG,QAAO,GAAG,IAAI,GAAG,GAAG;AACrC,QAAM,YAAY,QAAQ,mBAAmB,KAAK,GAAG,QAAQ,oBAAoB,GAAG;AACpF,SAAO,GAAG,IAAI,IAAI,QAAQ,GAAG,GAAG;AAClC;AAGO,SAAS,kBACd,QACA,MACA,OACA,OACQ;AAKR,SAAO,mBAAmB,MAAM,OAAO,MAAM,OAAO,OAAO,OAAO,SAAS;AAC7E;AAGO,SAAS,uBACd,OACA,MACA,OACQ;AACR,QAAM,SAAS,MAAM,QAAQ,KAAK;AAClC,QAAM,cAAc,OAAO,QACtB,MAAM,cAAc,CAAC,GAAG,UAAU,CAAC,WAAW,OAAO,SAAS,OAAO,IAAI,IAC1E;AACJ,QAAM,WAAW,eAAe,IAAI,cAAc;AAClD,QAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,QAAQ,MAAM,YAAY,UAAU,CAAC;AAC1E,SAAO,kBAAkB,QAAQ,MAAM,UAAU,KAAK;AACxD;AAMO,SAAS,yBAAyB,MAAY,OAA+B;AAClF,QAAM,QAAQ,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,KAAK,SAAS,KAAK,OAAO,GAAG,IAAI,CAAC,CAAC;AACtF,MAAI,UAAU;AACd,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACvD,UAAM,OAAO,MAAM,IAAI,GAAG;AAC1B,QAAI,CAAC,KAAM;AACX,QAAI,eAAe;AACnB,UAAM,UAAU,MAAM,QAAQ,IAAI,CAAC,QAAQ,UAAU;AACnD,YAAM,WAAW,uBAAuB,OAAO,MAAM,KAAK;AAC1D,YAAM,WAAW,mBAAmB,UAAU,KAAK,IAAI;AACvD,UAAI,aAAa,OAAO,KAAM,QAAO;AACrC;AACA,qBAAe;AACf,aAAO,EAAE,GAAG,QAAQ,MAAM,SAAS;AAAA,IACrC,CAAC;AACD,QAAI,aAAc,QAAO,MAAM,KAAK,EAAE,QAAQ,CAAC;AAAA,EACjD;AACA,SAAO;AACT;AAGO,SAAS,mBAAmB,OAAuB;AACxD,SAAO,UAAU,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC;AACjD;AASO,SAAS,SACd,SACA,QACA,OACA,OACQ;AACR,MAAI,UAAU,EAAG,QAAO;AACxB,SAAO,GAAG,OAAO,IAAI,OAAO,QAAQ,mBAAmB,KAAK,CAAC;AAC/D;AAGO,SAAS,oBACd,OACA,SACA,aACkB;AAClB,SAAO,MAAM,QAAQ,IAAI,CAAC,QAAQ,WAAW;AAAA,IAC3C,GAAG;AAAA,IACH;AAAA,IACA,IAAI,SAAS,SAAS,QAAQ,OAAO,MAAM,QAAQ,MAAM;AAAA,IACzD;AAAA,IACA,cAAc,kBAAkB,OAAO,MAAM,WAAW;AAAA,EAC1D,EAAE;AACJ;AAGO,SAAS,wBACd,OACA,MACkB;AAClB,SAAO,MAAM,QAAQ,IAAI,CAAC,QAAQ,WAAW;AAAA,IAC3C,GAAG;AAAA,IACH,SAAS,KAAK;AAAA,IACd,IAAI,SAAS,KAAK,SAAS,QAAQ,OAAO,MAAM,QAAQ,MAAM;AAAA,IAC9D;AAAA,IACA,cAAc,uBAAuB,OAAO,MAAM,KAAK;AAAA,EACzD,EAAE;AACJ;AA0BO,SAAS,kBAAkB,OAAkB,MAAgC;AAClF,MAAI,MAAM;AACR,UAAM,SAAS,MAAM,QAAQ,KAAK,CAAC,cAAc,UAAU,SAAS,IAAI;AACxE,WAAO,SACH,EAAE,IAAI,MAAM,OAAO,IACnB,EAAE,IAAI,OAAO,QAAQ,gBAAgB,IAAI,oBAAoB;AAAA,EACnE;AACA,MAAI,MAAM,QAAQ,WAAW,EAAG,QAAO,EAAE,IAAI,OAAO,QAAQ,qCAAqC;AACjG,MAAI,MAAM,QAAQ,WAAW,EAAG,QAAO,EAAE,IAAI,MAAM,QAAQ,MAAM,QAAQ,CAAC,EAAG;AAE7E,QAAM,UAAU,MAAM,QAAQ,OAAO,CAAC,WAAW,CAAC,OAAO,IAAI;AAC7D,MAAI,QAAQ,WAAW,EAAG,QAAO,EAAE,IAAI,MAAM,QAAQ,QAAQ,CAAC,EAAG;AACjE,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,QAAQ,GAAG,MAAM,QAAQ,MAAM;AAAA,EACjC;AACF;AAGO,SAAS,mBACd,MACA,MACA,aACkB;AAClB,QAAM,QAAQ,MAAM,QAAQ,QAAQ,KAAK,SAAS,KAAK,OAAO,CAAC;AAC/D,MAAI,OAAO,QAAQ,OAAQ,QAAO,wBAAwB,OAAO,IAAI;AACrE,SAAO,CAAC;AAAA,IACN,SAAS,KAAK;AAAA,IACd,IAAI,KAAK;AAAA,IACT,OAAO;AAAA,IACP,MAAM,KAAK;AAAA,IACX,cAAcC,MAAK,QAAQ,KAAK,OAAO;AAAA,IACvC,QAAQ;AAAA,EACV,CAAC;AACH;;;ADpLA,eAAsB,aAAa,cAA+C;AAChF,QAAM,MAAMC,MAAK,QAAQ,YAAY;AACrC,MAAI,CAACC,YAAW,GAAG,EAAG,OAAM,IAAI,MAAM,kBAAkB,GAAG,EAAE;AAC7D,QAAM,QAAQ,oBAAoB,UAAU,KAAK,MAAM,MAAMC,UAAS,KAAK,MAAM,CAAC,CAAC;AACnF,MAAI,CAAC,MAAM,SAAS;AAClB,UAAM,SAAS,qBAAqB,MAAM,MAAM,MAAM;AACtD,UAAM,IAAI,MAAM,eAAe,GAAG;AAAA,EAAiB,MAAM,EAAE;AAAA,EAC7D;AACA,MAAI;AACJ,MAAI;AACF,aAAS,wBAAwB,MAAM,KAAK,MAAM;AAAA,EACpD,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,eAAe,GAAG;AAAA,IAAmB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,IAC7F;AAAA,EACF;AACA,QAAM,SAAS,eAAe,UAAU,EAAE,GAAG,MAAM,MAAM,OAAO,CAAC;AACjE,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,SAAS,qBAAqB,OAAO,MAAM,MAAM;AACvD,UAAM,IAAI,MAAM,eAAe,GAAG;AAAA,EAAiB,MAAM,EAAE;AAAA,EAC7D;AACA,QAAM,WAAW,IAAI,IAAI,OAAO,KAAK,OAAO,KAAK,MAAM,CAAC;AACxD,QAAM,oBAA8B,CAAC;AACrC,aAAW,CAAC,SAAS,KAAK,KAAK,OAAO,QAAQ,OAAO,KAAK,MAAM,GAAG;AACjE,eAAW,WAAW,MAAM,QAAQ;AAClC,UAAI,CAAC,SAAS,IAAI,OAAO,EAAG,mBAAkB,KAAK,UAAU,OAAO,2BAA2B,OAAO,GAAG;AAAA,IAC3G;AACA,eAAW,WAAW,OAAO,KAAK,MAAM,aAAa,GAAG;AACtD,UAAI,CAAC,SAAS,IAAI,OAAO,GAAG;AAC1B,0BAAkB,KAAK,UAAU,OAAO,kCAAkC,OAAO,GAAG;AAAA,MACtF;AAAA,IACF;AACA,QAAI,MAAM,UAAU;AAClB,UAAI,CAAC,OAAO,KAAK,OAAO,MAAM,SAAS,IAAI,GAAG;AAC5C,0BAAkB;AAAA,UAChB,UAAU,OAAO,kCAAkC,MAAM,SAAS,IAAI;AAAA,QACxE;AAAA,MACF,WAAW,MAAM,SAAS,SAAS,SAAS;AAC1C,0BAAkB,KAAK,UAAU,OAAO,+CAA+C;AAAA,MACzF;AAAA,IACF;AAAA,EACF;AACA,QAAM,WAAW,oBAAI,IAAY;AACjC,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,gBAAgB,CAAC,SAAiB,UAAoB;AAC1D,QAAI,QAAQ,IAAI,OAAO,EAAG;AAC1B,QAAI,SAAS,IAAI,OAAO,GAAG;AACzB,YAAM,QAAQ,MAAM,QAAQ,OAAO;AACnC,wBAAkB;AAAA,QAChB,UAAU,OAAO,kCAAkC,CAAC,GAAG,MAAM,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,MAAM,CAAC;AAAA,MAClG;AACA;AAAA,IACF;AACA,aAAS,IAAI,OAAO;AACpB,UAAM,SAAS,OAAO,KAAK,OAAO,OAAO,GAAG,UAAU;AACtD,QAAI,UAAU,WAAW,WAAW,OAAO,KAAK,OAAO,MAAM,GAAG;AAC9D,oBAAc,QAAQ,CAAC,GAAG,OAAO,OAAO,CAAC;AAAA,IAC3C;AACA,aAAS,OAAO,OAAO;AACvB,YAAQ,IAAI,OAAO;AAAA,EACrB;AACA,aAAW,WAAW,OAAO,KAAK,OAAO,KAAK,MAAM,EAAG,eAAc,SAAS,CAAC,CAAC;AAChF,MAAI,kBAAkB,QAAQ;AAC5B,UAAM,IAAI,MAAM,eAAe,GAAG;AAAA,EAAiB,kBAAkB,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EACxG;AACA,SAAO,EAAE,UAAU,OAAO,MAAM,MAAMF,MAAK,QAAQ,GAAG,GAAG,MAAM,IAAI;AACrE;AAEA,SAAS,qBAAqB,QAA4B;AACxD,SAAO,OAAO,QAAQ,CAAC,UAAoB;AACzC,QAAI,MAAM,SAAS,iBAAiB;AAClC,aAAO,MAAM,YAAY,QAAQ,CAAC,UAAU,qBAAqB,MAAM,MAAM,EAAE,MAAM,IAAI,CAAC;AAAA,IAC5F;AACA,WAAO,CAAC,KAAK,MAAM,KAAK,KAAK,GAAG,CAAC,KAAK,MAAM,OAAO,EAAE;AAAA,EACvD,CAAC,EAAE,KAAK,IAAI;AACd;AAGA,SAAS,wBAAwB,QAA2D;AAC1F,QAAM,WAAW,oBAAI,IAAmB;AAExC,QAAM,QAAQ,CAAC,SAAiB,UAA2B;AACzD,UAAM,SAAS,SAAS,IAAI,OAAO;AACnC,QAAI,OAAQ,QAAO;AACnB,UAAM,aAAa,MAAM,QAAQ,OAAO;AACxC,QAAI,cAAc,GAAG;AACnB,YAAM,IAAI;AAAA,QACR,UAAU,OAAO,+BACZ,CAAC,GAAG,MAAM,MAAM,UAAU,GAAG,OAAO,EAAE,KAAK,MAAM,CAAC;AAAA,MACzD;AAAA,IACF;AACA,UAAM,QAAQ,OAAO,OAAO;AAC5B,QAAI,CAAC,MAAO,OAAM,IAAI,MAAM,UAAU,OAAO,iBAAiB;AAC9D,QAAI,EAAE,aAAa,QAAQ;AACzB,eAAS,IAAI,SAAS,KAAK;AAC3B,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,MAAM;AACvB,QAAI,CAAC,OAAO,OAAO,QAAQ,QAAQ,GAAG;AACpC,YAAM,IAAI,MAAM,UAAU,OAAO,4BAA4B,QAAQ,GAAG;AAAA,IAC1E;AACA,UAAM,SAAS,MAAM,UAAU,CAAC,GAAG,OAAO,OAAO,CAAC;AAClD,UAAM,EAAE,SAAS,SAAS,GAAG,MAAM,IAAI;AACvC,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,GAAG;AAAA,MACH,SACE,MAAM,WAAW,OACb,OAAO,UACP,EAAE,GAAI,OAAO,WAAW,CAAC,GAAI,GAAG,MAAM,QAAQ;AAAA,MACpD,iBAAiB,qBAAqB,OAAO,iBAAiB,MAAM,eAAe;AAAA,IACrF;AACA,UAAM,SAAS,YAAY,UAAU,MAAM;AAC3C,QAAI,CAAC,OAAO,SAAS;AACnB,YAAM,SAAS,OAAO,MAAM,OACzB,IAAI,CAAC,UAAU,UAAU,OAAO,IAAI,MAAM,KAAK,KAAK,GAAG,CAAC,KAAK,MAAM,OAAO,EAAE,EAC5E,KAAK,IAAI;AACZ,YAAM,IAAI,MAAM,MAAM;AAAA,IACxB;AACA,aAAS,IAAI,SAAS,OAAO,IAAI;AACjC,WAAO,OAAO;AAAA,EAChB;AAEA,SAAO,OAAO,YAAY,OAAO,KAAK,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,SAAS,MAAM,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/F;AAEA,SAAS,qBACP,QACA,OACyC;AACzC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,SAAS,EAAE,GAAG,OAAO;AAC3B,aAAW,CAAC,UAAU,OAAO,KAAK,OAAO,QAAQ,KAAK,GAAG;AACvD,WAAO,QAAQ,IAAI,EAAE,GAAI,OAAO,QAAQ,KAAK,CAAC,GAAI,GAAG,QAAQ;AAAA,EAC/D;AACA,SAAO;AACT;AAQA,eAAsB,aACpB,QACA,QAeyB;AACzB,QAAM,EAAE,UAAU,KAAK,IAAI;AAI3B,QAAM,mBAAmB,QAAQ;AACjC,QAAM,YAAY,oBAAI,IASnB;AACH,QAAM,cAAc,CAAC,OAAe;AAClC,QAAI,iBAAkB,QAAO;AAC7B,QAAI,WAAW,UAAU,IAAI,EAAE;AAC/B,QAAI,CAAC,UAAU;AACb,iBAAW,eAAe,IAAI,SAAS;AACvC,gBAAU,IAAI,IAAI,QAAQ;AAAA,IAC5B;AACA,WAAO;AAAA,EACT;AACA,QAAM,QAAwB,CAAC;AAE/B,QAAM,WAAW,OAAO,KAAK,SAAS,MAAM,EAAE;AAAA,IAC5C,CAAC,OAAO,CAAC,QAAQ,QAAQ,UAAU,OAAO,OAAO,SAAS,EAAE;AAAA,EAC9D;AACA,aAAW,gBAAgB,QAAQ,UAAU,CAAC,GAAG;AAC/C,QAAI,CAAC,SAAS,OAAO,YAAY,GAAG;AAClC,YAAM,IAAI;AAAA,QACR,kBAAkB,YAAY,eAAe,OAAO,KAAK,SAAS,MAAM,EAAE,KAAK,IAAI,KAAK,QAAQ;AAAA,MAClG;AAAA,IACF;AAAA,EACF;AACA,aAAW,gBAAgB,QAAQ,UAAU,CAAC,GAAG;AAC/C,QAAI,CAAC,SAAS,OAAO,YAAY,GAAG;AAClC,YAAM,IAAI,MAAM,kBAAkB,YAAY,IAAI;AAAA,IACpD;AAAA,EACF;AAEA,QAAM,oBAAoB,IAAI,IAAI,QAAQ,QAAQ,SAC9C,OAAO,SACP,OAAO,KAAK,SAAS,MAAM,CAAC;AAChC,QAAM,qBAAqB,IAAI,IAAI,iBAAiB;AACpD,aAAW,WAAW,CAAC,GAAG,iBAAiB,GAAG;AAC5C,QAAI,UAAU,SAAS,OAAO,OAAO,GAAG,UAAU;AAClD,WAAO,WAAW,CAAC,mBAAmB,IAAI,OAAO,GAAG;AAClD,yBAAmB,IAAI,OAAO;AAC9B,gBAAU,SAAS,OAAO,OAAO,GAAG,UAAU;AAAA,IAChD;AAAA,EACF;AAIA,QAAM,kBAAkB,oBAAI,IAG1B;AACF,iBAAe,eAAe,KAAa;AACzC,UAAM,MAAMA,MAAK,QAAQ,MAAM,GAAG;AAClC,QAAI,MAAM,gBAAgB,IAAI,GAAG;AACjC,QAAI,CAAC,KAAK;AACR,UAAI,CAACC,YAAW,GAAG,EAAG,OAAM,IAAI,MAAM,0BAA0B,GAAG,EAAE;AACrE,YAAM,MAAM,MAAMC,UAAS,GAAG;AAC9B,YAAM,WAAW,cAAc,GAAG;AAClC,UAAI,CAAC,SAAU,OAAM,IAAI,MAAM,8CAA8C,GAAG,EAAE;AAClF,UAAI,SAAS,QAAQ,KAAK,SAAS,SAAS,GAAG;AAC7C,cAAM,IAAI,MAAM,uCAAuC,GAAG,EAAE;AAAA,MAC9D;AACA,YAAM,EAAE,QAAQ,IAAI,SAAS,QAAQ,GAAG,MAAM,OAAO,GAAG,GAAG,GAAG,SAAS;AACvE,sBAAgB,IAAI,KAAK,GAAG;AAAA,IAC9B;AACA,WAAO;AAAA,EACT;AAEA,aAAW,WAAW,UAAU;AAC9B,UAAM,QAAQ,SAAS,OAAO,OAAO;AACrC,UAAM,iBAAiB,YAAY,MAAM,YAAY,SAAS,QAAQ;AACtE,UAAM,qBAAqB,MAAM,gBAAgB,eAAe,EAAE,KAAK,CAAC;AACxE,UAAM,mBAAmB,eAAe,iBACpC,MAAM,eAAe,eAAe,oBAAoB,EAAE,MAAM,QAAQ,CAAC,IACzE,EAAE,SAAS,mBAAmB;AAClC,UAAM,kBAAkB,iBAAiB;AACzC,UAAM,yBAAyB,iBAAiB,YAAY;AAC5D,UAAM,mBAA6B,CAAC;AACpC,UAAM,uBAA4D,CAAC;AACnE,eAAW,OAAO,MAAM,aAAa;AACnC,YAAM,cAAc,MAAM,eAAe,IAAI,IAAI;AACjD,uBAAiB,KAAK,YAAY,IAAI;AACtC,2BAAqB,KAAK,WAAW;AAAA,IACvC;AAEA,UAAM,iBAAiB,MAAM,YAAY,IAAI,CAAC,UAAU;AACtD,YAAM,MAAM,gBAAgB,IAAIF,MAAK,QAAQ,MAAM,MAAM,IAAI,CAAC;AAC9D,aAAO,EAAE,QAAQ,IAAI,QAAQ,OAAO,IAAI,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI,OAAO;AAAA,IACxF,CAAC;AACD,UAAM,aAAa,oBAAI,IAA0B;AACjD,UAAM,0BAA0B,oBAAI,IAAqB;AAEzD,eAAW,CAAC,SAAS,KAAK,KAAK,OAAO,QAAQ,SAAS,MAAM,GAAG;AAC9D,UAAI,CAAC,mBAAmB,IAAI,OAAO,EAAG;AACtC,UAAI,MAAM,OAAO,UAAU,CAAC,MAAM,OAAO,SAAS,OAAO,EAAG;AAE5D,YAAM,YAAY,MAAM;AACxB,UAAI,CAAC,eAAe,SAAS,SAAS,GAAG;AACvC,cAAM,IAAI,MAAM,aAAa,eAAe,EAAE,iCAAiC,SAAS,GAAG;AAAA,MAC7F;AACA,UAAI,OAAO,KAAK,MAAM,cAAc,EAAE,UAAU,CAAC,eAAe,eAAe;AAC7E,cAAM,IAAI;AAAA,UACR,aAAa,eAAe,EAAE,4CACxB,OAAO,IAAI,OAAO;AAAA,QAC1B;AAAA,MACF;AACA,YAAM,kBAAkB,eAAe,gBACnC,MAAM,eAAe,cAAc,MAAM,gBAAgB;AAAA,QACvD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC,IACD,EAAE,QAAQ,CAAC,EAAE;AACjB,YAAM,iBAAiB,gBAAgB;AACvC,YAAM,wBAAwB,gBAAgB,YAAY;AAC1D,8BAAwB,IAAI,SAAS,qBAAqB;AAC1D,UAAI;AACJ,UAAI;AACJ,UAAI;AAEJ,UAAI,cAAc,QAAQ;AAGxB,eAAO,qBAAqB,SACxB,KAAK,IAAI,GAAG,qBAAqB,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,IAAI,MAAM,CAAC,CAAC,IACzE,MAAM,QAAQ,MAAM,QAAQ;AACjC,gBAAQ;AACR,iBAAS;AAAA,MACX,WAAW,cAAc,SAAS;AAGhC,gBAAQ,qBAAqB,SACzB,KAAK,IAAI,GAAG,qBAAqB,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,IACvD,MAAM,YAAY;AACvB,iBAAS,qBAAqB,SAC1B,KAAK,IAAI,GAAG,qBAAqB,IAAI,CAAC,QAAQ,IAAI,MAAM,CAAC,IACxD,MAAM,YAAY;AACvB,eAAO,KAAK,IAAI,OAAO,MAAM;AAAA,MAC/B,OAAO;AACL,gBAAQ,MAAM,SAAS,MAAM,QAAQ;AACrC,iBAAS,MAAM,UAAU,MAAM,QAAQ;AACvC,eAAO,KAAK,IAAI,OAAO,MAAM;AAAA,MAC/B;AAIA,YAAM,UAAU,MAAM,cAAc,OAAO,KAAK,MAAM;AACtD,YAAM,SAAS,CAAC,MAAM,cAAc,SAAS,MAAM,YAAY,EAC5D,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO,EACd,KAAK,IAAI;AAEZ,YAAM,UAAU,MAAM,QAAQA,MAAK,KAAK,MAAM,YAAY,IAAI,GAAG,OAAO,MAAM;AAC9E,YAAM,UAAUA,MAAK,QAAQ,MAAM,MAAM,QAAQ,OAAO;AACxD,YAAM,iBAAiB,MAAM,UACzBA,MAAK,QAAQ,MAAM,MAAM,QAAQ,QAAQ,QAAQ,OAAO,CAAC,IACzD;AAIJ,YAAM,WAAW,cAAc,UAAU,OAAQ,MAAM,YAAY;AACnE,YAAM,iBACJ,uBAAuB,cAAc,UAAU,MAAM,cAAc,MAAS,KAC5E,mBAAmB,0BAA0B,MAAM,CAAC;AAEtD,YAAM,OAAO;AAAA,QACX;AAAA,QACA;AAAA,QACA,UAAU,eAAe;AAAA,QACzB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,MAAM,MAAM,SAAS,cAAc,SAAS,aAAa;AAAA,QACzD,iBAAiB,MAAM,YAAY,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,QACpD,SAAS,MAAM;AAAA,QACf,SAAS,MAAM;AAAA,QACf,QAAQ,MAAM;AAAA,QACd,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,cAAc,MAAM;AAAA,QACpB,UAAU,cAAc,UAAU,WAAW;AAAA,QAC7C,UAAU,cAAc,UAAU,MAAM,WAAW;AAAA,QACnD,UAAU,cAAc,UAAU,MAAM,WAAW;AAAA,QACnD,aAAa,cAAc,UAAU,MAAM,cAAc;AAAA,QACzD,aAAa,cAAc,UAAU,MAAM,cAAc;AAAA,QACzD,MACE,cAAc,UACV,UAAU,UAAU,cAAc,IAClC,eAAe,OAAO,QAAQ,SAAS;AAAA,QAC7C,UAAU;AAAA,QACV,YACE,cAAc,UACV,iBACA,cAAc,SACZ,eAAe,IAAI,IACnB;AAAA,MACV;AAEA,YAAM,OAAO;AAAA,QACX,GAAG,oBAAI,IAAI;AAAA,UACT,GAAG,MAAM;AAAA,UACT,GAAG,MAAM;AAAA,UACT,aAAa,SAAS,IAAI;AAAA,UAC1B,SAAS,OAAO;AAAA,UAChB,SAAS,OAAO;AAAA,QAClB,CAAC;AAAA,MACH;AACA,YAAM,WAAyB;AAAA,QAC7B,GAAG;AAAA,QACH;AAAA,QACA;AAAA,QACA,GAAI,MAAM,WAAW,iBACjB;AAAA,UACE,SAAS;AAAA,YACP,SAAS;AAAA,YACT,SAAS,MAAM,QAAQ;AAAA,YACvB,mBAAmB,MAAM,QAAQ;AAAA,YACjC,GAAI,MAAM,QAAQ,mBAAmB,OACjC,CAAC,IACD,EAAE,iBAAiB,MAAM,QAAQ,gBAAgB;AAAA,YACrD,GAAI,MAAM,QAAQ,gBACd,EAAE,eAAe,MAAM,QAAQ,cAAc,IAC7C,CAAC;AAAA,YACL,GAAI,MAAM,QAAQ,cACd,EAAE,aAAaA,MAAK,QAAQ,MAAM,MAAM,QAAQ,WAAW,EAAE,IAC7D,CAAC;AAAA,YACL,GAAI,MAAM,QAAQ,OAAO,OAAO,CAAC,IAAI,EAAE,KAAK,MAAM,QAAQ,IAAI;AAAA,UAChE;AAAA,QACF,IACA,CAAC;AAAA,QACL;AAAA,QACA,QAAQ,MAAM;AAAA;AAAA;AAAA,QAGd,UAAU;AAAA,MACZ;AACA,iBAAW,IAAI,SAAS,QAAQ;AAAA,IAClC;AAEA,UAAM,YAAY,oBAAI,IAAY;AAClC,UAAM,WAAW,OAAO,YAA2C;AACjE,YAAM,WAAW,WAAW,IAAI,OAAO;AACvC,UAAI,CAAC,UAAU;AACb,cAAM,IAAI;AAAA,UACR,UAAU,OAAO,gCAAgC,OAAO;AAAA,QAE1D;AAAA,MACF;AACA,UAAI,UAAU,IAAI,OAAO,EAAG,QAAO;AACnC,YAAM,QAAQ,SAAS,OAAO,OAAO;AACrC,UAAI,MAAM,UAAU;AAClB,YAAI,CAAC,eAAe,mBAAmB,MAAM,SAAS,IAAI,GAAG;AAC3D,gBAAM,IAAI;AAAA,YACR,aAAa,eAAe,EAAE,sBAAsB,MAAM,SAAS,IAAI;AAAA,UACzE;AAAA,QACF;AACA,cAAM,aAAa,MAAM,SAAS,MAAM,SAAS,IAAI;AACrD,cAAM,aAAa,WAAW,SAAS,YACpC,WAAW,SAASA,MAAK,QAAQ,MAAM,WAAW,MAAM,IAAI,WAAW;AAC1E,cAAM,cAAc,MAAM,sBAAsB,YAAY,iBAAiB;AAC7E,cAAM,WAAW,MAAM,SAAS,OAC5BA,MAAK,QAAQ,MAAM,MAAM,SAAS,IAAI,IACtC;AACJ,cAAM,YAAY,WACd,MAAM,sBAAsB,UAAU,iBAAiB,KAAK,IAC5D;AACJ,YACE,eAAe,cACd,YAAY,UAAU,UAAU,SAAS,YAAY,WAAW,UAAU,SAC3E;AACA,gBAAM,IAAI;AAAA,YACR,qBAAqB,OAAO,IAAI,OAAO,OAAO,UAAU,KAAK,IAAI,UAAU,MAAM,YACrE,MAAM,SAAS,IAAI,OAAO,YAAY,KAAK,IAAI,YAAY,MAAM;AAAA,UAC/E;AAAA,QACF;AACA,iBAAS,WAAW;AAAA,UAClB,MAAM,MAAM,SAAS;AAAA,UACrB,eAAe,MAAM,SAAS;AAAA,UAC9B;AAAA,UACA,cAAc,aAAa,QAAQ;AAAA,UACnC,aAAa,aAAa,SAAS;AAAA,UACnC,cAAc,aAAa,UAAU;AAAA,UACrC,cAAc,aAAa,UAAU;AAAA,UACrC;AAAA,UACA,GAAI,WACA;AAAA,YACE;AAAA,YACA,YAAY,WAAW,QAAQ;AAAA,YAC/B,WAAW,WAAW,SAAS;AAAA,YAC/B,YAAY,WAAW,UAAU;AAAA,YACjC,YAAY,WAAW,UAAU;AAAA,UACnC,IACA,CAAC;AAAA,UACL,GAAI,MAAM,SAAS,YAAY,OAAO,CAAC,IAAI,EAAE,UAAU,MAAM,SAAS,SAAS;AAAA,QACjF;AAAA,MACF;AACA,eAAS,WAAW;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA,wBAAwB,IAAI,OAAO;AAAA,MACrC;AACA,qBAAe,WAAW,UAAU,cAAc;AAClD,YAAM,WAAW,qBAAqB,eAAe,IAAI,eAAe,SAAS,QAAQ,CAAC;AAC1F,eAAS,OAAO,SAAS;AACzB,eAAS,WAAW,SAAS;AAC7B,eAAS,aAAa,SAAS;AAC/B,gBAAU,IAAI,OAAO;AACrB,aAAO;AAAA,IACT;AAEA,eAAW,WAAW,OAAO,KAAK,SAAS,MAAM,GAAG;AAClD,UAAI,CAAC,kBAAkB,IAAI,OAAO,KAAK,CAAC,WAAW,IAAI,OAAO,EAAG;AACjE,YAAM,KAAK,MAAM,SAAS,OAAO,CAAC;AAAA,IACpC;AAAA,EACF;AAEA,QAAM,WAAW,oBAAI,IAAoB;AACzC,QAAM,cAAc,CAAC,MAAc,UAAkB;AACnD,UAAM,WAAW,SAAS,IAAI,IAAI;AAClC,QAAI,UAAU;AACZ,YAAM,IAAI,MAAM,qBAAqB,QAAQ,QAAQ,KAAK,oBAAoB,IAAI,EAAE;AAAA,IACtF;AACA,aAAS,IAAI,MAAM,KAAK;AAAA,EAC1B;AACA,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,GAAG,KAAK,OAAO,IAAI,KAAK,OAAO;AAC3C,gBAAY,KAAK,SAAS,GAAG;AAC7B,QAAI,KAAK,SAAS;AAChB,UAAI,KAAK,cAAc,UAAU;AAC/B,cAAM,cAAc,OAAO,OAAO,KAAK,kBAAkB,CAAC,CAAC,EAAE,KAAK,MAAM,OAAO;AAC/E,cAAM,QAAQ,aAAa,UAAU;AACrC,iBAAS,QAAQ,GAAG,QAAQ,OAAO,SAAS;AAC1C,gBAAM,OAAO,SAAS,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC;AACpD;AAAA,YACE;AAAA,cACE,EAAE,GAAG,MAAM,SAAS,KAAK,QAAQ,QAAQ;AAAA,cACzC;AAAA,cACA;AAAA,cACA;AAAA,cACA,UAAU;AAAA,YACZ;AAAA,YACA,GAAG,GAAG,YAAY,IAAI;AAAA,UACxB;AAAA,QACF;AAAA,MACF,OAAO;AACL,oBAAY,KAAK,QAAQ,SAAS,GAAG,GAAG,iBAAiB;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,QAAQ,MAAsB;AACrC,QAAM,YAAYA,MAAK,QAAQ,IAAI;AACnC,SAAO,YAAY,GAAG,KAAK,MAAM,GAAG,CAAC,UAAU,MAAM,CAAC,SAAS,GAAG,IAAI;AACxE;AAEA,eAAe,sBACb,MACA,OACA,gBACyF;AACzF,MAAI,CAACC,YAAW,IAAI,EAAG,QAAO;AAC9B,QAAM,QAAQ,MAAMC,UAAS,IAAI;AACjC,QAAM,WAAW,cAAc,KAAK;AACpC,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,GAAG,KAAK,mCAAmC,IAAI,EAAE;AAChF,MAAI,kBAAkB,SAAS,WAAW,gBAAgB;AACxD,UAAM,IAAI,MAAM,GAAG,KAAK,YAAY,eAAe,YAAY,CAAC,KAAK,IAAI,EAAE;AAAA,EAC7E;AACA,SAAO,EAAE,MAAM,OAAO,KAAK,GAAG,GAAG,SAAS;AAC5C;AAGA,eAAsB,mBACpB,QACA,SAC+B;AAC/B,QAAM,QAAQ,OAAO,SAAS,OAAO,OAAO;AAC5C,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kBAAkB,OAAO,GAAG;AACxD,QAAM,MAA4B,CAAC;AACnC,aAAW,OAAO,MAAM,aAAa;AACnC,UAAM,OAAOF,MAAK,QAAQ,OAAO,MAAM,IAAI,IAAI;AAC/C,UAAM,MAAM,MAAME,UAAS,IAAI;AAC/B,UAAM,WAAW,cAAc,GAAG;AAClC,QAAI,CAAC,SAAU,OAAM,IAAI,MAAM,8CAA8C,IAAI,EAAE;AACnF,QAAI,SAAS,QAAQ,KAAK,SAAS,SAAS,GAAG;AAC7C,YAAM,IAAI,MAAM,uCAAuC,IAAI,EAAE;AAAA,IAC/D;AACA,QAAI,KAAK,EAAE,QAAQ,IAAI,SAAS,QAAQ,GAAG,GAAG,SAAS,CAAC;AAAA,EAC1D;AACA,SAAO;AACT;AAQO,SAAS,cACd,KACgE;AAChE,MACE,IAAI,UAAU,MACd,IAAI,aAAa,CAAC,MAAM,cACxB,IAAI,aAAa,CAAC,MAAM,aACxB,IAAI,SAAS,SAAS,IAAI,EAAE,MAAM,QAClC;AACA,WAAO,EAAE,OAAO,IAAI,aAAa,EAAE,GAAG,QAAQ,IAAI,aAAa,EAAE,GAAG,QAAQ,MAAM;AAAA,EACpF;AAEA,MAAI,IAAI,SAAS,KAAK,IAAI,CAAC,MAAM,OAAQ,IAAI,CAAC,MAAM,IAAM,QAAO;AACjE,MAAI,SAAS;AACb,SAAO,SAAS,IAAI,IAAI,QAAQ;AAC9B,QAAI,IAAI,MAAM,MAAM,IAAM,QAAO;AACjC,WAAO,IAAI,MAAM,MAAM,IAAM;AAC7B,UAAM,SAAS,IAAI,QAAQ;AAC3B,QAAI,UAAU,QAAQ,WAAW,OAAQ,WAAW,IAAM;AAC1D,QAAI,WAAW,KAAS,UAAU,OAAQ,UAAU,IAAO;AAC3D,QAAI,SAAS,IAAI,IAAI,OAAQ,QAAO;AACpC,UAAM,SAAS,IAAI,aAAa,MAAM;AACtC,QAAI,SAAS,KAAK,SAAS,SAAS,IAAI,OAAQ,QAAO;AACvD,UAAM,iBACJ,UAAU,OACV,UAAU,OACV,CAAC,CAAC,KAAM,KAAM,GAAI,EAAE,SAAS,MAAM;AACrC,QAAI,gBAAgB;AAClB,UAAI,SAAS,EAAG,QAAO;AACvB,aAAO;AAAA,QACL,OAAO,IAAI,aAAa,SAAS,CAAC;AAAA,QAClC,QAAQ,IAAI,aAAa,SAAS,CAAC;AAAA,QACnC,QAAQ;AAAA,MACV;AAAA,IACF;AACA,cAAU;AAAA,EACZ;AACA,SAAO;AACT;;;AG1oBA,SAAS,gBAAAC,qBAAoB;AAC7B,OAAOC,WAAU;AA+EV,SAAS,kBAAkB,KAAc,gBAAuC;AACrF,MAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,QAAQ;AACtC,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC3E;AACA,QAAM,UAAUC,MAAK,QAAQA,MAAK,QAAQ,cAAc,CAAC;AACzD,SAAO,IAAI,IAAI,CAAC,OAAO,MAAM;AAC3B,UAAM,IAAI;AACV,QAAI,OAAO,EAAE,OAAO,YAAY,OAAO,EAAE,SAAS,UAAU;AAC1D,YAAM,IAAI,MAAM,YAAY,CAAC,gCAAgC;AAAA,IAC/D;AACA,WAAO,EAAE,IAAI,EAAE,IAAI,MAAMA,MAAK,QAAQ,SAAS,EAAE,IAAI,EAAE;AAAA,EACzD,CAAC;AACH;AAYO,SAAS,YACd,QACA,UAAwD,CAAC,GAC5C;AACb,MAAI,CAAC,OAAO,OAAQ,OAAM,IAAI,MAAM,+BAA+B;AAQnE,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,QAAQ,oBAAI,IAAY;AAC9B,aAAW,SAAS,QAAQ;AAC1B,QAAI,KAAK,IAAI,MAAM,EAAE,EAAG,OAAM,IAAI,MAAM,EAAE;AAC1C,SAAK,IAAI,MAAM,EAAE;AAAA,EACnB;AACA,MAAI,MAAM,MAAM;AACd,UAAM,IAAI,MAAM,wCAAwC,CAAC,GAAG,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,EACjF;AAKA,QAAM,UAAU,QAAQ,UAAU,UAC9B,CAAC,GAAG,MAAM,IACV,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AAEvD,QAAM,UAA2E,CAAC;AAClF,QAAM,UAA4C,CAAC;AACnD,QAAM,UAA0B,CAAC;AAEjC,aAAW,SAAS,SAAS;AAC3B,QAAI,aAA4B;AAChC,QAAI;AACF,YAAM,QAAQC,cAAa,MAAM,IAAI;AACrC,mBAAa,OAAO,KAAK;AACzB,YAAM,MAAM,UAAU,KAAK;AAC3B,cAAQ,KAAK,EAAE,IAAI,MAAM,IAAI,OAAO,IAAI,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI,OAAO,CAAC;AACvF,cAAQ,KAAK,EAAE,GAAG,OAAO,QAAQ,YAAY,UAAU,KAAK,CAAC;AAAA,IAC/D,SAAS,KAAK;AACZ,cAAQ,KAAK,EAAE,IAAI,MAAM,IAAI,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AACvF,cAAQ,KAAK,EAAE,GAAG,OAAO,QAAQ,YAAY,UAAU,MAAM,CAAC;AAAA,IAChE;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,QAAQ;AACnB,UAAM,IAAI,MAAM,wCAAmC,QAAQ,MAAM,WAAW;AAAA,EAC9E;AAEA,QAAM,QAAQ,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACrD,QAAM,QAAQ,KAAK,IAAI,GAAG,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AACtD,QAAM,UAAU,QAAQ,WAAW,KAAK,KAAK,KAAK,KAAK,QAAQ,MAAM,CAAC;AACtE,QAAM,OAAO,KAAK,KAAK,QAAQ,SAAS,OAAO;AAE/C,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS,OAAO;AAEtB,QAAM,OAAO,OAAO,MAAM,SAAS,SAAS,CAAC;AAC7C,QAAM,SAAwB,CAAC;AAE/B,UAAQ,QAAQ,CAAC,QAAQ,MAAM;AAC7B,UAAM,KAAM,IAAI,UAAW;AAC3B,UAAM,KAAK,KAAK,MAAM,IAAI,OAAO,IAAI;AACrC,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAM,MAAM,IAAI,OAAO,QAAQ;AAC/B,YAAM,QAAQ,KAAK,KAAK,SAAS,MAAM;AACvC,aAAO,OAAO,KAAK,MAAM,KAAK,KAAK,MAAM,OAAO,QAAQ,CAAC;AAAA,IAC3D;AACA,WAAO,KAAK,EAAE,IAAI,OAAO,IAAI,GAAG,IAAI,GAAG,IAAI,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO,CAAC;AAAA,EACzF,CAAC;AAED,SAAO;AAAA,IACL,KAAK,cAAc,QAAQ,QAAQ,IAAI;AAAA,IACvC,OAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAAA,MACvC,MAAM,EAAE,OAAO,OAAO,QAAQ,MAAM;AAAA,MACpC;AAAA,MACA;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,UACd,MACA,SACA,aACA,UAMI,CAAC,GACQ;AACb,MAAI,QAAQ,iBAAiB;AAC3B,QAAI,QAAQ,aAAa,QAAQ;AAC/B,YAAM,IAAI,MAAM,6FAA6F;AAAA,IAC/G;AACA,UAAMC,UAAS,OAAO,QAAQ,QAAQ,eAAe,EAAE,IAAI,CAAC,CAAC,IAAI,MAAM,OAAO;AAAA,MAC5E;AAAA,MACA,MAAMF,MAAK,QAAQ,MAAM;AAAA,IAC3B,EAAE;AACF,QAAI,CAACE,QAAO,OAAQ,OAAM,IAAI,MAAM,0CAA0C,OAAO,IAAI;AACzF,UAAMC,UAAS,YAAYD,SAAQ,OAAO;AAC1C,WAAO,EAAE,GAAGC,SAAQ,OAAO,EAAE,GAAGA,QAAO,OAAO,OAAO,QAAQ,EAAE;AAAA,EACjE;AAGA,QAAM,SAAS,GAAG,OAAO;AACzB,QAAM,UAAU,OAAO,QAAQ,KAAK,OAAO,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,IAAI,WAAW,MAAM,CAAC;AAErF,MAAI,CAAC,QAAQ,QAAQ;AACnB,UAAM,IAAI;AAAA,MACR,+BAA+B,OAAO,kCAAkC,OAAO;AAAA,IACjF;AAAA,EACF;AAEA,QAAM,SAAwB,CAAC;AAC/B,QAAM,WAA6C,CAAC;AAEpD,aAAW,CAAC,KAAK,KAAK,KAAK,SAAS;AAClC,UAAM,KAAK,IAAI,MAAM,OAAO,MAAM;AAClC,UAAM,UAAU,oBAAoB,OAAO,IAAI,WAAW;AAC1D,QAAI,WAAW;AACf,QAAI,QAAQ,aAAa,QAAQ;AAC/B,iBAAW,QAAQ;AAAA,QACjB,CAAC,WAAW,OAAO,QAAQ,QAAQ,YAAa,SAAS,OAAO,IAAI;AAAA,MACtE;AAAA,IACF,WAAW,QAAQ,aAAa;AAC9B,YAAM,YAAY,kBAAkB,KAAK;AACzC,iBAAW,UAAU,KACjB,QAAQ,OAAO,CAAC,WAAW,OAAO,SAAS,UAAU,OAAO,IAAI,IAChE,CAAC;AAAA,IACP;AACA,QAAI,CAAC,SAAS,QAAQ;AACpB,YAAM,SAAS,QAAQ,aAAa,SAChC,8BAA8B,QAAQ,YAAY,KAAK,IAAI,CAAC,KAC5D,QAAQ,eAAe,QAAQ,SAAS,IACtC,qDACA;AACN,eAAS,KAAK,EAAE,IAAI,OAAO,CAAC;AAC5B;AAAA,IACF;AACA,eAAW,UAAU,SAAU,QAAO,KAAK,EAAE,IAAI,OAAO,IAAI,MAAM,OAAO,aAAa,CAAC;AAAA,EACzF;AAEA,MAAI,CAAC,OAAO,QAAQ;AAClB,UAAM,IAAI,MAAM,kCAAkC,OAAO,YAAO,SAAS,MAAM,WAAW;AAAA,EAC5F;AAEA,QAAM,SAAS,YAAY,QAAQ,OAAO;AAC1C,SAAO;AAAA,IACL,GAAG;AAAA,IACH,OAAO,EAAE,GAAG,OAAO,OAAO,OAAO,QAAQ;AAAA,IACzC,SAAS,CAAC,GAAG,UAAU,GAAG,OAAO,OAAO;AAAA,EAC1C;AACF;AAgDO,SAAS,aACd,YACA,SACc;AACd,MAAI,CAAC,WAAW,OAAQ,OAAM,IAAI,MAAM,gCAAgC;AACxE,QAAM,EAAE,WAAW,WAAW,IAAI;AAClC,MAAI,aAAa,KAAK,cAAc,GAAG;AACrC,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,QAAM,SAAS,oBAAI,IAAoB;AACvC,aAAW,KAAK,YAAY;AAC1B,UAAM,MAAM,GAAG,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACrC,UAAM,QAAQ,OAAO,IAAI,GAAG;AAC5B,QAAI,OAAO;AACT,YAAM,IAAI;AAAA,QACR,kBAAkB,EAAE,EAAE,UAAU,KAAK,qBAAqB,GAAG;AAAA,MAE/D;AAAA,IACF;AACA,WAAO,IAAI,KAAK,EAAE,EAAE;AAAA,EACtB;AAEA,QAAM,SAAiF,CAAC;AACxF,QAAM,UAA4C,CAAC;AACnD,QAAM,UAA0B,CAAC;AACjC,aAAW,KAAK,YAAY;AAC1B,QAAI,aAA4B;AAChC,QAAI;AACF,YAAM,QAAQF,cAAa,EAAE,IAAI;AACjC,mBAAa,OAAO,KAAK;AACzB,YAAM,MAAM,UAAU,KAAK;AAC3B,UAAI,IAAI,QAAQ,aAAa,IAAI,SAAS,YAAY;AACpD,cAAM,IAAI;AAAA,UACR,MAAM,IAAI,KAAK,IAAI,IAAI,MAAM,qBAAqB,SAAS,IAAI,UAAU;AAAA,QAC3E;AAAA,MACF;AACA,aAAO,KAAK,EAAE,GAAG,OAAO,IAAI,OAAO,QAAQ,IAAI,QAAQ,QAAQ,IAAI,OAAO,CAAC;AAC3E,cAAQ,KAAK,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,MAAM,QAAQ,YAAY,UAAU,KAAK,CAAC;AAAA,IAC7E,SAAS,KAAK;AACZ,cAAQ,KAAK,EAAE,IAAI,EAAE,IAAI,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AACnF,cAAQ,KAAK,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,MAAM,QAAQ,YAAY,UAAU,MAAM,CAAC;AAAA,IAC9E;AAAA,EACF;AACA,MAAI,CAAC,OAAO,QAAQ;AAClB,UAAM,IAAI,MAAM,yCAAoC,QAAQ,MAAM,WAAW;AAAA,EAC/E;AAKA,QAAM,SAAS,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;AACzD,QAAM,SAAS,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;AACzD,QAAM,OAAO,QAAQ,UAAU,UAAU,QAAQ,OAAO,IAAI;AAC5D,QAAM,SAAS,KAAK,KAAK,SAAS,KAAK,WAAW,MAAM,SAAS,CAAC;AAClE,QAAM,SAAS,KAAK,KAAK,SAAS,KAAK,YAAY,MAAM,UAAU,CAAC;AAEpE,QAAM,OAAO,OAAO,MAAM,SAAS,SAAS,CAAC;AAC7C,MAAI,MAAM;AACR,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAM,MAAM,IAAI,KAAK,QAAQ;AAC7B,WAAK,OAAO,KAAK,MAAM,IAAI,SAAS,GAAG,KAAK,MAAM,KAAK,QAAQ,CAAC;AAAA,IAClE;AAAA,EACF;AAEA,QAAM,SAAwB,CAAC;AAC/B,aAAW,EAAE,GAAG,OAAO,QAAQ,OAAO,KAAK,QAAQ;AACjD,UAAM,KAAK,EAAE,KAAK,CAAC,IAAI;AACvB,UAAM,KAAK,EAAE,KAAK,CAAC,IAAI;AAIvB,aAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,WAAK,KAAK,KAAK,KAAK,KAAK,SAAS,MAAM,KAAK,KAAK,KAAK,SAAS,KAAK,aAAa,CAAC;AAAA,IACrF;AACA,aAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,YAAM,MAAM,IAAI,QAAQ;AACxB,aAAO,KAAK,QAAQ,KAAK,KAAK,SAAS,MAAM,GAAG,KAAK,MAAM,QAAQ,CAAC;AAAA,IACtE;AACA,WAAO,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,OAAO,OAAO,CAAC;AAAA,EACvD;AAEA,SAAO,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAC5C,SAAO;AAAA,IACL,KAAK,cAAc,QAAQ,QAAQ,IAAI;AAAA,IACvC,OAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO;AAAA,MACvC,MAAM,EAAE,OAAO,WAAW,QAAQ,WAAW;AAAA,MAC7C;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,SAAS;AAAA,EACrB;AACF;AASO,SAAS,WACd,MACA,SACA,aACA,OACA,OACA,UAAkC,CAAC,GACnC,cAAsC,CAAC,GACzB;AAId,QAAM,MAAM,OAAO,KAAK,KAAK;AAC7B,MAAI,CAAC,IAAI,QAAQ;AACf,UAAM,IAAI;AAAA,MACR,uBAAuB,OAAO;AAAA,IAEhC;AAAA,EACF;AAEA,QAAM,aAA+B,CAAC;AACtC,QAAM,UAA4C,CAAC;AACnD,aAAW,MAAM,KAAK;AACpB,UAAM,OAAO,MAAM,EAAE;AACrB,UAAM,SAAS,QAAQ,EAAE;AACzB,QAAI,QAAQ;AACV,iBAAW,KAAK,EAAE,IAAI,MAAMD,MAAK,QAAQ,aAAa,MAAM,GAAG,KAAK,CAAC;AACrE;AAAA,IACF;AACA,UAAM,QAAQ,KAAK,QAAQ,GAAG,OAAO,IAAI,EAAE,EAAE;AAC7C,QAAI,CAAC,OAAO;AACV,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,QAAQ,2BAA2B,OAAO;AAAA,MAC5C,CAAC;AACD;AAAA,IACF;AACA,UAAM,YAAY,kBAAkB,OAAO,YAAY,EAAE,CAAC;AAC1D,QAAI,CAAC,UAAU,IAAI;AACjB,cAAQ,KAAK,EAAE,IAAI,QAAQ,UAAU,OAAO,CAAC;AAC7C;AAAA,IACF;AACA,eAAW,KAAK,EAAE,IAAI,MAAM,kBAAkB,UAAU,OAAO,MAAM,WAAW,GAAG,KAAK,CAAC;AAAA,EAC3F;AAEA,MAAI,CAAC,WAAW,QAAQ;AACtB,UAAM,SAAS,QAAQ,SACnB,KAAK,QAAQ,IAAI,CAAC,SAAS,GAAG,KAAK,EAAE,KAAK,KAAK,MAAM,EAAE,EAAE,KAAK,IAAI,CAAC,MACnE;AACJ,UAAM,IAAI;AAAA,MACR,+BAA+B,OAAO,MAAM,IAAI,MAAM,wGAEzB,OAAO,+BAA+B,MAAM;AAAA,IAC3E;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,OAAOC,cAAaD,MAAK,QAAQ,aAAa,MAAM,IAAI,CAAC,IAAI;AACnF,QAAM,UAAU,aAAa,YAAY;AAAA,IACvC,WAAW,MAAM;AAAA,IACjB,YAAY,MAAM;AAAA,IAClB;AAAA,EACF,CAAC;AACD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,MAAM,OACX,CAAC;AAAA,MACC,IAAI;AAAA,MACJ,MAAMA,MAAK,QAAQ,aAAa,MAAM,IAAI;AAAA,MAC1C,QAAQ,OAAO,OAAQ;AAAA,MACvB,UAAU;AAAA,IACZ,GAAG,GAAG,QAAQ,OAAO,IACrB,QAAQ;AAAA,IACZ,OAAO,EAAE,GAAG,QAAQ,OAAO,OAAO,QAAQ;AAAA,IAC1C,SAAS,CAAC,GAAG,SAAS,GAAG,QAAQ,OAAO;AAAA,EAC1C;AACF;;;AC5eA,SAAS,cAAAI,mBAAkB;AAC3B,OAAOC,YAAU;;;ACDjB,SAAS,cAAAC,mBAAkB;AAC3B,OAAOC,YAAU;;;ACDjB,OAAOC,YAAU;AACjB,SAAS,gBAAgB;AACzB,SAAS,SAAS,YAAAC,WAAU,MAAAC,WAAU;AACtC,SAAS,cAAc;AACvB,SAAS,iBAAiB;;;ACJ1B,OAAOC,WAAU;AACjB,SAAS,cAAAC,aAAY,cAAAC,mBAAkB;AACvC,SAAS,SAAAC,QAAO,YAAAC,WAAU,UAAAC,SAAQ,MAAAC,KAAI,aAAAC,kBAAiB;AAkFvD,IAAM,qBAAqB,oBAAI,IAAY;AAE3C,SAAS,QAAQ,OAAwB;AACvC,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAEA,SAAS,OAAO,MAAmC;AACjD,SAAON,YAAW,QAAQ,EAAE,OAAO,IAAI,EAAE,OAAO,KAAK;AACvD;AAEA,SAAS,iBAAiB,MAAc,IAAoB;AAC1D,SAAOD,MAAK,SAAS,MAAMA,MAAK,QAAQ,EAAE,CAAC,EAAE,MAAMA,MAAK,GAAG,EAAE,KAAK,GAAG,KAAK;AAC5E;AAEA,SAASQ,WAAU,OAAyB;AAC1C,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO;AACtF,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,CAAC,OAAO,SAAS,KAAK,EAAG,OAAM,IAAI,MAAM,6CAA6C;AAC1F,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAIA,UAAS;AACpD,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,SAAkC,CAAC;AACzC,eAAW,OAAO,OAAO,KAAK,KAAK,EAAE,KAAK,GAAG;AAC3C,YAAM,OAAQ,MAAkC,GAAG;AACnD,UAAI,SAAS,OAAW,QAAO,GAAG,IAAIA,WAAU,IAAI;AAAA,IACtD;AACA,WAAO;AAAA,EACT;AACA,QAAM,IAAI,MAAM,sCAAsC,OAAO,KAAK,UAAU;AAC9E;AAEA,SAAS,YAAY,YAA8F;AACjH,SAAO,OAAO,KAAK,UAAUA,WAAU;AAAA,IACrC,MAAM,WAAW;AAAA,IACjB,SAAS,WAAW;AAAA,IACpB,SAAS,WAAW;AAAA,IACpB,SAAS,WAAW;AAAA,EACtB,CAAC,CAAC,CAAC;AACL;AAEA,SAAS,sBAAsB,UAAkB,MAAsC;AACrF,MAAI;AACJ,MAAI;AACF,UAAM,KAAK,MAAM,IAAI;AAAA,EACvB,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,GAAG,QAAQ,uBAAuB,QAAQ,KAAK,CAAC,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,EACtF;AACA,MACE,IAAI,WAAW,+BACf,IAAI,YAAY,KACf,IAAI,SAAS,UAAU,IAAI,SAAS,WAAW,IAAI,SAAS,aAAa,IAAI,SAAS,YACvF,OAAO,IAAI,gBAAgB,YAC3B,IAAI,YAAY,UAChB,CAAC,MAAM,QAAQ,IAAI,OAAO,KAC1B,CAAC,MAAM,QAAQ,IAAI,OAAO,GAC1B;AACA,UAAM,IAAI,MAAM,GAAG,QAAQ,+CAA+C;AAAA,EAC5E;AACA,aAAW,UAAU,IAAI,SAAS;AAChC,QACE,CAAC,UACD,OAAO,OAAO,OAAO,YACrB,OAAO,OAAO,SAAS,YACtB,OAAO,WAAW,QAAQ,OAAO,OAAO,WAAW,YACpD,OAAO,OAAO,aAAa,WAC3B;AACA,YAAM,IAAI,MAAM,GAAG,QAAQ,uCAAuC;AAAA,IACpE;AAAA,EACF;AACA,aAAW,UAAU,IAAI,SAAS;AAChC,QAAI,CAAC,UAAU,OAAO,OAAO,SAAS,YAAY,OAAO,OAAO,WAAW,UAAU;AACnF,YAAM,IAAI,MAAM,GAAG,QAAQ,uCAAuC;AAAA,IACpE;AAAA,EACF;AACA,SAAO;AACT;AAGA,eAAsB,2BACpB,cACiC;AACjC,QAAM,WAAWR,MAAK,QAAQ,YAAY;AAC1C,SAAO,sBAAsB,UAAU,MAAMI,UAAS,UAAU,MAAM,CAAC;AACzE;AAEA,eAAe,aAAa,MAAsC;AAChE,MAAI;AACF,WAAO,MAAMA,UAAS,IAAI;AAAA,EAC5B,SAAS,OAAO;AACd,QAAI,OAAO,OAAO,QAAQ,EAAG,QAAO;AACpC,UAAM;AAAA,EACR;AACF;AAEA,SAAS,kBAAkB,SAAyB;AAClD,SAAO,GAAG,OAAO;AACnB;AAEA,SAAS,eAAe,KAAsB;AAC5C,MAAI,CAAC,OAAO,UAAU,GAAG,KAAK,MAAM,EAAG,QAAO;AAC9C,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO;AAAA,EACT,SAAS,OAAO;AACd,WAAO,CAAC,OAAO,OAAO,OAAO;AAAA,EAC/B;AACF;AAEA,SAAS,mBACP,WACA,aACA,MACS;AACT,SACEJ,MAAK,QAAQ,SAAS,MAAMA,MAAK,QAAQ,WAAW,KACpDA,MAAK,SAAS,SAAS,EAAE;AAAA,IACvB,IAAIA,MAAK,SAAS,WAAW,CAAC,cAAc,IAAI;AAAA,EAClD;AAEJ;AAEA,SAAS,iBAAiB,SAAiB,MAAmC;AAC5E,MAAI;AACJ,MAAI;AACF,UAAM,KAAK,MAAM,IAAI;AAAA,EACvB,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,GAAG,OAAO,mCAAmC,QAAQ,KAAK,CAAC,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,EACjG;AACA,MACE,IAAI,WAAW,oCACf,IAAI,YAAY,KAChB,CAAC,OAAO,UAAU,IAAI,GAAG,KACzB,OAAO,IAAI,cAAc,YACzB,CAAC,MAAM,QAAQ,IAAI,OAAO,KAC1B,CAAC,IAAI,QAAQ,QACb;AACA,UAAM,IAAI,MAAM,GAAG,OAAO,2CAA2C;AAAA,EACvE;AACA,SAAO;AACT;AAEA,eAAe,uBAAuB,SAAgC;AAGpE,QAAMM,IAAG,SAAS,EAAE,OAAO,KAAK,CAAC;AACjC,QAAMA,IAAG,kBAAkB,OAAO,GAAG,EAAE,OAAO,KAAK,CAAC;AACtD;AAEA,eAAe,2BACb,cACA,qBACe;AACf,QAAM,UAAUN,MAAK,QAAQ,YAAY;AACzC,QAAM,QAAQ,MAAM,aAAa,OAAO;AACxC,MAAI,CAAC,OAAO;AACV,UAAMM,IAAG,kBAAkB,OAAO,GAAG,EAAE,OAAO,KAAK,CAAC;AACpD;AAAA,EACF;AAEA,MAAI,mBAAmB,IAAI,OAAO,GAAG;AACnC,UAAM,IAAI,MAAM,2DAA2D,OAAO,GAAG;AAAA,EACvF;AACA,QAAM,cAAc,iBAAiB,SAAS,MAAM,SAAS,MAAM,CAAC;AACpE,MAAI,YAAY,QAAQ,QAAQ,OAAO,eAAe,YAAY,GAAG,GAAG;AACtE,UAAM,IAAI;AAAA,MACR,wBAAwB,OAAO,mCAAmC,YAAY,GAAG;AAAA,IAEnF;AAAA,EACF;AAEA,aAAW,SAAS,YAAY,SAAS;AACvC,QACE,OAAO,MAAM,gBAAgB,YAC7B,OAAO,MAAM,UAAU,YACvB,OAAO,MAAM,WAAW,YACvB,MAAM,WAAW,UAAa,OAAO,MAAM,WAAW,YACvD,CAAC,oBAAoB,IAAIN,MAAK,QAAQ,MAAM,WAAW,CAAC,KACxD,CAAC,mBAAmB,MAAM,OAAO,MAAM,aAAa,OAAO,KAC1D,MAAM,WAAW,UAAa,CAAC,mBAAmB,MAAM,QAAQ,MAAM,aAAa,QAAQ,GAC5F;AACA,YAAM,IAAI;AAAA,QACR,0CAA0C,OAAO;AAAA,MAEnD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAa,MAAM,aAAa,kBAAkB,OAAO,CAAC,MAAO;AACvE,QAAM,SAAmB,CAAC;AAC1B,MAAI,WAAW;AACb,eAAW,SAAS,YAAY,SAAS;AACvC,UAAI,MAAM,OAAQ,OAAMS,QAAO,MAAM,QAAQ,MAAM;AACnD,YAAMA,QAAO,MAAM,OAAO,MAAM;AAAA,IAClC;AAAA,EACF,OAAO;AACL,eAAW,SAAS,CAAC,GAAG,YAAY,OAAO,EAAE,QAAQ,GAAG;AACtD,YAAM,SAAS,MAAM,SAAS,MAAM,aAAa,MAAM,MAAM,IAAI;AACjE,YAAM,cAAc,MAAM,aAAa,MAAM,WAAW;AACxD,UAAI,QAAQ;AACV,YAAI,eAAe,OAAO,WAAW,MAAM,MAAM,QAAQ;AACvD,iBAAO;AAAA,YACL,oDAAoD,MAAM,WAAW,8BACvC,MAAM,MAAM;AAAA,UAC5C;AACA;AAAA,QACF;AACA,cAAMA,QAAO,MAAM,aAAa,MAAM;AACtC,YAAI;AACF,gBAAMJ,QAAO,MAAM,QAAS,MAAM,WAAW;AAAA,QAC/C,SAAS,OAAO;AACd,iBAAO;AAAA,YACL,qBAAqB,MAAM,WAAW,8BACjC,MAAM,MAAM,KAAK,QAAQ,KAAK,CAAC;AAAA,UACtC;AAAA,QACF;AAAA,MACF,WAAW,eAAe,OAAO,WAAW,MAAM,MAAM,QAAQ;AAC9D,cAAMI,QAAO,MAAM,aAAa,MAAM;AAAA,MACxC;AACA,YAAMA,QAAO,MAAM,OAAO,MAAM;AAAA,IAClC;AAAA,EACF;AAEA,MAAI,OAAO,QAAQ;AACjB,UAAM,IAAI;AAAA,MACR,sEAAsE,OAAO,OAC3E,OAAO,KAAK,IAAI;AAAA,IACpB;AAAA,EACF;AACA,QAAM,uBAAuB,OAAO;AACtC;AAGO,SAAS,6BACd,cACA,SACA,YACwB;AACxB,QAAM,OAAOT,MAAK,QAAQA,MAAK,QAAQ,YAAY,CAAC;AACpD,QAAM,UAAU,WAAW,QAAQ,IAAI,CAAC,YAAY;AAAA,IAClD,GAAG;AAAA,IACH,MAAM,iBAAiB,MAAM,OAAO,IAAI;AAAA,EAC1C,EAAE;AACF,QAAM,aAAa;AAAA,IACjB,MAAM,WAAW;AAAA,IACjB;AAAA,IACA,SAASQ,WAAU,WAAW,OAAO;AAAA,EACvC;AACA,QAAM,kBAAkB,QAAQ,IAAI,CAAC,YAAY;AAAA,IAC/C,MAAM,iBAAiB,MAAM,OAAO,IAAI;AAAA,IACxC,QAAQ,OAAO,OAAO,IAAI;AAAA,EAC5B,EAAE;AACF,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,GAAG;AAAA,IACH,aAAa,YAAY,EAAE,GAAG,YAAY,SAAS,gBAAgB,CAAC;AAAA,IACpE,SAAS;AAAA,EACX;AACF;AAGO,SAAS,qBACd,cACA,SACA,YACgB;AAChB,QAAM,WAAW,6BAA6B,cAAc,SAAS,UAAU;AAC/E,SAAO;AAAA,IACL,GAAG;AAAA,IACH,EAAE,MAAM,cAAc,MAAM,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,KAAK;AAAA,EACvE;AACF;AAOA,eAAsB,2BACpB,cACA,SACA,YACA,UAAwC,CAAC,GACV;AAC/B,QAAM,mBAAmBR,MAAK,QAAQ,YAAY;AAClD,QAAM,eAAe,GAAG,gBAAgB;AACxC,QAAM,sBAAsB,oBAAI,IAAI;AAAA,IAClC;AAAA,IACA,GAAG,QAAQ,IAAI,CAAC,WAAWA,MAAK,QAAQ,OAAO,IAAI,CAAC;AAAA,EACtD,CAAC;AACD,QAAM,2BAA2B,cAAc,mBAAmB;AAClE,QAAM,wBAAwB,MAAM,aAAa,gBAAgB;AACjE,MAAI,WAA0C;AAE9C,MAAI,yBAAyB,CAAC,QAAQ,OAAO;AAC3C,QAAI;AACF,iBAAW,sBAAsB,kBAAkB,sBAAsB,SAAS,MAAM,CAAC;AACzF,YAAM,QAAQ,SAAS,gBAAgB,YAAY,QAAQ;AAC3D,UAAI,CAAC,MAAO,OAAM,IAAI,MAAM,0CAA0C;AAAA,IACxE,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,8DAA8D,gBAAgB,KACzE,QAAQ,KAAK,CAAC;AAAA,QAEnB,EAAE,OAAO,MAAM;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,OAAO;AAClB,UAAM,OAAOA,MAAK,QAAQ,gBAAgB;AAC1C,UAAM,WAAW,IAAI;AAAA,MACnB,UAAU,QAAQ,IAAI,CAAC,WAAW,CAACA,MAAK,QAAQ,MAAM,OAAO,IAAI,GAAG,OAAO,MAAM,CAAC,KAAK,CAAC;AAAA,IAC1F;AACA,UAAM,YAAsB,CAAC;AAC7B,eAAW,UAAU,SAAS;AAC5B,YAAM,cAAcA,MAAK,QAAQ,OAAO,IAAI;AAC5C,YAAM,UAAU,MAAM,aAAa,WAAW;AAC9C,UAAI,CAAC,WAAW,OAAO,OAAO,MAAM,OAAO,OAAO,IAAI,EAAG;AACzD,YAAM,WAAW,SAAS,IAAI,WAAW;AACzC,UAAI,CAAC,YAAY,OAAO,OAAO,MAAM,SAAU,WAAU,KAAK,WAAW;AAAA,IAC3E;AACA,QAAI,UAAU,QAAQ;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,IACE,UAAU,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,EAAE,KAAK,IAAI,IAC9C;AAAA;AAAA,MAEJ;AAAA,IACF;AAAA,EACF;AAEA,QAAM,EAAE,OAAO,QAAQ,GAAG,cAAc,IAAI;AAC5C,SAAO;AAAA,IACL,qBAAqB,kBAAkB,SAAS,UAAU;AAAA,IAC1D,EAAE,GAAG,eAAe,aAAa;AAAA,EACnC;AACF;AAGA,eAAsB,qBAAqB,cAAqD;AAC9F,QAAM,WAAWA,MAAK,QAAQ,YAAY;AAC1C,QAAM,MAAM,MAAM,2BAA2B,QAAQ;AAErD,QAAM,OAAOA,MAAK,QAAQ,QAAQ;AAClC,QAAM,iBAA2B,CAAC;AAClC,QAAM,iBAA2B,CAAC;AAClC,aAAW,UAAU,IAAI,SAAS;AAChC,QAAI,SAAwB;AAC5B,QAAI;AACF,eAAS,OAAO,MAAMI,UAASJ,MAAK,QAAQ,MAAM,OAAO,IAAI,CAAC,CAAC;AAAA,IACjE,SAAS,OAAO;AACd,UAAI,CAAC,OAAO,OAAO,QAAQ,EAAG,OAAM;AAAA,IACtC;AACA,QAAI,WAAW,OAAO,OAAQ,gBAAe,KAAK,OAAO,EAAE;AAAA,EAC7D;AACA,aAAW,UAAU,IAAI,SAAS;AAChC,QAAI;AACF,UAAI,OAAO,MAAMI,UAASJ,MAAK,QAAQ,MAAM,OAAO,IAAI,CAAC,CAAC,MAAM,OAAO,QAAQ;AAC7E,uBAAe,KAAK,OAAO,IAAI;AAAA,MACjC;AAAA,IACF,SAAS,OAAO;AACd,UAAI,CAAC,OAAO,OAAO,QAAQ,EAAG,OAAM;AACpC,qBAAe,KAAK,OAAO,IAAI;AAAA,IACjC;AAAA,EACF;AAEA,QAAM,mBAAmB,IAAI,gBAAgB,YAAY;AAAA,IACvD,MAAM,IAAI;AAAA,IACV,SAAS,IAAI;AAAA,IACb,SAAS,IAAI;AAAA,IACb,SAAS,IAAI;AAAA,EACf,CAAC;AACD,SAAO;AAAA,IACL,SAAS,oBAAoB,CAAC,eAAe,UAAU,CAAC,eAAe;AAAA,IACvE;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,OAAO,OAAgB,MAAuB;AACrD,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,SAAS,MAAM,SAAS;AAC1F;AAEA,eAAeS,QAAO,MAAc,QAAkC;AACpE,MAAI;AACF,UAAMH,IAAG,MAAM,EAAE,OAAO,KAAK,CAAC;AAAA,EAChC,SAAS,OAAO;AACd,YAAQ,KAAK,oBAAoB,IAAI,KAAK,QAAQ,KAAK,CAAC,EAAE;AAAA,EAC5D;AACF;AAEA,eAAe,SAAS,UAAiD;AACvE,QAAM,SAAmB,CAAC;AAG1B,aAAW,YAAY,CAAC,GAAG,QAAQ,EAAE,QAAQ,GAAG;AAC9C,QAAI,SAAS,SAAU,OAAMG,QAAO,SAAS,aAAa,MAAM;AAAA,EAClE;AAEA,aAAW,YAAY,CAAC,GAAG,QAAQ,EAAE,QAAQ,GAAG;AAC9C,QAAI,CAAC,SAAS,UAAU,CAAC,SAAS,SAAU;AAC5C,QAAI;AACF,YAAMJ,QAAO,SAAS,QAAQ,SAAS,WAAW;AAClD,eAAS,WAAW;AAAA,IACtB,SAAS,OAAO;AACd,aAAO;AAAA,QACL,qBAAqB,SAAS,WAAW,8BACpC,SAAS,MAAM,KAAK,QAAQ,KAAK,CAAC;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAEA,aAAW,YAAY,UAAU;AAC/B,QAAI,SAAS,MAAO,OAAMI,QAAO,SAAS,OAAO,MAAM;AAAA,EACzD;AACA,SAAO;AACT;AAUA,eAAsB,oBACpB,OACA,UAAiC,CAAC,GACH;AAC/B,MAAI,CAAC,MAAM,OAAQ,OAAM,IAAI,MAAM,oDAAoD;AAEvF,QAAM,aAAa,MAAM,IAAI,CAAC,SAAS;AACrC,QAAI,CAAC,KAAK,KAAK,KAAK,EAAG,OAAM,IAAI,MAAM,iCAAiC;AACxE,WAAO,EAAE,aAAaT,MAAK,QAAQ,KAAK,IAAI,GAAG,MAAM,OAAO,KAAK,KAAK,IAAI,EAAE;AAAA,EAC9E,CAAC;AACD,QAAM,eAAe,oBAAI,IAAY;AACrC,aAAW,YAAY,YAAY;AACjC,QAAI,aAAa,IAAI,SAAS,WAAW,GAAG;AAC1C,YAAM,IAAI,MAAM,mDAAmD,SAAS,WAAW,EAAE;AAAA,IAC3F;AACA,iBAAa,IAAI,SAAS,WAAW;AAAA,EACvC;AACA,MAAI,QAAQ,cAAc;AACxB,UAAM,2BAA2B,QAAQ,cAAc,YAAY;AAAA,EACrE;AAEA,QAAM,UAA8B,CAAC;AACrC,QAAM,YAAsB,CAAC;AAC7B,aAAW,YAAY,YAAY;AACjC,QAAI;AACF,YAAM,UAAU,MAAMI,UAAS,SAAS,WAAW;AACnD,UAAI,QAAQ,OAAO,SAAS,IAAI,GAAG;AACjC,kBAAU,KAAK,SAAS,WAAW;AAAA,MACrC,OAAO;AACL,gBAAQ,KAAK,EAAE,GAAG,UAAU,SAAS,MAAM,UAAU,OAAO,UAAU,MAAM,CAAC;AAAA,MAC/E;AAAA,IACF,SAAS,OAAO;AACd,UAAI,CAAC,OAAO,OAAO,QAAQ,EAAG,OAAM;AACpC,cAAQ,KAAK,EAAE,GAAG,UAAU,SAAS,OAAO,UAAU,OAAO,UAAU,MAAM,CAAC;AAAA,IAChF;AAAA,EACF;AAEA,MAAI,CAAC,QAAQ,OAAQ,QAAO,EAAE,SAAS,CAAC,GAAG,UAAU;AAErD,QAAM,QAAQF,YAAW;AACzB,aAAW,CAAC,OAAO,QAAQ,KAAK,QAAQ,QAAQ,GAAG;AACjD,UAAM,WAAWF,MAAK,SAAS,SAAS,WAAW;AACnD,aAAS,QAAQA,MAAK;AAAA,MACpBA,MAAK,QAAQ,SAAS,WAAW;AAAA,MACjC,IAAI,QAAQ,oBAAoB,KAAK,IAAI,KAAK;AAAA,IAChD;AACA,QAAI,SAAS,SAAS;AACpB,eAAS,SAASA,MAAK;AAAA,QACrBA,MAAK,QAAQ,SAAS,WAAW;AAAA,QACjC,IAAI,QAAQ,qBAAqB,KAAK,IAAI,KAAK;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,QAAQ,eAAeA,MAAK,QAAQ,QAAQ,YAAY,IAAI;AAC5E,MAAI,SAAS;AACX,UAAMG,OAAMH,MAAK,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AACtD,UAAM,cAAmC;AAAA,MACvC,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,KAAK,QAAQ;AAAA,MACb,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,SAAS,QAAQ,IAAI,CAAC,cAAc;AAAA,QAClC,aAAa,SAAS;AAAA,QACtB,OAAO,SAAS;AAAA,QAChB,GAAI,SAAS,SAAS,EAAE,QAAQ,SAAS,OAAO,IAAI,CAAC;AAAA,QACrD,QAAQ,OAAO,SAAS,IAAI;AAAA,MAC9B,EAAE;AAAA,IACJ;AACA,QAAI;AACF,YAAMO,WAAU,SAAS,KAAK,UAAU,aAAa,MAAM,CAAC,IAAI,MAAM,EAAE,MAAM,KAAK,CAAC;AACpF,yBAAmB,IAAI,OAAO;AAAA,IAChC,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,mDAAmD,OAAO,KAAK,QAAQ,KAAK,CAAC;AAAA,QAC7E,EAAE,OAAO,MAAM;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,eAAW,CAAC,OAAO,QAAQ,KAAK,QAAQ,QAAQ,GAAG;AACjD,YAAMJ,OAAMH,MAAK,QAAQ,SAAS,WAAW,GAAG,EAAE,WAAW,KAAK,CAAC;AACnE,YAAM,QAAQ,cAAc,SAAS,aAAa,KAAK;AACvD,YAAMO,WAAU,SAAS,OAAQ,SAAS,MAAM,EAAE,MAAM,KAAK,CAAC;AAAA,IAChE;AAAA,EACF,SAAS,OAAO;AACd,UAAMG,iBAAgB,MAAM,SAAS,OAAO;AAC5C,QAAI,WAAW,CAACA,eAAc,OAAQ,OAAM,uBAAuB,OAAO;AAC1E,QAAI,QAAS,oBAAmB,OAAO,OAAO;AAC9C,UAAM,SAASA,eAAc,SAAS,yBAAyBA,eAAc,KAAK,IAAI,CAAC,KAAK;AAC5F,UAAM,IAAI,MAAM,oCAAoC,QAAQ,KAAK,CAAC,IAAI,MAAM,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,EAClG;AAEA,MAAI,gBAAgB;AACpB,MAAI;AAGF,eAAW,YAAY,SAAS;AAC9B,UAAI,CAAC,SAAS,QAAS;AACvB,YAAML,QAAO,SAAS,aAAa,SAAS,MAAO;AACnD,eAAS,WAAW;AAAA,IACtB;AAEA,eAAW,CAAC,OAAO,QAAQ,KAAK,QAAQ,QAAQ,GAAG;AACjD,YAAM,QAAQ,gBAAgB,SAAS,aAAa,KAAK;AACzD,YAAMA,QAAO,SAAS,OAAQ,SAAS,WAAW;AAClD,eAAS,QAAQ;AACjB,eAAS,WAAW;AAAA,IACtB;AACA,QAAI,SAAS;AACX,YAAME,WAAU,kBAAkB,OAAO,GAAG,GAAG,KAAK;AAAA,GAAM,EAAE,MAAM,KAAK,CAAC;AACxE,sBAAgB;AAChB,YAAM,QAAQ,cAAc;AAAA,IAC9B;AAAA,EACF,SAAS,OAAO;AACd,QAAI,eAAe;AACjB,UAAI,QAAS,oBAAmB,OAAO,OAAO;AAC9C,YAAM,IAAI;AAAA,QACR,qEAAqE,QAAQ,KAAK,CAAC,6CACtC,OAAO;AAAA,QACpD,EAAE,OAAO,MAAM;AAAA,MACjB;AAAA,IACF;AACA,UAAM,iBAAiB,MAAM,SAAS,OAAO;AAC7C,QAAI,WAAW,CAAC,eAAe,OAAQ,OAAM,uBAAuB,OAAO;AAC3E,QAAI,QAAS,oBAAmB,OAAO,OAAO;AAC9C,UAAM,SAAS,eAAe,SAC1B,8BAA8B,eAAe,KAAK,IAAI,CAAC,KACvD;AACJ,UAAM,IAAI,MAAM,sCAAsC,QAAQ,KAAK,CAAC,IAAI,MAAM,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,EACpG;AAEA,QAAM,gBAA0B,CAAC;AACjC,aAAW,YAAY,SAAS;AAC9B,QAAI,SAAS,OAAQ,OAAME,QAAO,SAAS,QAAQ,aAAa;AAAA,EAClE;AACA,MAAI,cAAc,QAAQ;AACxB,QAAI,QAAS,oBAAmB,OAAO,OAAO;AAC9C,UAAM,IAAI;AAAA,MACR,+DAA+D,cAAc,KAAK,IAAI,CAAC;AAAA,IACzF;AAAA,EACF;AACA,MAAI,SAAS;AACX,QAAI;AACF,YAAM,uBAAuB,OAAO;AAAA,IACtC,UAAE;AACA,yBAAmB,OAAO,OAAO;AAAA,IACnC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,QAAQ,IAAI,CAAC,aAAa,SAAS,WAAW;AAAA,IACvD;AAAA,EACF;AACF;;;AC5pBA,SAAS,YAAAE,iBAAgB;AACzB,SAAS,cAAAC,mBAAkB;AAC3B,OAAOC,WAAU;AAaV,SAAS,cACd,GACA,GACQ;AACR,QAAM,SAAS,EAAE,IAAI,EAAE,KAAK;AAC5B,QAAM,KAAK,EAAE,IAAI,EAAE;AACnB,QAAM,KAAK,EAAE,IAAI,EAAE;AACnB,QAAM,KAAK,EAAE,IAAI,EAAE;AACnB,SAAO,KAAK;AAAA,KACP,MAAM,SAAS,KAAK,KAAM,MAAO,IAAI,KAAK,MAAQ,MAAM,SAAS,KAAK,KAAM;AAAA,EACjF;AACF;AAUO,SAAS,gBAAgB,OAAuB,WAAmC;AACxF,MAAI,CAAC,MAAM,UAAU,CAAC,UAAU,OAAQ,QAAO;AAC/C,MAAI,QAAQ;AACZ,MAAI,SAAS;AACb,aAAW,SAAS,OAAO;AACzB,QAAI,UAAU;AACd,eAAW,OAAO,UAAW,WAAU,KAAK,IAAI,SAAS,cAAc,OAAO,GAAG,CAAC;AAClF,aAAS,UAAU,MAAM;AACzB,cAAU,MAAM;AAAA,EAClB;AACA,SAAO,WAAW,IAAI,IAAI,QAAQ;AACpC;AAGO,SAAS,cAAc,UAA4B,OAAO,IAAoB;AACnF,QAAM,SAAS,oBAAI,IAA0B;AAC7C,aAAW,WAAW,UAAU;AAC9B,eAAW,SAAS,SAAS;AAC3B,YAAM,MAAM,GAAG,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC;AAC5C,YAAM,WAAW,OAAO,IAAI,GAAG;AAC/B,UAAI,SAAU,UAAS,UAAU,MAAM;AAAA,UAClC,QAAO,IAAI,KAAK,EAAE,GAAG,MAAM,CAAC;AAAA,IACnC;AAAA,EACF;AACA,QAAM,SAAS,CAAC,GAAG,OAAO,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;AACrF,QAAM,MAAM,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC,KAAK;AACxD,SAAO,OAAO,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,QAAQ,EAAE,SAAS,IAAI,EAAE;AAC7D;AAqEA,eAAsB,WACpB,QACA,OACA,SACA,MACqB;AACrB,QAAM,QAAQ,OAAO,SAAS,OAAO,OAAO;AAC5C,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,kBAAkB,OAAO,GAAG;AAExD,QAAM,OAAO,MAAM,OAAO,CAAC,MAAM,EAAE,YAAY,OAAO;AACtD,QAAM,SAAuB,CAAC;AAC9B,QAAM,UAAoB,CAAC;AAC3B,QAAM,aAAuB,CAAC;AAE9B,aAAW,QAAQ,MAAM;AACvB,eAAW,UAAU,mBAAmB,MAAM,MAAM,OAAO,IAAI,GAAG;AAChE,UAAI,CAACC,YAAW,OAAO,YAAY,GAAG;AACpC,gBAAQ,KAAK,OAAO,EAAE;AACtB;AAAA,MACF;AACA,UAAI;AACF,cAAM,MAAM,UAAU,MAAMC,UAAS,OAAO,YAAY,CAAC;AACzD,cAAM,UAAU,eAAe,KAAK,EAAE;AACtC,eAAO,KAAK;AAAA,UACV,SAAS,KAAK;AAAA,UACd,GAAI,OAAO,OAAO,EAAE,YAAY,OAAO,KAAK,IAAI,CAAC;AAAA,UACjD,IAAI,OAAO;AAAA,UACX,MAAM,OAAO;AAAA,UACb,OAAO,IAAI;AAAA,UACX,QAAQ,IAAI;AAAA,UACZ,iBAAiB;AAAA;AAAA,UACjB,cAAc,kBAAkB,GAAG;AAAA,UACnC,YAAY,YAAY,GAAG;AAAA,UAC3B;AAAA,QACF,CAAC;AAAA,MACH,SAAS,KAAK;AACZ,mBAAW,KAAK,GAAG,OAAO,EAAE,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,YAA4B,CAAC;AACjC,MAAI,2BAA2B;AAC/B,QAAM,cAAgC,CAAC;AACvC,aAAW,OAAO,MAAM,aAAa;AACnC,UAAM,MAAMC,MAAK,QAAQ,OAAO,MAAM,IAAI,IAAI;AAC9C,QAAI,CAACF,YAAW,GAAG,EAAG;AACtB,QAAI;AACF,kBAAY,KAAK,eAAe,UAAU,MAAMC,UAAS,GAAG,CAAC,GAAG,EAAE,CAAC;AAAA,IACrE,QAAQ;AAAA,IAER;AAAA,EACF;AACA,MAAI,YAAY,QAAQ;AACtB,gBAAY,cAAc,WAAW;AACrC,+BAA2B;AAC3B,eAAW,SAAS,QAAQ;AAC1B,YAAM,kBAAkB,gBAAgB,MAAM,SAAS,SAAS;AAAA,IAClE;AAAA,EACF,OAAO;AAKL,gBAAY,cAAc,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC;AACtD,eAAW,SAAS,QAAQ;AAC1B,YAAM,SAAS,OAAO,OAAO,CAAC,MAAM,MAAM,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO;AACrE,YAAM,kBAAkB,OAAO,SAC3B,gBAAgB,MAAM,SAAS,cAAc,MAAM,CAAC,IACpD;AAAA,IACN;AAAA,EACF;AACA,SAAO,KAAK,CAAC,GAAG,MAAM,EAAE,kBAAkB,EAAE,eAAe;AAE3D,SAAO,EAAE,SAAS,0BAA0B,WAAW,QAAQ,SAAS,WAAW;AACrF;AAEA,SAAS,YAAY,KAAiC;AACpD,QAAM,OAAO,oBAAI,IAAY;AAC7B,WAAS,IAAI,GAAG,IAAI,IAAI,OAAO,QAAQ,KAAK,GAAG;AAC7C,QAAI,IAAI,OAAO,IAAI,CAAC,IAAK,IAAK;AAC9B,SAAK,IAAK,IAAI,OAAO,CAAC,KAAM,KAAO,IAAI,OAAO,IAAI,CAAC,KAAM,IAAK,IAAI,OAAO,IAAI,CAAC,CAAE;AAAA,EAClF;AACA,SAAO,KAAK;AACd;AAGO,SAAS,SAAS,OAAmB,QAAQ,KAAmB;AACrE,QAAM,IAAI,MAAM,OAAO;AACvB,MAAI,IAAI,EAAG,QAAO,CAAC;AACnB,QAAM,OAAO,MAAM,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,iBAAiB,CAAC,IAAI;AACvE,QAAM,WAAW,MAAM,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,EAAE,kBAAkB,SAAS,GAAG,CAAC,IAAI;AACzF,QAAM,KAAK,KAAK,KAAK,QAAQ;AAC7B,MAAI,OAAO,EAAG,QAAO,CAAC;AACtB,SAAO,MAAM,OAAO,OAAO,CAAC,MAAM,EAAE,kBAAkB,OAAO,QAAQ,EAAE;AACzE;AAGO,SAAS,cACd,OACA,aAA8B,CAAC,GACd;AACjB,QAAM,WAAW,EAAE,GAAG,YAAY,OAAO,WAAW,SAAS,IAAI;AACjE,QAAM,WAAW,SAAS,OAAO,SAAS,KAAK;AAC/C,QAAM,cAAc,IAAI,IAAI,SAAS,IAAI,CAAC,UAAU,MAAM,EAAE,CAAC;AAC7D,QAAM,aAA+B,CAAC;AAEtC,aAAW,SAAS,MAAM,QAAQ;AAChC,UAAM,UAAoB,CAAC;AAC3B,QAAI,YAAY,IAAI,MAAM,EAAE,GAAG;AAC7B,cAAQ,KAAK,0BAA0B,SAAS,KAAK,sBAAsB;AAAA,IAC7E;AACA,QAAI,SAAS,gBAAgB,UAAa,MAAM,kBAAkB,SAAS,aAAa;AACtF,cAAQ;AAAA,QACN,oBAAoB,MAAM,gBAAgB,QAAQ,CAAC,CAAC,YAAY,SAAS,WAAW;AAAA,MACtF;AAAA,IACF;AACA,QACE,SAAS,oBAAoB,UAC7B,MAAM,eAAe,SAAS,iBAC9B;AACA,cAAQ;AAAA,QACN,iBAAiB,MAAM,eAAe,KAAK,QAAQ,CAAC,CAAC,eAC/C,SAAS,kBAAkB,KAAK,QAAQ,CAAC,CAAC;AAAA,MAClD;AAAA,IACF;AACA,QAAI,SAAS,cAAc,UAAa,MAAM,aAAa,SAAS,WAAW;AAC7E,cAAQ,KAAK,eAAe,MAAM,UAAU,YAAY,SAAS,SAAS,EAAE;AAAA,IAC9E;AACA,QAAI,QAAQ,OAAQ,YAAW,KAAK,EAAE,IAAI,MAAM,IAAI,QAAQ,CAAC;AAAA,EAC/D;AAEA,SAAO;AAAA,IACL,MAAM,WAAW,WAAW,KAAK,MAAM,QAAQ,WAAW,KAAK,MAAM,WAAW,WAAW;AAAA,IAC3F,YAAY;AAAA,IACZ,UAAU,CAAC,GAAG,WAAW;AAAA,IACzB;AAAA,IACA,SAAS,CAAC,GAAG,MAAM,OAAO;AAAA,IAC1B,YAAY,CAAC,GAAG,MAAM,UAAU;AAAA,EAClC;AACF;AAEO,SAAS,IAAI,GAAgD;AAClE,SAAO,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AACjF;;;AF9PA,IAAM,gBAAgB,UAAU,QAAQ;AAExC,IAAM,2BAA2B;AACjC,IAAM,6BAA6B;AAE5B,IAAM,sBAAsB;AAC5B,IAAM,2BAA2B;AAoKxC,SAASE,SAAQ,OAAwB;AACvC,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAEO,SAAS,kBAAkB,QAAwB;AACxD,MAAI,CAAC,UAAU,KAAK,MAAM,EAAG,OAAM,IAAI,MAAM,qCAAqC;AAClF,SAAO,OAAO,QAAQ,WAAW,iBAAiB;AACpD;AAEA,SAAS,cAAc,WAAmC;AACxD,MAAI,UAAU,WAAW,OAAO,EAAG,QAAO;AAC1C,MACE,cAAc,gBACd,cAAc,YACb,UAAU,WAAW,WAAW,KAAK,UAAU,SAAS,GAAG,EAC5D,QAAO;AACT,SAAO;AACT;AAEA,IAAM,iBAAiD,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,EAAE;AAEpF,SAAS,kBAAkB,OAA+B;AACxD,MAAI,UAAU,SAAS,UAAU,YAAY,UAAU,OAAQ,QAAO;AACtE,QAAM,IAAI,MAAM,4BAA4B,KAAK,mCAAmC;AACtF;AAEA,SAAS,gBAAgB,MAAuB;AAC9C,QAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,MAAI,QAAQ,EAAG,OAAM,IAAI,MAAM,+CAA+C;AAC9E,MAAI,QAAQ;AACZ,MAAI,SAAS;AACb,MAAI,UAAU;AACd,WAAS,IAAI,OAAO,IAAI,KAAK,QAAQ,KAAK;AACxC,UAAM,OAAO,KAAK,CAAC;AACnB,QAAI,QAAQ;AACV,UAAI,QAAS,WAAU;AAAA,eACd,SAAS,KAAM,WAAU;AAAA,eACzB,SAAS,IAAK,UAAS;AAChC;AAAA,IACF;AACA,QAAI,SAAS,IAAK,UAAS;AAAA,aAClB,SAAS,IAAK;AAAA,aACd,SAAS,OAAO,EAAE,UAAU,GAAG;AACtC,UAAI;AACF,eAAO,KAAK,MAAM,KAAK,MAAM,OAAO,IAAI,CAAC,CAAC;AAAA,MAC5C,SAAS,OAAO;AACd,cAAM,IAAI,MAAM,mDAAmDA,SAAQ,KAAK,CAAC,EAAE;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AACA,QAAM,IAAI,MAAM,oDAAoD;AACtE;AAEA,IAAM,sBAAsB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,IAAI;AAEX,SAAS,eAAe,KAAsC;AAC5D,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,OAAM,IAAI,MAAM,+CAA+C;AACpG,QAAM,QAAQ;AACd,QAAM,QAAQ,OAAO,MAAM,MAAM;AACjC,QAAM,QAAQ,OAAO,MAAM,MAAM;AACjC,QAAM,SAAS,OAAO,MAAM,OAAO;AACnC,QAAM,SAAS,OAAO,MAAM,OAAO;AACnC,QAAM,UAAU,OAAO,MAAM,IAAI;AACjC,QAAM,OAAO,OAAO,MAAM,IAAI;AAC9B,QAAM,YAAY,MAAM;AACxB,MACE,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,KACpC,CAAC,OAAO,SAAS,KAAK,KAAK,SAAS,KACpC,CAAC,OAAO,SAAS,MAAM,KAAK,SAAS,KAAK,SAAS,SACnD,CAAC,OAAO,SAAS,MAAM,KAAK,SAAS,KAAK,SAAS,SACnD,CAAC,OAAO,UAAU,OAAO,KAAK,UAAU,KACxC,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAClC,OAAO,cAAc,YAAY,CAAC,WAClC;AACA,UAAM,IAAI,MAAM,4DAA4D;AAAA,EAC9E;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,cAAc,SAAS;AAAA,EACrC;AACF;AAEA,SAAS,iBAAiB,QAA2E;AACnG,QAAM,SAAS,oBAAI,IAA8D;AACjF,aAAW,SAAS,QAAQ;AAC1B,UAAM,MAAM,SAAS,KAAK;AAC1B,UAAMC,OAAM,IAAI,IAAI,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,GAAG,IAAI,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,GAAG,IAAI,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC;AAC/H,WAAO,IAAIA,MAAK,EAAE,KAAAA,MAAK,GAAG,IAAI,CAAC;AAAA,EACjC;AACA,MAAI,OAAO,OAAO,KAAK,OAAO,OAAO,KAAK;AACxC,UAAM,IAAI,MAAM,mEAA8D,OAAO,IAAI,GAAG;AAAA,EAC9F;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC;AAC5B;AAGO,SAAS,2BAA2B,QAA4B;AACrE,SAAO,iBAAiB,MAAM,EAAE,IAAI,CAAC,UAAU,MAAM,GAAG;AAC1D;AAGO,SAAS,kBAAkB,KAAiB,SAA+B;AAChF,QAAM,SAAS,iBAAiB,OAAO;AACvC,QAAM,SAAS,OAAO,KAAK,IAAI,MAAM;AACrC,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;AACzC,UAAM,QAAQ,OAAO,IAAI,CAAC;AAC1B,QAAI,UAAU,GAAG;AACf,aAAO,CAAC,IAAI;AACZ,aAAO,IAAI,CAAC,IAAI;AAChB,aAAO,IAAI,CAAC,IAAI;AAChB;AAAA,IACF;AACA,UAAM,QAAQ,EAAE,GAAG,OAAO,CAAC,GAAI,GAAG,OAAO,IAAI,CAAC,GAAI,GAAG,OAAO,IAAI,CAAC,EAAG;AACpE,QAAI,UAAU,OAAO,CAAC;AACtB,QAAI,WAAW,cAAc,OAAO,OAAO;AAC3C,aAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,YAAM,YAAY,OAAO,CAAC;AAC1B,YAAM,oBAAoB,cAAc,OAAO,SAAS;AACxD,UAAI,oBAAoB,UAAU;AAChC,kBAAU;AACV,mBAAW;AAAA,MACb;AAAA,IACF;AACA,WAAO,CAAC,IAAI,QAAQ;AACpB,WAAO,IAAI,CAAC,IAAI,QAAQ;AACxB,WAAO,IAAI,CAAC,IAAI,QAAQ;AAAA,EAC1B;AACA,SAAO,EAAE,OAAO,IAAI,OAAO,QAAQ,IAAI,QAAQ,OAAO;AACxD;AAEA,SAAS,WAAW,KAAyB;AAC3C,QAAM,SAAS,oBAAI,IAAY;AAC/B,WAAS,IAAI,GAAG,IAAI,IAAI,OAAO,QAAQ,KAAK,GAAG;AAC7C,QAAI,IAAI,OAAO,IAAI,CAAC,IAAK,IAAK;AAC9B,WAAO,IAAK,IAAI,OAAO,CAAC,KAAM,KAAO,IAAI,OAAO,IAAI,CAAC,KAAM,IAAK,IAAI,OAAO,IAAI,CAAC,CAAE;AAAA,EACpF;AACA,SAAO,OAAO;AAChB;AAEA,SAAS,wBAAwB,KAAiB,SAA2B;AAC3E,QAAM,UAAU,IAAI,IAAI,QAAQ,IAAI,CAACA,SAAQ;AAC3C,UAAM,QAAQ,SAASA,IAAG;AAC1B,WAAQ,MAAM,KAAK,KAAO,MAAM,KAAK,IAAK,MAAM;AAAA,EAClD,CAAC,CAAC;AACF,QAAM,aAAa,oBAAI,IAAY;AACnC,WAAS,IAAI,GAAG,IAAI,IAAI,OAAO,QAAQ,KAAK,GAAG;AAC7C,QAAI,IAAI,OAAO,IAAI,CAAC,MAAM,EAAG;AAC7B,UAAM,QAAS,IAAI,OAAO,CAAC,KAAM,KAAO,IAAI,OAAO,IAAI,CAAC,KAAM,IAAK,IAAI,OAAO,IAAI,CAAC;AACnF,QAAI,CAAC,QAAQ,IAAI,KAAK,EAAG,YAAW,IAAI,KAAK;AAAA,EAC/C;AACA,SAAO,WAAW;AACpB;AAEA,SAAS,gBACP,KACA,WACA,SACA,iBACA,mBACa;AACb,QAAM,SAAS,WAAW,GAAG;AAC7B,QAAM,mBAAmB,wBAAwB,KAAK,OAAO;AAC7D,QAAM,eAAe,kBAAkB,GAAG;AAC1C,QAAM,UAAoB,CAAC;AAC3B,MAAI,IAAI,UAAU,UAAU,WAAW,IAAI,WAAW,UAAU,MAAM;AACpE,YAAQ;AAAA,MACN,oBAAoB,IAAI,KAAK,IAAI,IAAI,MAAM,4BACtC,UAAU,OAAO,IAAI,UAAU,IAAI;AAAA,IAC1C;AAAA,EACF;AACA,MAAI,SAAS,QAAQ,OAAQ,SAAQ,KAAK,sBAAsB,MAAM,YAAY,QAAQ,MAAM,EAAE;AAClG,MAAI,iBAAkB,SAAQ,KAAK,GAAG,gBAAgB,iDAAiD;AACvG,MAAI,oBAAoB,UAAa,eAAe,iBAAiB;AACnE,YAAQ;AAAA,MACN,iBAAiB,eAAe,KAAK,QAAQ,CAAC,CAAC,eACzC,kBAAkB,KAAK,QAAQ,CAAC,CAAC;AAAA,IACzC;AAAA,EACF;AACA,MAAI,eAAe,UAAU,UAAU,IAAI,eAAe,iBAAiB,GAAG;AAC5E,YAAQ;AAAA,MACN,mBAAmB,UAAU,UAAU,sBAAsB,iBAAiB,KACxE,UAAU,SAAS;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AAAA,IACL,OAAO,IAAI;AAAA,IACX,QAAQ,IAAI;AAAA,IACZ,YAAY;AAAA,IACZ,mBAAmB,qBAAqB;AAAA,IACxC;AAAA,IACA,YAAY;AAAA,MACV,WAAW,QAAQ;AAAA,MACnB,iBAAiB,mBAAmB;AAAA,MACpC;AAAA,IACF;AAAA,IACA,MAAM,QAAQ,WAAW;AAAA,IACzB;AAAA,EACF;AACF;AAEA,SAAS,iBAAiB,OAAyC;AACjE,SAAO,UAAU,SAAS,UAAU,YAAY,UAAU;AAC5D;AAEA,SAAS,YAAY,OAAiD;AACpE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,YAAY;AAClB,SACE,OAAO,SAAS,UAAU,KAAK,KAAK,UAAU,QAAS,KACvD,OAAO,SAAS,UAAU,KAAK,KAAK,UAAU,QAAS,KACvD,OAAO,SAAS,UAAU,MAAM,KAAK,UAAU,UAAW,KACxD,UAAU,UAAW,UAAU,SACjC,OAAO,SAAS,UAAU,MAAM,KAAK,UAAU,UAAW,KACxD,UAAU,UAAW,UAAU,SACjC,OAAO,UAAU,UAAU,OAAO,KAAK,UAAU,UAAW,KAC5D,OAAO,UAAU,UAAU,IAAI,KAAK,UAAU,OAAQ,KACtD,OAAO,UAAU,cAAc,YAAY,CAAC,CAAC,UAAU,aACvD,iBAAiB,UAAU,UAAU;AAEzC;AAEA,SAAS,QAAQ,OAAsC;AACrD,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,QAAQ;AACd,SACE,OAAO,UAAU,MAAM,KAAK,KAAK,MAAM,QAAS,KAChD,OAAO,UAAU,MAAM,MAAM,KAAK,MAAM,SAAU,KAClD,OAAO,UAAU,MAAM,UAAU,KAAK,MAAM,cAAe,KAC3D,OAAO,MAAM,sBAAsB,aACnC,OAAO,SAAS,MAAM,YAAY,KAAK,MAAM,gBAAiB,KAAK,MAAM,gBAAiB,KAC1F,CAAC,CAAC,MAAM,cACR,OAAO,UAAU,MAAM,WAAW,SAAS,KAAK,MAAM,WAAW,YAAY,MAC5E,MAAM,WAAW,oBAAoB,QACnC,OAAO,SAAS,MAAM,WAAW,eAAe,KAC/C,MAAM,WAAW,mBAAmB,KAAK,MAAM,WAAW,mBAAmB,MACjF,iBAAiB,MAAM,WAAW,iBAAiB,KACnD,OAAO,MAAM,SAAS,aACtB,MAAM,QAAQ,MAAM,OAAO,KAAK,MAAM,QAAQ,MAAM,CAAC,WAAW,OAAO,WAAW,QAAQ;AAE9F;AAEA,SAAS,cAAc,OAAuE;AAC5F,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,WAAW;AACjB,SACE,OAAO,UAAU,SAAS,GAAG,KAAK,SAAS,OAAO,KAAK,SAAS,OAAO,MACvE,OAAO,UAAU,SAAS,KAAK,KAAK,SAAS,SAAS,KAAK,SAAS,SAAS,MAC7E,MAAM,QAAQ,SAAS,KAAK,KAAK,SAAS,MAAM,WAAW,SAAS,SACpE,IAAI,IAAI,SAAS,KAAK,EAAE,SAAS,SAAS,MAAM,UAChD,SAAS,MAAM,MAAM,CAAC,SAAS,OAAO,SAAS,YAAY,CAAC,CAAC,IAAI,KACjE,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,OAAO,WAAW,SAAS,SACtE,SAAS,OAAO;AAAA,IAAM,CAAC,OAAO,UAC5B,MAAM,SAAS,SAAS,MAAM,KAAK,KACnC,OAAO,UAAU,MAAM,WAAW,KAAK,MAAM,cAAc,KAC3D,OAAO,UAAU,MAAM,YAAY,KAAK,MAAM,eAAe,KAC7D,YAAY,MAAM,SAAS,KAAK,QAAQ,MAAM,KAAK;AAAA,EACrD;AAEJ;AAEA,SAAS,mBAAmB,UAAkC,QAAqC;AACjG,MAAI,SAAS,SAAS,SAAU,OAAM,IAAI,MAAM,GAAG,MAAM,wCAAwC;AACjG,QAAM,MAAM,SAAS;AACrB,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,OAAM,IAAI,MAAM,GAAG,MAAM,gCAAgC;AAC9F,QAAM,UAAU;AAChB,QAAM,OAAO,QAAQ;AACrB,QAAM,UAAU,QAAQ;AACxB,QAAM,QAAQ,QAAQ;AACtB,QAAM,SAAS,QAAQ;AACvB,MACE,QAAQ,WAAW,uBAAuB,QAAQ,YAAY,KAC9D,CAAC,QAAQ,KAAK,SAAS,qBAAqB,KAAK,QAAQ,uBACzD,OAAO,KAAK,aAAa,YAAY,CAAC,KAAK,YAC1C,KAAK,aAAa,mBAAmB,KAAK,aAAa,oBACtD,KAAK,aAAa,mBACpB,CAAC,iBAAiB,KAAK,UAAU,KAAK,OAAO,KAAK,cAAc,YAChE,CAAC,OAAO,SAAS,KAAK,KAAK,KAAK,CAAC,OAAO,SAAS,KAAK,KAAK,MACzD,KAAK,WAAW,UAAa,KAAK,WAAW,UAAa,QAAQ,aAAa,YAC9E,CAAC,OAAO,SAAS,KAAK,MAAM,KAAK,CAAC,OAAO,SAAS,KAAK,MAAM,MAChE,CAAC,OAAO,UAAU,KAAK,WAAW,KAAK,CAAC,OAAO,UAAU,KAAK,YAAY,KAC1E,CAAC,OAAO,UAAU,KAAK,WAAW,KAAK,CAAC,OAAO,UAAU,KAAK,YAAY,KAC1E,CAAC,WAAW,CAAC,MAAM,QAAQ,QAAQ,MAAM,KAAK,QAAQ,OAAO,SAAS,KACtE,CAAC,QAAQ,OAAO,MAAM,CAAC,UAAU,OAAO,UAAU,QAAQ,KAC1D,QAAQ,WAAW,UAAU,QAAQ,aAAa,aAClD,CAAC,QAAQ,KAAK,KACd,CAAC,UAAW,OAAO,WAAW,aAAa,OAAO,WAAW,cAC5D,QAAQ,aAAa,UAAa,CAAC,cAAc,QAAQ,QAAQ,GAClE;AACA,UAAM,IAAI,MAAM,GAAG,MAAM,gCAAgC;AAAA,EAC3D;AACA,SAAO;AACT;AAEA,SAAS,cAAc,MAAc,OAAuB;AAC1D,QAAM,OAAO,KAAK,KAAK,EAAE,QAAQ,oBAAoB,GAAG,EAAE,QAAQ,YAAY,EAAE;AAChF,SAAO,QAAQ,SAAS,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC;AACxD;AAGO,SAAS,uBAAuB,QAAgB,MAAc,OAAuB;AAC1F,MAAI,CAAC,UAAU,KAAK,MAAM,EAAG,OAAM,IAAI,MAAM,gDAAgD;AAC7F,SAAO,OAAO,QAAQ,WAAW,IAAI,cAAc,MAAM,KAAK,CAAC,MAAM;AACvE;AAEA,SAAS,cACP,OACA,MACS;AACT,QAAM,eAAe,CAAC,GAAW,GAAW,SAAiB;AAC3D,UAAM,WAAW,KAAK,IAAI,IAAI,CAAC,IAAI;AACnC,WAAO,KAAK,IAAI,UAAU,OAAO,QAAQ,KAAK;AAAA,EAChD;AACA,SACE,KAAK,UAAU,UAAU,MAAM,UAAU,SACzC,KAAK,UAAU,UAAU,MAAM,UAAU,SACzC,KAAK,UAAU,YAAY,MAAM,UAAU,WAC3C,KAAK,UAAU,SAAS,MAAM,UAAU,QACxC,aAAa,KAAK,UAAU,QAAQ,MAAM,UAAU,QAAQ,MAAM,UAAU,KAAK,KACjF,aAAa,KAAK,UAAU,QAAQ,MAAM,UAAU,QAAQ,MAAM,UAAU,KAAK,KACjF,KAAK,MAAM,UAAU,MAAM,MAAM,SACjC,KAAK,MAAM,WAAW,MAAM,MAAM,UAClC,KAAK,gBAAgB,MAAM,eAC3B,KAAK,iBAAiB,MAAM;AAEhC;AAGA,eAAsB,YAAY,SAA+C;AAC/E,QAAM,SAASC,OAAK,QAAQ,QAAQ,MAAM;AAC1C,QAAM,SAASA,OAAK,QAAQ,QAAQ,MAAM;AAC1C,MAAI,WAAW,OAAQ,OAAM,IAAI,MAAM,uDAAuD;AAC9F,QAAM,SAASA,OAAK,QAAQ,kBAAkB,MAAM,CAAC;AACrD,QAAM,UAAU,iBAAiB,QAAQ,OAAO,EAAE,IAAI,CAAC,UAAU,MAAM,GAAG;AAC1E,QAAM,oBAAoB,kBAAkB,QAAQ,qBAAqB,MAAM;AAC/E,MACE,QAAQ,oBAAoB,WAC3B,CAAC,OAAO,SAAS,QAAQ,eAAe,KAAK,QAAQ,kBAAkB,KAAK,QAAQ,kBAAkB,GACvG,OAAM,IAAI,MAAM,0CAA0C;AAE5D,MAAI;AACJ,MAAI;AACF,gBAAY,UAAU,MAAMC,UAAS,MAAM,CAAC;AAAA,EAC9C,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,iCAAiC,MAAM,KAAKH,SAAQ,KAAK,CAAC,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,EAChG;AAEA,QAAM,uBAAuB,QAAQ;AACrC,MAAI,CAAC,sBAAsB;AACzB,QACE,UAAU,QAAQ,4BAClB,UAAU,SAAS,0BACnB;AACA,YAAM,IAAI;AAAA,QACR,4DACK,wBAAwB,WAAW,UAAU,KAAK,IAAI,UAAU,MAAM;AAAA,MAC7E;AAAA,IACF;AACA,QAAI,UAAU,QAAQ,UAAU,SAAS,4BAA4B;AACnE,YAAM,IAAI;AAAA,QACR,mCAAmC,2BAA2B,eAAe,OAAO,CAAC,uBAC7D,UAAU,KAAK,IAAI,UAAU,MAAM;AAAA,MAC7D;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,QAAQE,OAAK,KAAK,OAAO,GAAG,mBAAmB,CAAC;AACnE,QAAM,YAAYA,OAAK,KAAK,MAAM,YAAY;AAC9C,QAAM,eAAe,wBAAwB,QAAQ,eACnD,QAAQ,IAAI,gCAAgC;AAC9C,QAAM,OAAO,uBACT,CAAC,GAAI,QAAQ,mBAAmB,CAAC,GAAI,QAAQ,aAAa,SAAS,IACnE,CAAC,MAAM,qBAAqB,QAAQ,SAAS;AACjD,MAAI;AACF,QAAI;AACJ,QAAI;AACF,YAAM,SAAS,MAAM,cAAc,cAAc,MAAM;AAAA,QACrD,UAAU;AAAA,QACV,WAAW,IAAI,OAAO;AAAA,QACtB,SAAS,KAAK,KAAK;AAAA,MACrB,CAAC;AACD,eAAS,OAAO;AAAA,IAClB,SAAS,OAAO;AACd,YAAM,OAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,QAClE,OAAO,MAAM,IAAI,IACjB;AACJ,YAAM,UACJ,0CAA0C,mBAAmB,OAC1D,QAAQ,iBAAiB,wBAAwB;AACtD,YAAM,IAAI;AAAA,QACR,SAAS,WACL,sCAAsC,YAAY,KAAK,OAAO,KAC9D,2BAA2BF,SAAQ,KAAK,CAAC,KAAK,OAAO;AAAA,QACzD,EAAE,OAAO,MAAM;AAAA,MACjB;AAAA,IACF;AACA,UAAM,YAAY,eAAe,gBAAgB,MAAM,CAAC;AACxD,UAAM,SAAS,UAAU,MAAMG,UAAS,SAAS,CAAC;AAClD,UAAM,YAAY,kBAAkB,QAAQ,OAAO;AACnD,UAAM,MAAM,cAAc,UAAU,OAAO,UAAU,QAAQ,UAAU,MAAM;AAC7E,UAAM,QAAQ;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,IACF;AACA,QAAI,CAAC,MAAM,MAAM;AACf,YAAM,IAAI,MAAM,wCAAwC,MAAM,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,IACpF;AAEA,UAAM,mBAAmC;AAAA,MACvC,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,QAAQ,MAAM,WAAW,MAAM;AAAA,MAC/B,UAAU;AAAA,IACZ;AACA,UAAM,gBAAqC;AAAA,MACzC,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,QACV,MAAM;AAAA,QACN,KAAK;AAAA,QACL,UAAU,QAAQ,iBAAiB;AAAA,QACnC,UAAU,uBAAuB,kBAAkB;AAAA,QACnD,YAAY,UAAU;AAAA,QACtB,WAAW,UAAU;AAAA,QACrB,OAAO,UAAU;AAAA,QACjB,OAAO,UAAU;AAAA,QACjB,QAAQ,UAAU;AAAA,QAClB,QAAQ,UAAU;AAAA,QAClB,aAAa,UAAU;AAAA,QACvB,cAAc,UAAU;AAAA,QACxB,aAAa,UAAU;AAAA,QACvB,cAAc,UAAU;AAAA,MAC1B;AAAA,MACA,SAAS,EAAE,QAAQ,SAAS,QAAQ,QAAQ,UAAU,UAAU;AAAA,MAChE;AAAA,MACA,QAAQ,EAAE,QAAQ,UAAU;AAAA,IAC9B;AACA,UAAM;AAAA,MACJ;AAAA,MACA,CAAC,EAAE,MAAM,QAAQ,MAAM,IAAI,CAAC;AAAA,MAC5B,EAAE,MAAM,UAAU,SAAS,CAAC,gBAAgB,GAAG,SAAS,cAAc;AAAA,MACtE,EAAE,OAAO,QAAQ,MAAM;AAAA,IACzB;AACA,WAAO,EAAE,QAAQ,QAAQ,QAAQ,WAAW,SAAS,MAAM;AAAA,EAC7D,UAAE;AACA,UAAMC,IAAG,MAAM,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACjD;AACF;AAGA,eAAsB,eAAe,SAA+D;AAClG,MAAI,CAAC,OAAO,UAAU,QAAQ,GAAG,KAAK,QAAQ,MAAM,KAAK,QAAQ,MAAM,IAAI;AACzE,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACtE;AACA,MAAI,QAAQ,QAAQ,SAAS,KAAK,QAAQ,QAAQ,SAAS,IAAI;AAC7D,UAAM,IAAI,MAAM,2DAAsD,QAAQ,QAAQ,MAAM,GAAG;AAAA,EACjG;AACA,QAAM,QAAQ,QAAQ,QAAQ,IAAI,CAAC,WAAW,OAAO,IAAI;AACzD,MAAI,MAAM,KAAK,CAAC,SAAS,CAAC,KAAK,KAAK,CAAC,KAAK,IAAI,IAAI,KAAK,EAAE,SAAS,MAAM,QAAQ;AAC9E,UAAM,IAAI,MAAM,+CAA+C;AAAA,EACjE;AAEA,QAAM,SAASF,OAAK,QAAQ,QAAQ,MAAM;AAC1C,QAAM,SAASA,OAAK,QAAQ,kBAAkB,MAAM,CAAC;AACrD,QAAM,UAAU,2BAA2B,QAAQ,OAAO;AAC1D,QAAM,eAAe,QAAQ,QAAQ,IAAI,CAAC,QAAQ,UAChD,uBAAuB,QAAQ,OAAO,MAAM,KAAK,CAAC;AACpD,MAAI,IAAI,IAAI,YAAY,EAAE,SAAS,aAAa,QAAQ;AACtD,UAAM,IAAI,MAAM,wDAAwD;AAAA,EAC1E;AACA,QAAM,YAAY,IAAI,IAAI,QAAQ,QAAQ,IAAI,CAAC,WAAWA,OAAK,QAAQ,OAAO,IAAI,CAAC,CAAC;AACpF,MAAI,aAAa,KAAK,CAAC,SAAS,UAAU,IAAI,IAAI,CAAC,GAAG;AACpD,UAAM,IAAI,MAAM,mEAAmE;AAAA,EACrF;AACA,QAAM,OAAO,MAAM,QAAQA,OAAK,KAAK,OAAO,GAAG,0BAA0B,CAAC;AAC1E,MAAI;AACF,UAAM,SAAyC,CAAC;AAChD,UAAM,UAAiD,CAAC;AACxD,UAAM,oBAAsC,CAAC;AAC7C,UAAM,cAAwB,CAAC;AAC/B,QAAI,eAA2C;AAE/C,eAAW,CAAC,OAAO,WAAW,KAAK,QAAQ,QAAQ,QAAQ,GAAG;AAC5D,YAAM,SAASA,OAAK,QAAQ,YAAY,IAAI;AAC5C,YAAM,kBAAkBA,OAAK,KAAK,MAAM,GAAG,OAAO,KAAK,EAAE,SAAS,GAAG,GAAG,CAAC,MAAM;AAC/E,YAAM,UAAU,MAAM,YAAY;AAAA,QAChC;AAAA,QACA,QAAQ;AAAA,QACR;AAAA,QACA,aAAa,QAAQ;AAAA,QACrB,cAAc,QAAQ;AAAA,QACtB,iBAAiB,QAAQ;AAAA,QACzB,eAAe,QAAQ;AAAA,QACvB,mBAAmB,QAAQ;AAAA,QAC3B,iBAAiB,QAAQ;AAAA,QACzB,OAAO;AAAA,MACT,CAAC;AACD,YAAM,kBAAkB,MAAM,2BAA2B,QAAQ,MAAM;AACvE,YAAM,eAAe,mBAAmB,iBAAiB,QAAQ,MAAM;AACvE,uBAAiB;AACjB,aAAO,KAAK;AAAA,QACV,MAAM,YAAY;AAAA,QAClB,aAAa,aAAa,WAAW;AAAA,QACrC,cAAc,aAAa,WAAW;AAAA,QACtC,WAAW,QAAQ;AAAA,QACnB,OAAO,QAAQ;AAAA,MACjB,CAAC;AACD,kBAAY,KAAK,MAAM;AACvB,wBAAkB,KAAK;AAAA,QACrB,IAAI,YAAY;AAAA,QAChB,MAAM;AAAA,QACN,QAAQ,MAAM,WAAW,MAAM;AAAA,QAC/B,UAAU;AAAA,MACZ,CAAC;AACD,cAAQ,KAAK;AAAA,QACX,MAAM,aAAa,KAAK;AAAA,QACxB,MAAM,MAAMC,UAAS,eAAe;AAAA,MACtC,CAAC;AAAA,IACH;AAEA,UAAM,QAAQ,OAAO,CAAC;AACtB,UAAM,WAAW,OAAO,KAAK,CAAC,UAAU,CAAC,cAAc,OAAO,KAAK,CAAC;AACpE,QAAI,UAAU;AACZ,YAAM,IAAI;AAAA,QACR,mCAAmC,MAAM,IAAI,aACxC,MAAM,UAAU,OAAO,IAAI,MAAM,UAAU,IAAI,OAC/C,MAAM,UAAU,KAAK,IAAI,MAAM,UAAU,KAAK,WAC9C,MAAM,UAAU,MAAM,IAAI,MAAM,UAAU,MAAM,SAAS,SAAS,IAAI,aACtE,SAAS,UAAU,OAAO,IAAI,SAAS,UAAU,IAAI,OACrD,SAAS,UAAU,KAAK,IAAI,SAAS,UAAU,KAAK,WACpD,SAAS,UAAU,MAAM,IAAI,SAAS,UAAU,MAAM;AAAA,MAC7D;AAAA,IACF;AAEA,UAAM,UAAU,OAAO;AAAA,MAAQ,CAAC,UAC9B,MAAM,MAAM,QAAQ,IAAI,CAAC,WAAW,GAAG,MAAM,IAAI,KAAK,MAAM,EAAE;AAAA,IAChE;AACA,UAAM,QAAqB;AAAA,MACzB,OAAO,MAAM,MAAM;AAAA,MACnB,QAAQ,MAAM,MAAM;AAAA,MACpB,YAAY,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,MAAM,UAAU,CAAC;AAAA,MACrE,mBAAmB,OAAO,MAAM,CAAC,UAAU,MAAM,MAAM,iBAAiB;AAAA,MACxE,cAAc,KAAK,IAAI,GAAG,OAAO,IAAI,CAAC,UAAU,MAAM,MAAM,YAAY,CAAC;AAAA,MACzE,YAAY,MAAM,MAAM;AAAA,MACxB,MAAM,OAAO,MAAM,CAAC,UAAU,MAAM,MAAM,IAAI,KAAK,QAAQ,WAAW;AAAA,MACtE;AAAA,IACF;AACA,UAAM,cAAc;AACpB,UAAM,gBAAqC;AAAA,MACzC,GAAG;AAAA,MACH;AAAA,MACA,QAAQ,EAAE,QAAQ,UAAU;AAAA,MAC5B,UAAU;AAAA,QACR,KAAK,QAAQ;AAAA,QACb,OAAO,OAAO;AAAA,QACd;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,EAAE,MAAM,UAAU,SAAS,mBAAmB,SAAS,cAAc;AAAA,MACrE,EAAE,OAAO,QAAQ,MAAM;AAAA,IACzB;AACA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,SAAS,QAAQ,IAAI,CAAC,SAASD,OAAK,QAAQ,KAAK,IAAI,CAAC;AAAA,MACtD;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,UAAE;AACA,UAAME,IAAG,MAAM,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACjD;AACF;AAGA,eAAsB,mBAAmB,YAA2C;AAClF,QAAM,SAASF,OAAK,QAAQ,UAAU;AACtC,QAAM,WAAW,MAAM,2BAA2B,MAAM;AACxD,QAAM,UAAU,mBAAmB,UAAU,MAAM;AACnD,QAAM,eAAe,MAAM,qBAAqB,MAAM;AACtD,QAAM,UAAU,SAAS,QAAQ,IAAI,CAACG,YAAWH,OAAK,QAAQA,OAAK,QAAQ,MAAM,GAAGG,QAAO,IAAI,CAAC;AAChG,QAAM,UAAU,SAAS,QAAQ,IAAI,CAACC,YAAWJ,OAAK,QAAQA,OAAK,QAAQ,MAAM,GAAGI,QAAO,IAAI,CAAC;AAChG,QAAM,SAAS,QAAQ,CAAC,KAAK;AAC7B,QAAM,SAAS,QAAQ,CAAC,KAAK;AAC7B,QAAM,gBAAgB,QAAQ,UAAU,SAAS;AACjD,QAAM,UAAoB,CAAC;AAC3B,MAAI,CAAC,aAAa,iBAAkB,SAAQ,KAAK,oCAAoC;AACrF,aAAWD,WAAU,aAAa,eAAgB,SAAQ,KAAK,mBAAmBA,OAAM,EAAE;AAC1F,aAAW,WAAW,aAAa,eAAgB,SAAQ,KAAK,mBAAmB,OAAO,EAAE;AAC5F,MAAI,SAAS,QAAQ,WAAW,eAAe;AAC7C,YAAQ,KAAK,uCAAuC,aAAa,YAAY;AAAA,EAC/E;AACA,MAAI,SAAS,QAAQ,WAAW,eAAe;AAC7C,YAAQ,KAAK,uCAAuC,aAAa,YAAY;AAAA,EAC/E;AACA,MAAI,CAAC,QAAQ,MAAM,KAAM,SAAQ,KAAK,GAAG,QAAQ,MAAM,QAAQ,IAAI,CAAC,WAAW,UAAU,MAAM,EAAE,CAAC;AAClG,MAAI,QAAQ,OAAO,WAAW,WAAY,SAAQ,KAAK,+BAA4B;AACnF,SAAO;AAAA,IACL,MAAM,QAAQ,WAAW;AAAA,IACzB,SAAS,aAAa;AAAA,IACtB,UAAU,QAAQ,OAAO,WAAW;AAAA,IACpC,WAAW,QAAQ,MAAM;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGA,eAAsB,qBACpB,YACA,UACuB;AACvB,QAAM,WAAW,SAAS,SAAS,KAAK;AACxC,MAAI,CAAC,SAAU,OAAM,IAAI,MAAM,oCAAoC;AACnE,QAAM,SAASH,OAAK,QAAQ,UAAU;AACtC,QAAM,WAAW,MAAM,2BAA2B,MAAM;AACxD,QAAM,UAAU,mBAAmB,UAAU,MAAM;AACnD,QAAM,eAAe,MAAM,qBAAqB,MAAM;AACtD,MAAI,CAAC,aAAa,SAAS;AACzB,UAAM,UAAU;AAAA,MACd,GAAG,aAAa,eAAe,IAAI,CAAC,WAAW,UAAU,MAAM,EAAE;AAAA,MACjE,GAAG,aAAa,eAAe,IAAI,CAAC,WAAW,UAAU,MAAM,EAAE;AAAA,MACjE,GAAI,CAAC,aAAa,mBAAmB,CAAC,kBAAkB,IAAI,CAAC;AAAA,IAC/D;AACA,UAAM,IAAI,MAAM,+CAA+C,QAAQ,KAAK,IAAI,CAAC,qBAAqB;AAAA,EACxG;AACA,MAAI,CAAC,QAAQ,MAAM,MAAM;AACvB,UAAM,IAAI,MAAM,0CAA0C,QAAQ,MAAM,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,EAC9F;AACA,QAAM,gBAAgB,QAAQ,UAAU,SAAS;AACjD,MAAI,SAAS,QAAQ,WAAW,iBAAiB,SAAS,QAAQ,WAAW,eAAe;AAC1F,UAAM,IAAI;AAAA,MACR,4CAA4C,aAAa;AAAA,IAC3D;AAAA,EACF;AAEA,QAAM,OAAOA,OAAK,QAAQ,MAAM;AAChC,QAAM,UAAU,MAAM,QAAQ,IAAI,SAAS,QAAQ,IAAI,OAAO,UAAU;AACtE,UAAM,aAAaA,OAAK,QAAQ,MAAM,MAAM,IAAI;AAChD,WAAO,EAAE,MAAM,YAAY,MAAM,MAAMC,UAAS,UAAU,EAAE;AAAA,EAC9D,CAAC,CAAC;AACF,QAAM,UAA4B,SAAS,QAAQ,IAAI,CAAC,YAAY;AAAA,IAClE,GAAG;AAAA,IACH,MAAMD,OAAK,QAAQ,MAAM,OAAO,IAAI;AAAA,EACtC,EAAE;AACF,QAAM,WAAgC;AAAA,IACpC,GAAG;AAAA,IACH,QAAQ;AAAA,MACN,QAAQ;AAAA,MACR;AAAA,MACA,aAAa,SAAS,cAAc,oBAAI,KAAK,GAAG,YAAY;AAAA,MAC5D,WAAW;AAAA,QACT,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,iBAAiB;AAAA,QACjB,mBAAmB;AAAA,QACnB,eAAe;AAAA,MACjB;AAAA,MACA,GAAI,SAAS,MAAM,KAAK,IAAI,EAAE,MAAM,SAAS,KAAK,KAAK,EAAE,IAAI,CAAC;AAAA,IAChE;AAAA,EACF;AACA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,EAAE,MAAM,UAAU,SAAS,SAAS,SAAS;AAAA,EAC/C;AACA,SAAO,mBAAmB,MAAM;AAClC;;;ADj0BA,eAAe,cAAc,MAAoB,MAAoC;AACnF,MAAI,KAAK,QAAQ;AACf,QAAI,KAAK,cAAc,UAAU;AAC/B,aAAO,EAAE,OAAO,MAAM,QAAQ,iEAAiE;AAAA,IACjG;AACA,UAAM,SAASK,OAAK,QAAQ,KAAK,MAAM,KAAK,MAAM;AAClD,WAAOC,YAAW,MAAM,IACpB,EAAE,OAAO,CAAC,EAAE,MAAM,UAAU,MAAM,OAAO,CAAC,EAAE,IAC5C,EAAE,OAAO,MAAM,QAAQ,+BAA+B,KAAK,MAAM,GAAG;AAAA,EAC1E;AAEA,QAAM,QAAQ,KAAK,QAAQ,QAAQ,KAAK,SAAS,KAAK,OAAO,CAAC;AAC9D,MAAI,CAAC,MAAO,QAAO,EAAE,OAAO,MAAM,QAAQ,6CAA6C;AACvF,MAAI,MAAM,aAAa,KAAK,UAAU;AACpC,WAAO,EAAE,OAAO,MAAM,QAAQ,iEAAiE;AAAA,EACjG;AACA,MAAI,MAAM,WAAW,cAAc;AACjC,WAAO,EAAE,OAAO,MAAM,QAAQ,0BAA0B,MAAM,MAAM,mBAAmB;AAAA,EACzF;AACA,QAAM,WAAW,KAAK,cAAc;AACpC,MAAK,CAAC,YAAY,MAAM,QAAQ,WAAW,KAAO,YAAY,MAAM,QAAQ,SAAS,GAAI;AACvF,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,WACJ,uEAAuE,MAAM,QAAQ,MAAM,KAC3F,2DAA2D,MAAM,QAAQ,MAAM;AAAA,IACrF;AAAA,EACF;AACA,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,QAA+C,CAAC;AACtD,aAAW,CAAC,OAAO,MAAM,KAAK,MAAM,QAAQ,QAAQ,GAAG;AACrD,QAAI,OAAO,aAAa,OAAO,cAAc,UAAU,KAAK;AAC1D,aAAO,EAAE,OAAO,MAAM,QAAQ,qDAAqD,OAAO,SAAS,GAAG;AAAA,IACxG;AACA,UAAM,OAAO,WAAW,OAAO,OAAO;AACtC,QAAI,aAAa,CAAC,QAAQ,MAAM,IAAI,IAAI,IAAI;AAC1C,aAAO,EAAE,OAAO,MAAM,QAAQ,oEAAoE;AAAA,IACpG;AACA,QAAI,KAAM,OAAM,IAAI,IAAI;AACxB,UAAM,SAAS,uBAAuB,OAAO,MAAM,KAAK;AACxD,QAAI,CAACA,YAAW,MAAM,EAAG,QAAO,EAAE,OAAO,MAAM,QAAQ,mCAAmC,MAAM,GAAG;AACnG,QAAK,MAAM,WAAW,MAAM,MAAO,OAAO,QAAQ;AAChD,aAAO,EAAE,OAAO,MAAM,QAAQ,kDAAkD;AAAA,IAClF;AACA,UAAM,KAAK,EAAE,MAAa,MAAM,OAAO,CAAC;AAAA,EAC1C;AACA,SAAO,EAAE,MAAM;AACjB;AAGA,eAAsB,sBACpB,MACA,MAC0C;AAC1C,MAAI,CAAC,KAAK,QAAS,QAAO;AAC1B,QAAM,MAAM,QAAQ,KAAK,SAAS,KAAK,OAAO;AAC9C,QAAM,SAAS,KAAK,QAAQ;AAC5B,QAAM,SAAS,kBAAkB,MAAM;AACvC,QAAM,SAAS,MAAM,cAAc,MAAM,IAAI;AAC7C,MAAI,CAAC,OAAO,OAAO;AACjB,WAAO,EAAE,KAAK,OAAO,WAAW,QAAQ,OAAO,QAAS,QAAQ,MAAM,QAAQ,OAAO;AAAA,EACvF;AACA,QAAM,cAAc,OAAO,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI;AACxD,QAAM,kBAAkB,KAAK,cAAc,WACvC,OAAO,MAAM,IAAI,CAAC,MAAM,UAAU,uBAAuB,QAAQ,KAAK,MAAM,KAAK,CAAC,IAClF,CAAC,MAAM;AACX,MAAI,CAACA,YAAW,MAAM,GAAG;AACvB,WAAO;AAAA,MACL;AAAA,MACA,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ,YAAY,CAAC;AAAA,MACrB,SAAS;AAAA,MACT;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACF,UAAM,QAAQ,MAAM,mBAAmB,MAAM;AAC7C,UAAM,kBAAkB,2BAA2B,KAAK,QAAQ,OAAO;AACvE,UAAM,mBAAmB,KAAK,QAAQ,iBAAiB;AACvD,UAAM,uBAAuB,KAAK,QAAQ,mBAAmB;AAC7D,UAAM,mBAAmB,KAAK,cAAc,WACxC,EAAE,KAAK,KAAK,QAAQ,OAAO,IAAI,OAAO,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,IACxG;AACJ,UAAM,kBACJ,KAAK,UAAU,MAAM,QAAQ,IAAI,CAAC,SAASD,OAAK,QAAQ,IAAI,CAAC,CAAC,MAC5D,KAAK,UAAU,YAAY,IAAI,CAAC,SAASA,OAAK,QAAQ,IAAI,CAAC,CAAC,KAC9D,KAAK,UAAU,MAAM,QAAQ,IAAI,CAAC,SAASA,OAAK,QAAQ,IAAI,CAAC,CAAC,MAC5D,KAAK,UAAU,gBAAgB,IAAI,CAAC,SAASA,OAAK,QAAQ,IAAI,CAAC,CAAC,KAClE,KAAK,UAAU,MAAM,QAAQ,QAAQ,MAAM,MAAM,KAAK,UAAU,eAAe,KAC/E,MAAM,QAAQ,WAAW,aAAa,oBACtC,MAAM,QAAQ,MAAM,WAAW,sBAAsB,KAAK,QAAQ,qBAClE,MAAM,QAAQ,MAAM,WAAW,oBAAoB,yBAClD,mBACG,CAAC,MAAM,QAAQ,YACf,MAAM,QAAQ,SAAS,QAAQ,iBAAiB,OAChD,MAAM,QAAQ,SAAS,UAAU,iBAAiB,SAClD,KAAK,UAAU,MAAM,QAAQ,SAAS,KAAK,MAAM,KAAK,UAAU,iBAAiB,KAAK,IACtF,MAAM,QAAQ,aAAa;AAEjC,QAAI,iBAAiB;AACnB,aAAO;AAAA,QACL;AAAA,QACA,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ,YAAY,CAAC;AAAA,QACrB,SAAS;AAAA,QACT;AAAA,QACA,SAAS;AAAA,QACT;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,MAAM,WAAW,CAAC,MAAM,WAAW;AACtC,aAAO;AAAA,QACL;AAAA,QACA,OAAO;AAAA,QACP,QAAQ,MAAM,QAAQ,OAAO,CAAC,WAAW,WAAW,+BAA4B,EAAE,KAAK,IAAI,KACzF;AAAA,QACF,QAAQ,YAAY,CAAC;AAAA,QACrB,SAAS;AAAA,QACT;AAAA,QACA,SAAS;AAAA,QACT;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,MAAM,UAAU;AACnB,aAAO;AAAA,QACL;AAAA,QACA,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ,YAAY,CAAC;AAAA,QACrB,SAAS;AAAA,QACT;AAAA,QACA,SAAS;AAAA,QACT;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,MACA,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ,YAAY,CAAC;AAAA,MACrB,SAAS;AAAA,MACT;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL;AAAA,MACA,OAAO;AAAA,MACP,QAAQ,8BAA8B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC5F,QAAQ,YAAY,CAAC;AAAA,MACrB,SAAS;AAAA,MACT;AAAA,MACA,SAAS;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACF;AAGA,eAAsB,sBACpB,OACA,MACA,UAAwC,CAAC,GACH;AACtC,QAAM,aAAa,MAAM,OAAO,CAAC,SAAS,KAAK,OAAO;AACtD,MAAI,CAAC,WAAW,QAAQ;AACtB,UAAM,IAAI,MAAM,0CAA0C;AAAA,EAC5D;AAEA,QAAM,SAAsC,EAAE,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAC,EAAE;AAC7F,aAAW,QAAQ,YAAY;AAC7B,UAAM,aAAc,MAAM,sBAAsB,MAAM,IAAI;AAC1D,QAAI,CAAC,QAAQ,UAAU,WAAW,UAAU,cAAc,WAAW,UAAU,mBAAmB;AAChG,aAAO;AACP,aAAO,MAAM,KAAK,UAAU;AAC5B;AAAA,IACF;AACA,QAAI,WAAW,UAAU,WAAW;AAClC,aAAO;AACP,aAAO,MAAM,KAAK,UAAU;AAC5B;AAAA,IACF;AACA,QAAI;AACF,YAAM,SAAS;AAAA,QACb,QAAQ,WAAW;AAAA,QACnB,SAAS,KAAK,QAAS;AAAA,QACvB,mBAAmB,KAAK,QAAS;AAAA,QACjC,GAAI,KAAK,QAAS,mBAAmB,OACjC,CAAC,IACD,EAAE,iBAAiB,KAAK,QAAS,gBAAgB;AAAA,QACrD,eAAe,KAAK,QAAS,iBAAiB;AAAA;AAAA;AAAA,QAG9C,aAAa,QAAQ,eAAe,KAAK,QAAS;AAAA,QAClD,cAAc,QAAQ;AAAA,QACtB,iBAAiB,QAAQ;AAAA,QACzB,OAAO,QAAQ;AAAA,MACjB;AACA,UAAI,KAAK,cAAc,UAAU;AAC/B,cAAM,eAAe,MAAM,cAAc,MAAM,IAAI;AACnD,YAAI,CAAC,aAAa,MAAO,OAAM,IAAI,MAAM,aAAa,MAAM;AAC5D,cAAM,eAAe;AAAA,UACnB,GAAG;AAAA,UACH,SAAS,aAAa;AAAA,UACtB,KAAK,KAAK,QAAS,OAAO;AAAA,QAC5B,CAAC;AAAA,MACH,OAAO;AACL,cAAM,YAAY,EAAE,GAAG,QAAQ,QAAQ,WAAW,OAAQ,CAAC;AAAA,MAC7D;AACA,aAAO;AACP,aAAO,MAAM,KAAM,MAAM,sBAAsB,MAAM,IAAI,CAAG;AAAA,IAC9D,SAAS,OAAO;AACd,aAAO;AACP,aAAO,MAAM,KAAK;AAAA,QAChB,GAAG;AAAA,QACH,OAAO;AAAA,QACP,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC/D,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;AAGA,eAAsB,8BACpB,OACA,MACA,UACA,aAC6C;AAC7C,QAAM,aAAa,MAAM;AAAA,IACvB,CAAC,SAAS,KAAK,YAAY,CAAC,YAAY,SAAS,IAAI,KAAK,OAAO;AAAA,EACnE;AACA,MAAI,CAAC,WAAW,OAAQ,QAAO;AAE/B,QAAM,UAAkC,CAAC;AACzC,QAAM,WAAuC,CAAC;AAC9C,aAAW,QAAQ,YAAY;AAC7B,UAAM,aAAc,MAAM,sBAAsB,MAAM,IAAI;AAC1D,QAAI,WAAW,UAAU,YAAY;AACnC,UAAI,KAAK,cAAc,UAAU;AAC/B,cAAM,QAAQ,MAAM,mBAAmB,WAAW,MAAM;AACxD,cAAM,QAAQ,MAAM,QAAQ,SAAU;AACtC,YAAI,aAAa;AACf,gBAAM,eAAe,YAAY,KAAK,OAAO;AAC7C,cAAI,CAAC,cAAc;AACjB,kBAAM,IAAI;AAAA,cACR,uCAAuC,WAAW,GAAG;AAAA,YACvD;AAAA,UACF;AACA,gBAAM,QAAQ,MAAM,QAAQ,YAAY;AACxC,cAAI,QAAQ,GAAG;AACb,kBAAM,IAAI;AAAA,cACR,aAAa,WAAW,GAAG,iCAAiC,YAAY;AAAA,YAC1E;AAAA,UACF;AACA,kBAAQ,KAAK,OAAO,IAAI,MAAM,QAAQ,KAAK;AAAA,QAC7C,OAAO;AACL,qBAAW,CAAC,OAAO,MAAM,KAAK,MAAM,QAAQ,QAAQ,GAAG;AACrD,oBAAQ,GAAG,KAAK,OAAO,IAAI,MAAM,KAAK,CAAC,EAAE,IAAI;AAAA,UAC/C;AAAA,QACF;AAAA,MACF,OAAO;AACL,gBAAQ,KAAK,OAAO,IAAI,WAAW;AAAA,MACrC;AAAA,IACF,MAAO,UAAS,KAAK,UAAU;AAAA,EACjC;AACA,MAAI,SAAS,QAAQ;AACnB,UAAM,SAAS,SACZ,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,SAAS,GAAG,KAAK,GAAG,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM,GAAG,EAC3D,KAAK,IAAI;AACZ,UAAM,IAAI;AAAA,MACR,8DAA8D,MAAM;AAAA,IAEtE;AAAA,EACF;AACA,SAAO;AACT;;;AIlVA,SAAS,cAAAE,mBAAkB;AAC3B,OAAOC,YAAU;AAkBjB,eAAsB,yBACpB,MACA,MACmC;AACnC,MAAI,CAAC,KAAK,SAAU,QAAO;AAC3B,SAAO,gBAAgB,MAAM,MAAM,oBAAI,IAAI,CAAC;AAC9C;AAEA,eAAe,gBACb,MACA,MACA,MAC4B;AAC5B,QAAM,WAAW,KAAK;AACtB,MAAI,CAAC,SAAU,QAAO,EAAE,OAAO,MAAM,QAAQ,+BAA+B;AAC5E,QAAM,aAAa,MAAM,cAAc,SAAS,YAAY,MAAM,IAAI;AACtE,MAAI,CAAC,WAAW,OAAO;AACrB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,QAAQ,mBAAmB,KAAK,OAAO,IAAI,SAAS,aAAa,kBAAkB,WAAW,MAAM;AAAA,IACtG;AAAA,EACF;AAEA,MAAI,CAAC,SAAS,gBAAgB,CAACC,YAAW,SAAS,UAAU,GAAG;AAC9D,WAAO,EAAE,OAAO,OAAO,QAAQ,+BAA+B,SAAS,UAAU,GAAG;AAAA,EACtF;AACA,MAAK,MAAM,WAAW,SAAS,UAAU,MAAO,SAAS,cAAc;AACrE,WAAO,EAAE,OAAO,OAAO,QAAQ,0DAA0D;AAAA,EAC3F;AAEA,MAAI,SAAS,UAAU;AACrB,QAAI,CAAC,SAAS,cAAc,CAACA,YAAW,SAAS,QAAQ,GAAG;AAC1D,aAAO,EAAE,OAAO,OAAO,QAAQ,6BAA6B,SAAS,QAAQ,GAAG;AAAA,IAClF;AACA,QAAK,MAAM,WAAW,SAAS,QAAQ,MAAO,SAAS,YAAY;AACjE,aAAO,EAAE,OAAO,OAAO,QAAQ,wDAAwD;AAAA,IACzF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,MAAM,QAAQ,8BAA8B;AAC9D;AAEA,eAAsB,qBAAqB,MAAoB,MAA2B;AACxF,QAAM,aAAa,MAAM,yBAAyB,MAAM,IAAI;AAC5D,MAAI,cAAc,CAAC,WAAW,MAAO,OAAM,IAAI,MAAM,WAAW,MAAM;AACxE;AAEA,eAAe,cACb,MACA,MACA,MAC4B;AAC5B,QAAM,MAAM,QAAQ,KAAK,SAAS,KAAK,OAAO;AAC9C,MAAI,KAAK,IAAI,GAAG,EAAG,QAAO,EAAE,OAAO,OAAO,QAAQ,gCAAgC,GAAG,GAAG;AACxF,QAAM,WAAW,IAAI,IAAI,IAAI;AAC7B,WAAS,IAAI,GAAG;AAEhB,MAAI,KAAK,UAAU;AACjB,UAAM,SAAS,MAAM,gBAAgB,MAAM,MAAM,QAAQ;AACzD,QAAI,CAAC,OAAO,MAAO,QAAO;AAAA,EAC5B;AAEA,MAAI,KAAK,SAAS;AAChB,UAAM,UAAU,MAAM,sBAAsB,MAAM,IAAI;AACtD,WAAO,SAAS,UAAU,aACtB,EAAE,OAAO,MAAM,QAAQ,qCAAqC,IAC5D;AAAA,MACE,OAAO;AAAA,MACP,QAAQ,qBAAqB,SAAS,SAAS,SAAS,MACrD,SAAS,SAAS,KAAK,QAAQ,MAAM,MAAM;AAAA,IAChD;AAAA,EACN;AAEA,MAAI,KAAK,QAAQ;AACf,UAAM,SAASC,OAAK,QAAQ,KAAK,MAAM,KAAK,MAAM;AAClD,WAAOD,YAAW,MAAM,IACpB,EAAE,OAAO,MAAM,QAAQ,6BAA6B,IACpD,EAAE,OAAO,OAAO,QAAQ,+BAA+B,KAAK,MAAM,GAAG;AAAA,EAC3E;AAEA,QAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,MAAI,CAAC,MAAO,QAAO,EAAE,OAAO,OAAO,QAAQ,gCAAgC;AAC3E,MAAI,MAAM,aAAa,KAAK,UAAU;AACpC,WAAO,EAAE,OAAO,OAAO,QAAQ,kCAAkC;AAAA,EACnE;AACA,MAAI,MAAM,WAAW,cAAc;AACjC,WAAO,EAAE,OAAO,OAAO,QAAQ,aAAa,MAAM,MAAM,mBAAmB;AAAA,EAC7E;AACA,MAAI,CAAC,MAAM,QAAQ,OAAQ,QAAO,EAAE,OAAO,OAAO,QAAQ,gCAAgC;AAC1F,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,QAAQ,SAAS;AACzD,UAAM,SAAS,MAAM,QAAQ,KAAK;AAClC,UAAM,OAAO,uBAAuB,OAAO,MAAM,KAAK;AACtD,QAAI,CAACA,YAAW,IAAI,EAAG,QAAO,EAAE,OAAO,OAAO,QAAQ,6BAA6B,IAAI,GAAG;AAC1F,QAAK,MAAM,WAAW,IAAI,MAAO,OAAO,QAAQ;AAC9C,aAAO,EAAE,OAAO,OAAO,QAAQ,+BAA+B,IAAI,GAAG;AAAA,IACvE;AAAA,EACF;AACA,SAAO,EAAE,OAAO,MAAM,QAAQ,2BAA2B;AAC3D;;;AL3FA,eAAe,kBAAkB,OAAkB,MAAsC;AACvF,WAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,QAAQ,SAAS;AACzD,UAAM,SAAS,MAAM,QAAQ,KAAK;AAClC,QACG,MAAM,WAAW,uBAAuB,OAAO,MAAM,KAAK,CAAC,MAAO,OAAO,OAC1E,QAAO;AAAA,EACX;AACA,SAAO;AACT;AAwCO,SAAS,uBACd,QACsB;AACtB,MAAI,WAAW,aAAa,WAAW,aAAc,QAAO;AAC5D,MAAI,WAAW,SAAU,QAAO;AAChC,MAAI,WAAW,cAAc,WAAW,kBAAmB,QAAO;AAClE,SAAO;AACT;AAGO,SAAS,cAAc,OAAuB,MAA4B;AAC/E,QAAM,UAAU,oBAAI,IAA6B;AACjD,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,QAAQ,KAAK,SAAS,KAAK,OAAO;AAC9C,UAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,QAAI,CAAC,SAAS,MAAM,aAAa,KAAK,SAAU;AAChD,UAAM,UAAU,uBAAuB,MAAM,MAAM;AACnD,QAAI,CAAC,QAAS;AACd,QAAI,YAAY,UAAU,CAAC,MAAM,MAAO;AACxC,QAAI,YAAY,UAAU,CAAC,MAAM,eAAgB;AACjD,YAAQ,IAAI,SAAS,CAAC,GAAI,QAAQ,IAAI,OAAO,KAAK,CAAC,GAAI,GAAG,CAAC;AAAA,EAC7D;AACA,SAAQ,CAAC,QAAQ,QAAQ,OAAO,EAAY,QAAQ,CAAC,YAAY;AAC/D,UAAM,OAAO,QAAQ,IAAI,OAAO;AAChC,WAAO,MAAM,SAAS,CAAC,EAAE,SAAS,KAAK,CAAC,IAAI,CAAC;AAAA,EAC/C,CAAC;AACH;AAOA,eAAsB,UACpB,OACA,MACA,OAA4B,CAAC,GACd;AACf,QAAM,QAAoB,CAAC;AAE3B,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,QAAQ,KAAK,SAAS,KAAK,OAAO;AAC9C,UAAM,QAAQ,KAAK,QAAQ,GAAG;AAE9B,QAAI;AACJ,QAAI;AAEJ,UAAM,WAAW,MAAM,yBAAyB,MAAM,IAAI;AAC1D,QAAI,YAAY,CAAC,SAAS,OAAO;AAC/B,cAAQ;AACR,eAAS,SAAS;AAAA,IACpB,WAAW,KAAK,OAAO;AACrB,cAAQ;AACR,eAAS;AAAA,IACX,WAAW,CAAC,SAAS,KAAK,QAAQ;AAKhC,UAAIE,YAAWC,OAAK,QAAQ,KAAK,MAAM,KAAK,MAAM,CAAC,GAAG;AACpD,gBAAQ;AACR,iBAAS,eAAe,KAAK,MAAM;AAAA,MACrC,OAAO;AACL,gBAAQ;AACR,iBAAS,+BAA+B,KAAK,MAAM;AAAA,MACrD;AAAA,IACF,WAAW,CAAC,OAAO;AAKjB,UAAID,YAAW,KAAK,OAAO,GAAG;AAC5B,gBAAQ;AACR,iBAAS;AAAA,MACX,OAAO;AACL,gBAAQ;AACR,iBAAS;AAAA,MACX;AAAA,IACF,WAAW,MAAM,aAAa,KAAK,UAAU;AAC3C,cAAQ;AACR,eAAS;AAAA,IACX,WAAW,MAAM,WAAW,mBAAmB;AAC7C,cAAQ;AACR,YAAM,QAAQ,MAAM,OAAO,SAAS,cAAc,IAAI,aAAa;AACnE,eACE,GAAG,MAAM,SAAS,iBAAiB,wBAAwB,KAAK;AAAA,IAEpE,WAAW,MAAM,WAAW,UAAU;AACpC,cAAQ;AACR,eAAS,MAAM,SAAS;AAAA,IAC1B,WAAW,MAAM,WAAW,YAAY;AACtC,cAAQ;AACR,eAAS;AAAA,IACX,WAAW,MAAM,WAAW,aAAa,MAAM,WAAW,cAAc;AACtE,cAAQ;AACR,eAAS,MAAM,QACX,4CACA;AAAA,IACN,WAAW,MAAM,WAAW,UAAU;AACpC,cAAQ;AACR,eAAS,MAAM,iBACX,wCACA;AAAA,IACN,WAAW,MAAM,WAAW,cAAc;AACxC,cAAQ;AACR,eAAS,YAAY,MAAM,MAAM;AAAA,IACnC,WACE,MAAM,QAAQ,WAAW,KACzB,MAAM,QAAQ,KAAK,CAAC,SAAS,UAC3B,CAACA,YAAW,uBAAuB,OAAO,MAAM,KAAK,CAAC,CAAC,GACzD;AACA,cAAQ;AACR,eACE,MAAM,QAAQ,WAAW,IACrB,6BACA,oBAAoB,MAAM,QACvB,OAAO,CAAC,SAAS,UAChB,CAACA,YAAW,uBAAuB,OAAO,MAAM,KAAK,CAAC,CAAC,EACxD,IAAI,CAAC,MAAM,EAAE,QAAQ,OAAO,EAC5B,KAAK,IAAI,CAAC;AAAA,IACrB,WAAW,MAAM,kBAAkB,OAAO,IAAI,GAAG;AAG/C,cAAQ;AACR,eAAS;AAAA,IACX,OAAO;AACL,cAAQ;AACR,eAAS;AAAA,IACX;AAEA,UAAM,UAAU,MAAM,sBAAsB,MAAM,IAAI;AACtD,UAAM,KAAK,EAAE,MAAM,KAAK,OAAO,QAAQ,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,EAAG,CAAC;AAAA,EAC1E;AAIA,QAAM,aAAa,MAAM,OAAO,CAAC,MAAM,EAAE,UAAU,aAAa,EAAE,UAAU,WAAW,EAAE,UAAU,QAAQ;AAC3G,QAAM,mBAAmB,oBAAI,IAAuB;AACpD,aAAW,QAAQ,YAAY;AAC7B,UAAM,WAAW,KAAK,KAAK;AAC3B,UAAM,WAAW,KAAK,KAAK,YAAY;AACvC,UAAM,QAAQ,iBAAiB,IAAI,QAAQ;AAC3C,QAAI,SAAS,MAAM,aAAa,UAAU;AACxC,YAAM,IAAI;AAAA,QACR,aAAa,QAAQ,gCAAgC,MAAM,QAAQ,KAAK,QAAQ;AAAA,MAClF;AAAA,IACF;AACA,QAAI,OAAO;AACT,YAAM,WAAW,KAAK,IAAI;AAC1B,YAAM,QAAQ,KAAK,KAAK;AACxB,YAAM,cAAc,KAAK,KAAK;AAAA,IAChC,OAAO;AACL,uBAAiB,IAAI,UAAU;AAAA,QAC7B;AAAA,QACA;AAAA,QACA,MAAM,KAAK,KAAK;AAAA,QAChB,YAAY,KAAK,KAAK;AAAA,QACtB,YAAY,CAAC,IAAI;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,EACF;AACA,QAAM,SAAS,CAAC,GAAG,iBAAiB,OAAO,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,SAAS,cAAc,EAAE,QAAQ,CAAC;AACjG,QAAM,gBAAgB,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC;AAChE,QAAM,SAAS,OAAO,WAAW,IAAI,OAAO,CAAC,IAAK;AAElD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,QAAQ,SAAS,OAAO,SAAS,OAAO;AAAA,IAC9C,UAAU,QAAQ,aAAa,OAAO,UAAU,cAAc,OAAO,IACjE,OACA,cAAc,OAAO,EAAE,KAAK,EAAE,UAAU,MAAM,SAAS,gBAAgB;AAAA,IAC3E,YAAY,WAAW,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,KAAK,YAAY,CAAC;AAAA,EACtE;AACF;AAEO,SAAS,UAAU,MAAuC;AAC/D,QAAM,SAAS;AAAA,IACb,IAAI;AAAA,IAAG,SAAS;AAAA,IAAG,WAAW;AAAA,IAAG,OAAO;AAAA,IAAG,UAAU;AAAA,IAAG,aAAa;AAAA,IACrE,aAAa;AAAA,IAAG,SAAS;AAAA,IAAG,QAAQ;AAAA,EACtC;AACA,aAAW,QAAQ,KAAK,MAAO,QAAO,KAAK,KAAK;AAChD,SAAO;AACT;;;AMtOA,IAAM,oBAAoB;AAE1B,IAAME,SAAQ,CAAC,OAAe,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAsBlE,eAAsB,OACpB,UACA,QACA,OACA,MACA,UACA,OAAsB,CAAC,GACA;AACvB,QAAM,SAAS,SAAS,YAAY,KAAK;AACzC,QAAM,cAAc,KAAK,eAAe,OAAO;AAC/C,QAAM,UAAU,KAAK,aAAa,OAAO;AACzC,QAAM,aAAa,KAAK,cAAc;AACtC,QAAM,gBAAgB,KAAK,iBAAiB,KAAK,KAAK;AACtD,QAAMC,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AAEvC,QAAM,YAAY,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS;AAAA,IAC5C,KAAK;AAAA,IACL,qBAAqB,SAAS,IAAI,SAAS,SAAS,KAAK,IAAI,CAAC;AAAA,EAChE,CAAC,CAAC;AACF,QAAM,QAAQ,IAAI,IAAI,CAAC,GAAG,UAAU,OAAO,CAAC,EAAE,IAAI,CAAC,aAAa,SAAS,IAAI,CAAC;AAC9E,MAAI,MAAM,OAAO,GAAG;AAClB,UAAM,IAAI,MAAM,aAAa,SAAS,EAAE,sDAAsD;AAAA,EAChG;AACA,QAAM,OAAO,MAAM,OAAO,EAAE,KAAK,EAAE,SAAS;AAE5C,MAAI,KAAK,UAAU,MAAM;AACvB,UAAM,OAAO,CAAC,GAAG,UAAU,OAAO,CAAC,EAAE,OAAO,CAAC,KAAK,aAAa,MAAM,SAAS,QAAQ,CAAC;AACvF,QAAI,OAAO,KAAK,QAAQ;AACtB,YAAM,IAAI;AAAA,QACR,wBAAwB,WAAW,MAAM,IAAI,CAAC,sBACzC,WAAW,MAAM,KAAK,MAAM,CAAC;AAAA,MAEpC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,cAAc,oBAAI,IAAkC;AAC1D,aAAW,WAAW,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,OAAO,CAAC,GAAG;AAC/D,gBAAY,IAAI,SAAS,MAAM,mBAAmB,QAAQ,OAAO,CAAC;AAAA,EACpE;AAEA,MAAI,YAAY;AAChB,MAAI,SAAS;AACb,MAAI,QAAQ;AACZ,MAAI,eAAe;AAGnB,QAAM,WAAW,oBAAI,IAA0B;AAC/C,MAAI,gBAA+B;AAEnC,iBAAe,gBAA+B;AAC5C,eAAW,CAAC,IAAI,IAAI,KAAK,CAAC,GAAG,QAAQ,GAAG;AACtC,UAAI;AACF,cAAM,QAAQ,MAAM,SAAS,KAAK,IAAI,KAAK,WAAW,EAAE,MAAM,aAAa,KAAK,YAAY,CAAC;AAC7F,YAAI,MAAM,WAAW,aAAc,UAAS,OAAO,EAAE;AACrD,wBAAgB;AAAA,MAClB,SAAS,KAAK;AAGZ,wBAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACjE;AAAA,IACF;AAAA,EACF;AAEA,iBAAe,cAA6B;AAC1C,UAAM,UAAU,KAAK,IAAI;AACzB,WAAO,SAAS,QAAQ,aAAa;AACnC,UAAI,KAAK,IAAI,IAAI,WAAW,eAAe;AACzC,cAAM,IAAI;AAAA,UACR,6CACG,gBAAgB,sBAAsB,aAAa,KAAK;AAAA,QAC7D;AAAA,MACF;AACA,YAAMD,OAAM,UAAU;AACtB,YAAM,cAAc;AAAA,IACtB;AAAA,EACF;AAEA,aAAW,EAAE,MAAM,IAAI,KAAK,OAAO;AACjC,UAAM,WAAW,UAAU,IAAI,GAAG;AAClC,UAAM,YAAY;AAElB,UAAM,QAAQ,KAAK,IAAI,IAAI;AAC3B,QAAI,QAAQ,QAAS,OAAMA,OAAM,UAAU,KAAK;AAIhD,UAAM,qBAAqB,MAAM,IAAI;AAErC,UAAM,gBAAgB,KAAK,QAAQ,GAAG;AACtC,UAAM,oBAAoB,eAAe,QAAQ,SAC7C,cAAc,UACd,eAAe,qBAAqB,CAAC;AAGzC,WAAO,MAAM,KAAK;AAAA,MAChB,SAAS,KAAK;AAAA,MACd,SAAS,KAAK;AAAA,MACd,UAAU,KAAK;AAAA,MACf,WAAW,KAAK;AAAA,MAChB,aAAa,KAAK,eAAe;AAAA,MACjC,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK,WACX;AAAA,QACE,MAAM,KAAK,SAAS;AAAA,QACpB,eAAe,KAAK,SAAS;AAAA,QAC7B,cAAc,KAAK,SAAS;AAAA,QAC5B,GAAI,KAAK,SAAS,aAAa,EAAE,YAAY,KAAK,SAAS,WAAW,IAAI,CAAC;AAAA,QAC3E,GAAI,KAAK,SAAS,YAAY,OAAO,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS,SAAS;AAAA,MAC/E,IACA;AAAA,MACJ,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,UAAU;AAAA,MACV,gBAAgB;AAAA,MAChB,gBAAgB;AAAA,MAChB,OAAO;AAAA,MACP,SAAS,CAAC;AAAA;AAAA;AAAA,MAGV;AAAA,MACA,kBAAkB,CAAC;AAAA,MACnB,WAAW;AAAA,MACX,YAAY,CAAC;AAAA,MACb,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC,MAAM,SAAS;AAAA,MACf,UAAU,SAAS;AAAA;AAAA;AAAA;AAAA,MAInB,UAAU,SAAS;AAAA,MACnB,cAAc;AAAA,IAChB,CAAC;AACD,UAAM,SAAS,UAAU,IAAI;AAE7B,mBAAe,KAAK,IAAI;AACxB,QAAI;AAIF,YAAM,OAAO,YAAY,IAAI,KAAK,OAAO,KAAK,CAAC;AAC/C,YAAM,EAAE,OAAO,SAAS,IAAI,MAAM,SAAS,OAAO,MAAM,IAAI;AAC5D,aAAO,MAAM,KAAK;AAAA,QAChB;AAAA;AAAA;AAAA,QAGA,gBACE,KAAK,cAAc,YAAa,SAAS,aAAa,KAAK,CAAC,KAAK,cAC7D,QACA;AAAA,QACN,QAAQ;AAAA,QACR,kBAAkB,WACd,EAAE,GAAG,KAAK,QAAQ,GAAG,EAAG,kBAAkB,CAAC,SAAS,EAAE,GAAG,SAAS,IAClE,KAAK,QAAQ,GAAG,EAAG;AAAA,MACzB,CAAC;AACD,eAAS,IAAI,OAAO,IAAI;AACxB;AACA,eAAS,SAAS;AAClB,MAAAC;AAAA,QACE,KAAK,GAAG,WAAM,KAAK,MAAM,KAAK,KAAK,IAAI,KAAK,MAAM,MAC/C,SAAS,aAAa,IACnB,KAAK,SAAS,UAAU,IAAI,KAAK,cAAc,YAAY,YAAY,KACvE,MACJ,KAAK,SAAS,MAAM;AAAA,MACxB;AAAA,IACF,SAAS,KAAK;AACZ;AACA,YAAMC,WAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAE/D,aAAO,MAAM,KAAK,EAAE,QAAQ,UAAU,OAAOA,UAAS,MAAM,EAAE,CAAC;AAC/D,MAAAD,KAAI,YAAY,GAAG,KAAKC,QAAO,EAAE;AAAA,IACnC;AACA,UAAM,SAAS,UAAU,IAAI;AAAA,EAC/B;AAEA,SAAO,EAAE,WAAW,QAAQ,OAAO,KAAK;AAC1C;;;ACjOA,IAAMC,SAAQ,CAAC,OAAe,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,EAAE,CAAC;AAwBlE,eAAsB,KACpB,UACA,MACA,UACA,OAAoB,CAAC,GACA;AACrB,QAAM,WAAW,KAAK,cAAc;AACpC,QAAM,UAAU,KAAK,aAAa,KAAK,KAAK;AAC5C,QAAMC,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AACvC,QAAM,UAAU,KAAK,IAAI;AACzB,QAAM,YAAY,IAAI,KAAK,KAAK,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;AAC3F,QAAM,eAAe,KAAK,QAAQ,IAAI,IAAI,UAAU,KAAK,CAAC,IAAI;AAE9D,QAAM,SAAqB,EAAE,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,cAAc,EAAE;AAEjF,QAAM,UAAU,MACd,OAAO,QAAQ,KAAK,OAAO,EAAE;AAAA,IAC3B,CAAC,CAAC,KAAK,CAAC,MACN,EAAE,aAAa,SAAS,OACvB,CAAC,gBAAgB,aAAa,IAAI,GAAG,MACtC,EAAE,UACD,EAAE,WAAW,aAAa,EAAE,WAAW;AAAA,EAC5C;AAEF,SAAO,QAAQ,EAAE,SAAS,GAAG;AAC3B,QAAI,KAAK,IAAI,IAAI,UAAU,SAAS;AAClC,aAAO,eAAe,QAAQ,EAAE;AAChC,MAAAA,KAAI,oBAAoB,OAAO,YAAY,wDAAmD;AAC9F;AAAA,IACF;AAEA,eAAW,CAAC,KAAK,KAAK,KAAK,QAAQ,GAAG;AACpC,UAAI;AACF,cAAM,cAAc,UAAU,IAAI,GAAG;AACrC,cAAM,QAAQ,MAAM,SAAS,KAAK,MAAM,OAAQ,MAAM,WAAW;AAAA,UAC/D,aAAa,MAAM,eAAe,aAAa;AAAA,UAC/C,MAAM;AAAA,QACR,CAAC;AACD,YAAI,MAAM,WAAW,YAAY,MAAM,WAAW,cAAc;AAC9D,iBAAO,MAAM,KAAK;AAAA,YAChB,QAAQ;AAAA,YACR,gBAAgB,MAAM;AAAA,YACtB,kBAAkB,MAAM,WACpB;AAAA,cACE,GAAG,MAAM;AAAA,cACT,CAAC,SAAS,EAAE,GAAG;AAAA,gBACb,GAAG,MAAM,iBAAiB,SAAS,EAAE;AAAA,gBACrC,GAAG,MAAM;AAAA,cACX;AAAA,YACF,IACA,MAAM;AAAA,UACZ,CAAC;AACD,iBAAO;AACP,UAAAA;AAAA,YACE,MAAM,WAAW,eACb,aAAa,GAAG,KAAK,MAAM,UAAU,MAAM,qBAC3C,aAAa,GAAG,KAAK,MAAM,cAAc,MAAM;AAAA,UACrD;AAAA,QACF,WAAW,MAAM,WAAW,SAAS;AACnC,gBAAM,aAAa,MAAM,SAAS,SAC9B,MAAM,UACN,MAAM,YACJ,CAAC,EAAE,KAAK,MAAM,UAAU,CAAC,IACzB,CAAC;AACP,iBAAO,MAAM,KAAK;AAAA,YAChB,QAAQ;AAAA,YACR,UAAU,MAAM;AAAA,YAChB,WAAW,WAAW,CAAC,GAAG,OAAO;AAAA,YACjC;AAAA,YACA,kBAAkB,MAAM,WACpB;AAAA,cACE,GAAG,MAAM;AAAA,cACT,CAAC,SAAS,EAAE,GAAG;AAAA,gBACb,GAAG,MAAM,iBAAiB,SAAS,EAAE;AAAA,gBACrC,GAAG,MAAM;AAAA,cACX;AAAA,YACF,IACA,MAAM;AAAA,YACV,OAAO;AAAA,UACT,CAAC;AACD,iBAAO;AACP,UAAAA,KAAI,aAAa,GAAG,EAAE;AAAA,QACxB,WAAW,MAAM,WAAW,UAAU;AACpC,iBAAO,MAAM,KAAK,EAAE,QAAQ,UAAU,OAAO,MAAM,MAAM,CAAC;AAC1D,iBAAO;AACP,UAAAA,KAAI,aAAa,GAAG,KAAK,MAAM,KAAK,EAAE;AAAA,QACxC;AAAA,MACF,SAAS,KAAK;AACZ,QAAAA,KAAI,mBAAmB,GAAG,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MACnF;AAAA,IACF;AAEA,UAAM,SAAS,UAAU,IAAI;AAC7B,QAAI,QAAQ,EAAE,SAAS,EAAG,OAAMD,OAAM,QAAQ;AAAA,EAChD;AAEA,QAAM,SAAS,UAAU,IAAI;AAC7B,SAAO;AACT;;;AC/HA,SAAS,cAAAE,mBAAkB;AAC3B,SAAS,SAAAC,QAAO,YAAAC,WAAU,UAAAC,SAAQ,MAAAC,KAAI,aAAAC,kBAAiB;AACvD,OAAOC,YAAU;;;ACFjB,IAAM,uBAAuB,oBAAI,IAAI;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,SAAS,qBAAqB,OAAwB;AAC3D,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,KAAK;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,OAAO,YAAY,OAAO,SAAU,QAAO;AAC/C,aAAW,OAAO,OAAO,aAAa,KAAK,GAAG;AAC5C,UAAM,aAAa,IAAI,YAAY;AACnC,QACE,qBAAqB,IAAI,UAAU,KACnC,WAAW,SAAS,YAAY,KAChC,WAAW,SAAS,WAAW,KAC/B,WAAW,SAAS,gBAAgB,KACpC,WAAW,SAAS,OAAO,EAC3B,QAAO;AAAA,EACX;AACA,SAAO;AACT;AAOO,SAAS,uBAAuB,OAAwB;AAC7D,MAAI;AACJ,MAAI;AACF,aAAS,IAAI,IAAI,KAAK;AAAA,EACxB,QAAQ;AAGN,WAAO;AAAA,EACT;AACA,MAAI,OAAO,aAAa,WAAW,OAAO,aAAa,QAAS,QAAO;AACvE,SAAO,CAAC,qBAAqB,KAAK;AACpC;;;ADdA,eAAsB,YACpB,UACA,OACA,MACA,UACA,OAQI,CAAC,GACiB;AACtB,QAAMC,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AACvC,QAAM,SAAsB,EAAE,YAAY,GAAG,SAAS,GAAG,QAAQ,EAAE;AACnE,QAAM,YAAY,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;AAC9E,2BAAyB,MAAM,KAAK;AACpC,QAAM,WACJ,KAAK,aAAa,QACd,OACAC,OAAK,QAAQ,KAAK,YAAYA,OAAK,KAAKA,OAAK,QAAQ,QAAQ,GAAG,cAAc,OAAO,CAAC;AAK5F,QAAM,UAAU,OAAO,QAAQ,KAAK,OAAO,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM;AAChE,QAAI,EAAE,aAAa,SAAS,MAAM,CAAC,UAAU,IAAI,GAAG,EAAG,QAAO;AAC9D,QAAI,EAAE,WAAW,cAAc,EAAE,WAAW,kBAAmB,QAAO;AACtE,QAAI,CAAC,KAAK,UAAU,EAAE,WAAW,aAAc,QAAO;AACtD,UAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,WAAO,EAAE,QAAQ,WAAW,KAAK,CAAC,QAChC,EAAE,QAAQ,KAAK,CAAC,WAAW,CAACC,YAAW,kBAAkB,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC;AAAA,EACrF,CAAC;AACD,QAAM,cAAc,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,eAAe,CAAC,GAAG,KAAK,IAAI,GAAG,QAAQ,MAAM,CAAC;AAC5F,MAAI,SAAS;AAEb,iBAAe,SAAwB;AACrC,eAAS;AACP,YAAM,OAAO,QAAQ,QAAQ;AAC7B,UAAI,CAAC,KAAM;AACX,YAAM,CAAC,KAAK,KAAK,IAAI;AAErB,YAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,UAAI,CAAC,MAAM;AAET,QAAAF,KAAI,aAAa,GAAG,4BAA4B;AAChD,eAAO;AACP;AAAA,MACF;AACA,UAAI,MAAM,aAAa,KAAK,UAAU;AACpC,QAAAA,KAAI,aAAa,GAAG,mCAAmC;AACvD,eAAO;AACP;AAAA,MACF;AACA,YAAM,UAAU,MAAM,YAAY,SAC9B,MAAM,aACN,MAAM,YACJ,CAAC,EAAE,KAAK,MAAM,UAAU,CAAC,IACzB,KAAK,UAAU,MAAM,QAAQ,SAC3B,MAAM,QAAQ,IAAI,CAAC,OAAO,EAAE,KAAK,IAAI,MAAM,EAAE,MAAM,WAAW,EAAE,UAAU,EAAE,IAC9E,CAAC;AACP,UAAI,CAAC,QAAQ,QAAQ;AACnB,eAAO,MAAM,KAAK;AAAA,UAChB,QAAQ;AAAA,UACR,OAAO;AAAA,QACT,CAAC;AACD,eAAO;AACP;AAAA,MACF;AAEA,YAAM,UAAwB,CAAC;AAC/B,UAAI;AACF,iBAAS,QAAQ,GAAG,QAAQ,QAAQ,QAAQ,SAAS;AACnD,gBAAM,SAAS,QAAQ,KAAK;AAC5B,gBAAM,WAAW,MAAM,QAAQ;AAAA,YAAK,CAAC,MACnC,OAAO,OAAO,EAAE,SAAS,OAAO,OAAO,CAAC,EAAE,QAAQ,QAAQ,WAAW;AAAA,UACvE;AACA,gBAAM,SAAS,WACX,kBAAkB,SAAS,MAAM,KAAK,IAAI,IAC1C,mBAAmB,MAAM,OAAO,MAAM,OAAO,QAAQ,QAAQ,OAAO,SAAS;AAEjF,cAAIE,YAAW,MAAM,GAAG;AACtB,kBAAM,cAAc,MAAM,WAAW,MAAM;AAC3C,gBAAI,YAAY,gBAAgB,SAAS,QAAQ;AAC/C,kBAAI,UAAU;AACZ,sBAAM;AAAA,kBACJ;AAAA,kBACA,MAAMC,UAAS,MAAM;AAAA,kBACrB,SAAS,aAAa,UAAU;AAAA,kBAChC,SAAS;AAAA,gBACX;AAAA,cACF;AACA,sBAAQ,KAAK,EAAE,GAAG,UAAU,MAAM,mBAAmB,QAAQ,KAAK,IAAI,EAAE,CAAC;AACzE;AAAA,YACF;AAEA,kBAAM,cAAc,MAAM,qBAAqB,CAAC,GAAG;AAAA,cAAK,CAAC,QAAQ,UAAU,QACzE,kBAAkB,QAAQ,MAAM,UAAU,IAAI,MAAM,MAAM;AAAA,YAC5D;AACA,gBAAI,CAAC,KAAK,OAAO;AACf,kBAAI,CAAC,YAAY,cAAc,gBAAgB,WAAW,QAAQ;AAAA,cAIlE,WAAW,YAAY,YAAY;AACjC,sBAAM,IAAI;AAAA,kBACR,yCAAyC,MAAM;AAAA,gBACjD;AAAA,cACF,OAAO;AACL,sBAAM,IAAI;AAAA,kBACR,0CAA0C,MAAM;AAAA,gBAClD;AAAA,cACF;AAAA,YACF;AACA,YAAAH;AAAA,cACE,aAAaC,OAAK,SAAS,QAAQ,IAAI,GAAG,MAAM,CAAC,MAC9C,KAAK,QAAQ,eAAe;AAAA,YACjC;AAAA,UACF;AAEA,gBAAM,oBAAoB,OAAO,aAAa,UAAU,aAAa,UAAU;AAC/E,cAAI,MAAM,YAAY,WAClB,MAAM,gBAAgB,UAAU,SAAS,QAAQ,iBAAiB,IAClE;AACJ,cAAI,KAAK;AACP,YAAAD,KAAI,aAAaC,OAAK,SAAS,QAAQ,IAAI,GAAG,MAAM,CAAC,EAAE;AAAA,UACzD,OAAO;AACL,gBAAI,CAAC,OAAO,KAAK;AACf,oBAAM,IAAI,MAAM,4CAA4C,OAAO,QAAQ,OAAO,EAAE;AAAA,YACtF;AACA,kBAAM,MAAM,SAAS,SAAS,OAAO,GAAG;AAAA,UAC1C;AACA,cAAI;AACJ,cAAI;AACF,wBAAY,cAAc,KAAK,iBAAiB;AAAA,UAClD,SAAS,KAAK;AACZ,kBAAM,QAAQ,sBAAsB,UAAU,MAAM,QAAQ;AAC5D,kBAAM,WAAW,gBAAgB,GAAG,MAAM;AAC1C,kBAAM,IAAI;AAAA,cACR,gBAAgB,OAAO,QAAQ,OAAO,YAAY,WAAW,MAAM,SAAS,IAAI,KAAK,MAClF,WAAW,KAAK,IAAI,MAAM,YAAY,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,YAChG;AAAA,UACF;AACA,cAAI,SAAU,OAAM,WAAW,UAAU,KAAK,SAAS;AACvD,gBAAMG,OAAMH,OAAK,QAAQ,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;AACrD,gBAAM,MAAM,GAAG,MAAM;AACrB,gBAAMI,WAAU,KAAK,GAAG;AACxB,kBAAQ,KAAK;AAAA,YACX,MAAM,mBAAmB,QAAQ,KAAK,IAAI;AAAA,YAC1C,QAAQ,OAAO,GAAG;AAAA,YAClB,GAAI,OAAO,OAAO,EAAE,MAAM,OAAO,KAAK,IAAI,CAAC;AAAA,YAC3C;AAAA,UACF,CAAC;AAKD,iBAAO,MAAM,KAAK,EAAE,SAAS,aAAa,MAAM,SAAS,OAAO,EAAE,CAAC;AACnE,gBAAM,SAAS,UAAU,IAAI;AAC7B,gBAAMC,QAAO,KAAK,MAAM;AACxB,UAAAN,KAAI,aAAaC,OAAK,SAAS,QAAQ,IAAI,GAAG,MAAM,CAAC,EAAE;AAAA,QACzD;AACA,cAAM,oBAAoB,QAAQ,OAAO,CAAC,WAAW,uBAAuB,OAAO,GAAG,CAAC;AACvF,eAAO,MAAM,KAAK;AAAA,UAChB,QAAQ;AAAA,UACR,UAAU,SAAS;AAAA,UACnB;AAAA;AAAA;AAAA;AAAA,UAIA,WAAW,kBAAkB,CAAC,GAAG,OAAO;AAAA,UACxC,YAAY;AAAA,UACZ,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,UACrC,OAAO;AAAA,UACP,mBAAmB,CAAC;AAAA,QACtB,CAAC;AACD,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAMM,WAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,eAAO,MAAM,KAAK;AAAA,UAChB,QAAQ;AAAA,UACR,SAAS,aAAa,MAAM,SAAS,OAAO;AAAA,UAC5C,OAAO,oBAAoBA,QAAO;AAAA,QACpC,CAAC;AACD,eAAO;AACP,QAAAP,KAAI,aAAa,GAAG,KAAKO,QAAO,EAAE;AAAA,MACpC;AACA,YAAM,SAAS,UAAU,IAAI;AAAA,IAC/B;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,MAAM,KAAK,EAAE,QAAQ,YAAY,GAAG,MAAM,CAAC;AAC7D,QAAM,SAAS,UAAU,IAAI;AAC7B,SAAO;AACT;AAEA,eAAe,gBACb,UACA,MACA,WACwB;AACxB,QAAM,OAAON,OAAK,KAAK,UAAU,cAAc,MAAM,SAAS,CAAC;AAC/D,MAAI,CAACC,YAAW,IAAI,EAAG,QAAO;AAC9B,MAAI;AACF,UAAM,MAAM,MAAMC,UAAS,IAAI;AAC/B,QAAI,OAAO,GAAG,MAAM,KAAM,QAAO;AACjC,kBAAc,KAAK,SAAS;AAC5B,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,WACb,UACA,KACA,WACA,WACe;AACf,QAAM,OAAO,aAAa,OAAO,GAAG;AACpC,gBAAc,KAAK,SAAS;AAC5B,QAAM,OAAOF,OAAK,KAAK,UAAU,cAAc,MAAM,SAAS,CAAC;AAC/D,MAAI,MAAM,gBAAgB,UAAU,MAAM,SAAS,EAAG;AACtD,QAAMG,OAAM,UAAU,EAAE,WAAW,KAAK,CAAC;AACzC,QAAM,MAAM,GAAG,IAAI,IAAI,QAAQ,GAAG,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AACzE,QAAMC,WAAU,KAAK,GAAG;AACxB,MAAI;AACF,UAAMC,QAAO,KAAK,IAAI;AAAA,EACxB,SAAS,KAAK;AAGZ,QAAI,CAACJ,YAAW,IAAI,EAAG,OAAM;AAAA,EAC/B,UAAE;AACA,UAAMM,IAAG,KAAK,EAAE,OAAO,KAAK,CAAC;AAAA,EAC/B;AACF;AAEA,SAAS,aAAa,UAAwB,SAAqC;AACjF,QAAM,SAAS,oBAAI,IAAwB;AAC3C,aAAW,UAAU,CAAC,GAAG,UAAU,GAAG,OAAO,GAAG;AAC9C,WAAO,IAAI,OAAO,OAAO,QAAQ,OAAO,IAAI,KAAK,QAAQ,OAAO,IAAI,IAAI,MAAM;AAAA,EAChF;AACA,SAAO,CAAC,GAAG,OAAO,OAAO,CAAC;AAC5B;AAQA,eAAsB,SACpB,UACA,OACA,MACA,OAA+C,CAAC,GAC/B;AACjB,QAAMR,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AACvC,QAAM,YAAY,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;AAC9E,MAAI,SAAS;AAEb,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACvD,UAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,QAAI,CAAC,QAAQ,MAAM,aAAa,SAAS,MAAM,CAAC,MAAM,SAAU;AAGhE,QAAI,MAAM,cAAc,UAAW;AACnC,QAAI,CAAC,SAAS,QAAS,QAAO;AAC9B,QAAI;AACF,YAAM,SAAS,QAAQ,MAAM,UAAU,KAAK,IAAI;AAChD;AAAA,IACF,SAAS,KAAK;AACZ,MAAAA,KAAI,gBAAgB,GAAG,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,IAChF;AAAA,EACF;AACA,SAAO;AACT;;;AE1TA,SAAS,WAAW,cAAAS,oBAAkB;AACtC,SAAS,QAAQ,QAAAC,aAAY;AAC7B,OAAOC,YAAU;AA6CjB,eAAsB,OACpB,QACA,OACA,MACA,UACA,OAAsB,CAAC,GACA;AACvB,QAAM,SAAwB,CAAC;AAC/B,QAAM,MAAM,CAAC,IAAY,OAAoBC,aAAoB,OAAO,KAAK,EAAE,IAAI,OAAO,SAAAA,SAAQ,CAAC;AAEnG;AAAA,IACE;AAAA,IACA;AAAA,IACA,GAAG,OAAO,KAAK,OAAO,SAAS,MAAM,EAAE,MAAM,cACxC,OAAO,KAAK,OAAO,SAAS,MAAM,EAAE,MAAM,cAAc,MAAM,MAAM;AAAA,EAC3E;AACA,MAAI,QAAQ,MAAM,GAAG,OAAO,KAAK,KAAK,OAAO,EAAE,MAAM,0BAA0B;AAE/E,QAAM,OAAO,CAAC,GAAG,IAAI,IAAI,MAAM,QAAQ,CAAC,SAAS;AAAA,IAC/CC,OAAK,QAAQ,KAAK,OAAO;AAAA,IACzB,GAAI,KAAK,UAAU,CAACA,OAAK,QAAQ,KAAK,QAAQ,OAAO,CAAC,IAAI,CAAC;AAAA,EAC7D,CAAC,CAAC,CAAC;AACH,QAAM,aAAuB,CAAC;AAC9B,aAAW,OAAO,MAAM;AACtB,UAAM,WAAW,MAAM,yBAAyB,GAAG;AACnD,QAAI;AACF,YAAM,OAAO,UAAU,UAAU,IAAI;AAAA,IACvC,QAAQ;AACN,iBAAW,KAAK,GAAG;AAAA,IACrB;AAAA,EACF;AACA;AAAA,IACE;AAAA,IACA,WAAW,SAAS,UAAU;AAAA,IAC9B,WAAW,SACP,gCAAgC,WAAW,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,KACjE,GAAG,KAAK,MAAM,mBAAmB,KAAK,WAAW,IAAI,SAAS,SAAS;AAAA,EAC7E;AAEA,QAAM,eAAe,oBAAI,IAAoB;AAC7C,QAAM,mBAA6B,CAAC;AACpC,QAAM,YAAY,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,KAAK,OAAO,IAAI,KAAK,OAAO,IAAI,IAAI,CAAC,CAAC;AACxF,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACvD,aAAS,QAAQ,GAAG,QAAQ,MAAM,QAAQ,QAAQ,SAAS;AACzD,YAAM,SAAS,MAAM,QAAQ,KAAK;AAClC,YAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,YAAM,WAAW,OACb,uBAAuB,OAAO,MAAM,KAAK,IACzC,kBAAkB,OAAO,MAAMA,OAAK,QAAQ,QAAQ,CAAC;AACzD,YAAM,QAAQ,aAAa,IAAI,QAAQ;AACvC,UAAI,SAAS,UAAU,IAAK,kBAAiB,KAAK,GAAG,OAAO,IAAI,KAAK,KAAK,KAAK,GAAG,GAAG;AACrF,mBAAa,IAAI,UAAU,GAAG;AAAA,IAChC;AAAA,EACF;AACA,MAAI,iBAAiB,QAAQ;AAK3B;AAAA,MACE;AAAA,MACA;AAAA,MACA,oCAAoC,iBAAiB,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,GACtE,iBAAiB,SAAS,IAAI,SAAS,iBAAiB,SAAS,CAAC,UAAU,EAAE;AAAA,IAErF;AAAA,EACF,OAAO;AACL,QAAI,gBAAgB,MAAM,GAAG,aAAa,IAAI,6CAA6C;AAAA,EAC7F;AAEA,QAAM,WAAWA,OAAK,KAAKA,OAAK,QAAQ,QAAQ,GAAG,cAAc,OAAO;AACxE,QAAM,WAAqB,CAAC;AAC5B,QAAM,eAAyB,CAAC;AAChC,QAAM,eAAyB,CAAC;AAChC,QAAM,MAAM,KAAK,IAAI;AACrB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACvD,SAAK,MAAM,WAAW,aAAa,MAAM,WAAW,iBAAiB,CAAC,MAAM,OAAO;AACjF,mBAAa,KAAK,GAAG,GAAG,KAAK,MAAM,MAAM,kBAAkB;AAAA,IAC7D;AACA,QAAI,MAAM,WAAW,YAAY,CAAC,MAAM,gBAAgB;AACtD,mBAAa,KAAK,GAAG,GAAG,oCAAoC;AAAA,IAC9D;AACA,QAAI,MAAM,WAAW,cAAc,MAAM,WAAW,kBAAmB;AACvE,UAAM,YAAY,QAAQ,MAAM,aAAa,MAAM,YAAY,MAAM;AACrE,QAAI,WAAW;AACf,eAAW,UAAU,MAAM,SAAS;AAClC,YAAM,SAASA,OAAK;AAAA,QAClB;AAAA,QACA,cAAc,OAAO,QAAQ,OAAO,aAAa,UAAU,GAAG;AAAA,MAChE;AACA,UAAIC,aAAW,MAAM,KAAM,MAAM,WAAW,MAAM,MAAO,OAAO,QAAQ;AACtE,mBAAW;AACX;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,aAAa,CAAC,SAAU,UAAS,KAAK,GAAG;AAC9C,QACE,MAAM,cAAc,SACpB,MAAM,eACN,MAAM,KAAK,MAAM,MAAM,WAAW,IAAI,IAAI,KAAK,KAAK,KACpD;AACA,mBAAa,KAAK,GAAG;AAAA,IACvB;AAAA,EACF;AACA;AAAA,IACE;AAAA,IACA,SAAS,UAAU,aAAa,SAAS,UAAU,aAAa,SAAS,YAAY;AAAA,IACrF,aAAa,SACT,4BAA4B,aAAa,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,KAC/D,SAAS,SACT,GAAG,SAAS,MAAM,oEAAoE,SAAS,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,KACrH,aAAa,SACX,GAAG,aAAa,MAAM,8EACtB;AAAA,EACR;AAEA,QAAM,OAAO,MAAM,UAAU,OAAO,IAAI;AACxC,QAAM,SAAS,UAAU,IAAI;AAC7B,QAAM,YAAY,KAAK,MAAM,OAAO,CAAC,MAAM,EAAE,UAAU,IAAI,EAAE;AAC7D;AAAA,IACE;AAAA,IACA,YAAY,YAAY;AAAA,IACxB,YACI,GAAG,SAAS,+BACZ,OAAO,QAAQ,MAAM,EAClB,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,EACvB,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,EAAE,EACnC,KAAK,IAAI,IACZ;AAAA,EACN;AAEA,QAAM,YAAY,cAAc,OAAO,IAAI;AAC3C;AAAA,IACE;AAAA,IACA,UAAU,SAAS,YAAY;AAAA,IAC/B,UAAU,SACN,4CACA,UACG;AAAA,MAAI,CAAC,WACJ,aAAa,OAAO,OAAO,KAAK,OAAO,KAAK,MAAM,SAAS,OAAO,KAAK,WAAW,IAAI,KAAK,GAAG;AAAA,IAChG,EACC,KAAK,IAAI,IACZ;AAAA,EACN;AAEA,QAAM,UAAU,KAAK,MAAM,QAAQ,CAAC,SAAS,KAAK,UAAU,CAAC,KAAK,OAAO,IAAI,CAAC,CAAC;AAC/E,QAAM,iBAAiB,QAAQ,OAAO,CAAC,SAAS,KAAK,UAAU,UAAU;AACzE,MAAI,QAAQ,QAAQ;AAClB;AAAA,MACE;AAAA,MACA,eAAe,SAAS,YAAY;AAAA,MACpC,eAAe,SACX,GAAG,eAAe,MAAM,IAAI,QAAQ,MAAM,qDAC1C,eAAe,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,GAAG,KAAK,GAAG,IAAI,KAAK,KAAK,EAAE,EAAE,KAAK,IAAI,IAC/E,OAAO,QAAQ,MAAM;AAAA,IAC3B;AAAA,EACF;AAEA,QAAM,eAAe,CAAC,KAAK;AAC3B,QAAM,UAAkC,KAAK,aAAa,CAAC;AAAA,IACzD,IAAI,KAAK,UAAU,MAAM;AAAA,IACzB,UAAU,KAAK;AAAA,IACf,eAAe,KAAK,iBAAiB,QAAQ,KAAK,QAAQ;AAAA,IAC1D,eAAe,KAAK;AAAA,EACtB,CAAC;AACD,aAAW,UAAU,SAAS;AAC5B,UAAM,UAAU,QAAQ,WAAW,IAAI,aAAa,YAAY,OAAO,EAAE;AACzE,QAAI,KAAK,SAAS;AAChB,UAAI,SAAS,WAAW,GAAG,OAAO,EAAE,mCAAmC;AAAA,IACzE,WAAW,CAAC,OAAO,UAAU;AAC3B;AAAA,QACE;AAAA,QACA;AAAA,QACA,CAAC,OAAO,gBACJ,GAAG,OAAO,uBAAuB,SAC7B,OAAO,sBAAsB,KAAK,IAAI,IACtC,OAAO,kBAAkB,eAAe,qBAAqB,GAAG,OAAO,EAAE,cAAc,IACxF,OAAO,yBAAyB,OAAO,sBAAsB,SAAS,IAAI,QAAQ,IAAI,oBACzF,GAAG,OAAO,EAAE;AAAA,MAClB;AAAA,IACF,WAAW,CAAC,OAAO,SAAS,WAAW,CAAC,OAAO,SAAS,iBAAiB;AACvE,UAAI,SAAS,MAAM,GAAG,OAAO,EAAE,6CAA6C;AAAA,IAC9E,WAAW,CAAC,OAAO,SAAS,SAAS;AACnC,UAAI;AACF,cAAM,OAAO,SAAS,gBAAiB;AACvC,YAAI,SAAS,MAAM,GAAG,OAAO,EAAE,2CAA2C;AAAA,MAC5E,SAAS,KAAK;AACZ;AAAA,UACE;AAAA,UACA;AAAA,UACA,GAAG,eAAe,aAAa,OAAO,EAAE,yBACnC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACvD;AAAA,MACF;AAAA,IACF,OAAO;AACL,UAAI;AACF,cAAM,UAAU,MAAM,OAAO,SAAS,QAAQ;AAC9C;AAAA,UACE;AAAA,UACA;AAAA,UACA,GAAG,OAAO,EAAE,eAAe,QAAQ,SAAS,IAAI,QAAQ,IAAI;AAAA,QAC9D;AAAA,MACF,SAAS,KAAK;AACZ;AAAA,UACE;AAAA,UACA;AAAA,UACA,GAAG,eAAe,aAAa,OAAO,EAAE,yBACnC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,IAAI,CAAC,OAAO,KAAK,CAAC,MAAM,EAAE,UAAU,OAAO,GAAG,OAAO;AAChE;AAEA,eAAe,yBAAyB,OAAgC;AACtE,MAAI,UAAU;AACd,aAAS;AACP,QAAI;AACF,WAAK,MAAMC,MAAK,OAAO,GAAG,YAAY,EAAG,QAAO;AAAA,IAClD,QAAQ;AAAA,IAGR;AACA,UAAM,SAASF,OAAK,QAAQ,OAAO;AACnC,QAAI,WAAW,QAAS,QAAO;AAC/B,cAAU;AAAA,EACZ;AACF;;;ACpRA,SAAS,cAAAG,oBAAkB;AAC3B,SAAS,YAAAC,WAAU,aAAAC,kBAAiB;AACpC,OAAOC,YAAU;;;ACFjB,SAAS,SAAAC,QAAO,YAAAC,WAAU,UAAAC,SAAQ,MAAAC,KAAI,aAAAC,kBAAiB;AACvD,SAAS,cAAAC,oBAAkB;AAC3B,OAAO,gBAAgB;AACvB,SAAS,KAAAC,UAAS;AAEX,IAAM,kBAAkBA,GAAE,OAAO;AAAA,EACtC,SAASA,GAAE,QAAQ,CAAC;AAAA;AAAA,EAEpB,QAAQA,GAAE,OAAOA,GAAE,OAAO,CAAC;AAC7B,CAAC;AAGD,IAAM,aAAa;AAEZ,SAAS,aAAa,OAAwB;AACnD,SAAO,WAAW,KAAK,KAAK;AAC9B;AAGO,SAAS,WAAW,OAA2B;AACpD,SAAO,gBAAgB,MAAM,KAAK;AACpC;AAcA,eAAsB,UAAUC,QAAkC;AAChE,MAAI,CAACF,aAAWE,MAAI,EAAG,QAAO,EAAE,SAAS,GAAG,QAAQ,CAAC,EAAE;AACvD,MAAI;AACF,UAAM,SAAS,gBAAgB,UAAU,KAAK,MAAM,MAAMN,UAASM,QAAM,MAAM,CAAC,CAAC;AACjF,QAAI,CAAC,OAAO,QAAS,QAAO,EAAE,SAAS,GAAG,QAAQ,CAAC,EAAE;AAGrD,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQ,OAAO;AAAA,QACb,OAAO,QAAQ,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,CAAC,EAAE,IAAI,MAAM,aAAa,IAAI,CAAC;AAAA,MAC5E;AAAA,IACF;AAAA,EACF,QAAQ;AAEN,WAAO,EAAE,SAAS,GAAG,QAAQ,CAAC,EAAE;AAAA,EAClC;AACF;AAEA,eAAsB,UAAUA,QAAc,OAAiC;AAC7E,QAAM,SAAiC,CAAC;AACxC,aAAW,OAAO,OAAO,KAAK,MAAM,MAAM,EAAE,KAAK,GAAG;AAClD,UAAM,OAAO,MAAM,OAAO,GAAG;AAC7B,QAAI,CAAC,aAAa,IAAI,EAAG,OAAM,IAAI,MAAM,yCAAyC,GAAG,EAAE;AACvF,WAAO,GAAG,IAAI;AAAA,EAChB;AACA,QAAMP,OAAM,WAAW,QAAQ,WAAW,QAAQO,MAAI,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;AAC7E,QAAM,MAAM,GAAGA,MAAI,IAAI,QAAQ,GAAG,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AACzE,MAAI;AACF,UAAMH,WAAU,KAAK,KAAK,UAAU,EAAE,SAAS,GAAG,QAAQ,OAAO,GAAG,MAAM,CAAC,IAAI,IAAI;AACnF,UAAMF,QAAO,KAAKK,MAAI;AAAA,EACxB,UAAE;AACA,UAAMJ,IAAG,KAAK,EAAE,OAAO,KAAK,CAAC;AAAA,EAC/B;AACF;AAGO,SAAS,WAAW,OAAkB,SAA8B;AACzE,MAAI,UAAU;AACd,aAAW,MAAM,OAAO,KAAK,MAAM,MAAM,GAAG;AAC1C,QAAI,CAAC,QAAQ,IAAI,EAAE,GAAG;AACpB,aAAO,MAAM,OAAO,EAAE;AACtB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAWO,SAAS,aAAa,UAA0B;AACrD,MAAI,SAAS,SAAS,YAAY,EAAG,QAAO,SAAS,QAAQ,iBAAiB,aAAa;AAC3F,SAAO,GAAG,QAAQ;AACpB;;;ADjEA,eAAsB,MACpB,UACA,OACA,MACA,UACA,OAAwF,CAAC,GACnE;AACtB,QAAMK,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AACvC,QAAM,cAAc,KAAK,eAAe;AAExC,QAAM,YAAY,aAAa,QAAQ;AACvC,QAAM,QAAmB,KAAK,UAAU,EAAE,SAAS,GAAG,QAAQ,CAAC,EAAE,IAAI,MAAM,UAAU,SAAS;AAC9F,MAAI,YAAY;AAGhB,QAAM,cAAc,oBAAI,IAA4B;AACpD,QAAM,iBAA2B,CAAC;AAClC,aAAW,QAAQ,OAAO;AACxB,QAAI,CAACC,aAAW,KAAK,OAAO,GAAG;AAC7B,qBAAe,KAAK,GAAG,KAAK,OAAO,IAAI,KAAK,OAAO,gBAAgB,KAAK,OAAO,GAAG;AAClF;AAAA,IACF;AACA,UAAM,QAAQ,MAAMC,UAAS,KAAK,OAAO;AACzC,QAAI;AACF,gBAAU,KAAK;AAAA,IACjB,SAAS,KAAK;AACZ,qBAAe;AAAA,QACb,GAAG,KAAK,OAAO,IAAI,KAAK,OAAO,kBAC1B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MACvD;AACA;AAAA,IACF;AACA,UAAM,OAAO,OAAO,KAAK;AACzB,UAAM,SAAS,YAAY,IAAI,IAAI,KAAK,CAAC;AACzC,WAAO,KAAK,IAAI;AAChB,gBAAY,IAAI,MAAM,MAAM;AAAA,EAC9B;AACA,EAAAF,KAAI,YAAY,YAAY,IAAI,0BAA0B;AAG1D,QAAM,SAAwB,CAAC;AAC/B,mBAAiB,OAAO,YAAY,QAAQ,EAAE,EAAG,QAAO,KAAK,GAAG;AAChE,EAAAA,KAAI,WAAW,OAAO,MAAM,2BAA2B;AAEvD,QAAM,gBAAgB,oBAAI,IAAY;AACtC,QAAM,YAAsB,CAAC;AAC7B,MAAI,UAAU;AACd,MAAI,SAAS;AAEb,iBAAe,SAAS;AACtB,eAAS;AACP,YAAM,MAAM,OAAO,QAAQ;AAC3B,UAAI,CAAC,IAAK;AACV,YAAM,MAAM,IAAI;AAChB,UAAI,CAAC,OAAO,IAAI,WAAW,YAAa;AAExC,UAAI,OAA2B,MAAM,OAAO,IAAI,EAAE;AAClD,UAAI,MAAM;AACR;AAAA,MACF,OAAO;AACL,YAAI;AACF,gBAAM,QAAQ,MAAM,SAAS,SAAS,GAAG;AACzC,oBAAU,KAAK;AACf,iBAAO,OAAO,KAAK;AAAA,QACrB,QAAQ;AACN;AAAA,QACF;AACA,cAAM,OAAO,IAAI,EAAE,IAAI;AAAA,MACzB;AAEA,YAAM,OAAO,YAAY,IAAI,IAAI;AACjC,UAAI,CAAC,MAAM,OAAQ;AAEnB,oBAAc,IAAI,IAAI,EAAE;AACxB,iBAAW,QAAQ,MAAM;AACvB,cAAM,MAAM,QAAQ,KAAK,SAAS,KAAK,OAAO;AAC9C,cAAM,WAAW,KAAK,QAAQ,GAAG;AACjC,YAAI,UAAU,YAAY,SAAS,aAAa,IAAI,IAAI;AAGtD,oBAAU,KAAK,GAAG,GAAG,uBAAuB,SAAS,QAAQ,kBAAkB,IAAI,EAAE,EAAE;AACvF;AAAA,QACF;AACA,cAAM,gBAAgB,uBAAuB,GAAG,IAAI,MAAM;AAC1D,eAAO,MAAM,KAAK;AAAA,UAChB,SAAS,KAAK;AAAA,UACd,SAAS,KAAK;AAAA;AAAA;AAAA,UAGd,UAAU,KAAK;AAAA,UACf,WAAW,KAAK;AAAA,UAChB,QAAQ,IAAI,UAAU,KAAK;AAAA,UAC3B,OAAO,IAAI;AAAA,UACX,QAAQ,IAAI;AAAA,UACZ,OAAO,IAAI;AAAA,UACX,UAAU,IAAI;AAAA,UACd,gBAAgB;AAAA,UAChB,gBAAgB;AAAA,UAChB,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,WAAW;AAAA,UACX,YAAY,gBAAgB,CAAC,EAAE,KAAK,cAAc,CAAC,IAAI,CAAC;AAAA,UACxD,SAAS,CAAC,EAAE,MAAM,mBAAmB,KAAK,SAAS,KAAK,IAAI,GAAG,QAAQ,KAAK,CAAC;AAAA,UAC7E,aAAa,IAAI;AAAA,UACjB,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,UACrC,MAAM;AAAA;AAAA,UACN,UAAU,qBAAqB,SAAS,IAAI,SAAS,SAAS,IAAI,CAAC,EAAE;AAAA,UACrE,UAAU,SAAS;AAAA,QACrB,CAAC;AACD;AACA,QAAAA,KAAI,aAAa,GAAG,WAAM,IAAI,EAAE,EAAE;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,aAAa,OAAO,UAAU,CAAC,EAAE,GAAG,MAAM,CAAC;AAC3F,QAAM,SAAS,UAAU,IAAI;AAE7B,MAAI,CAAC,KAAK,SAAS;AACjB,eAAW,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAClD,UAAM,UAAU,WAAW,KAAK;AAChC,QAAI,UAAW,CAAAA,KAAI,YAAY,SAAS,gCAAgC,OAAO,SAAS,SAAS,EAAE;AAAA,EACrG;AAEA,SAAO;AAAA,IACL,SAAS,OAAO;AAAA,IAChB;AAAA,IACA;AAAA,IACA,iBAAiB,OAAO,OAAO,CAAC,MAAM,CAAC,cAAc,IAAI,EAAE,EAAE,CAAC;AAAA,IAC9D;AAAA,EACF;AACF;AAGA,eAAsB,WACpB,UACA,OACA,MACA,OAA+C,CAAC,GAC/B;AACjB,QAAMA,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AACvC,QAAM,YAAY,IAAI,IAAI,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;AAC9E,MAAI,QAAQ;AACZ,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACvD,UAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,QAAI,CAAC,QAAQ,CAAC,MAAM,SAAU;AAC9B,QAAI,CAAC,SAAS,QAAS,QAAO;AAC9B,QAAI;AACF,YAAM,SAAS,QAAQ,MAAM,UAAU,KAAK,IAAI;AAChD;AAAA,IACF,SAAS,KAAK;AACZ,MAAAA,KAAI,gBAAgB,GAAG,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,IAChF;AAAA,EACF;AACA,SAAO;AACT;AAUA,eAAsB,iBACpB,cACA,MACA,OAMI,CAAC,GAC8C;AACnD,QAAMA,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AACvC,QAAM,iBAAiB,KAAK,WAAW,IAAI,IAAI,KAAK,QAAQ,IAAI;AAChE,QAAM,MAAM,KAAK,MAAM,MAAME,UAAS,cAAc,MAAM,CAAC;AAM3D,QAAM,OAAO,oBAAI,IAAoB;AACrC,aAAW,SAAS,OAAO,OAAO,KAAK,OAAO,GAAG;AAC/C,QAAI,KAAK,YAAY,MAAM,aAAa,KAAK,SAAU;AACvD,QAAI,kBAAkB,CAAC,eAAe,IAAI,MAAM,OAAO,EAAG;AAC1D,QAAI,CAAC,MAAM,YAAY,CAAC,MAAM,OAAQ;AACtC,UAAM,UAAU,KAAK,IAAI,MAAM,OAAO;AACtC,QAAI,CAAC,WAAW,MAAM,OAAO,SAAS,QAAQ,OAAQ,MAAK,IAAI,MAAM,SAAS,MAAM,MAAM;AAAA,EAC5F;AAEA,MAAI,SAAS;AACb,QAAM,aAAuB,CAAC;AAC9B,aAAW,CAAC,IAAI,KAAK,KAAK,OAAO,QAAQ,IAAI,MAAM,GAAG;AACpD,QAAI,kBAAkB,CAAC,eAAe,IAAI,EAAE,EAAG;AAC/C,QAAI,MAAM,UAAU,MAAM,OAAO,KAAK,EAAG;AACzC,UAAM,YAAY,KAAK,IAAI,EAAE;AAC7B,QAAI,WAAW;AACb,YAAM,SAAS;AACf;AAAA,IACF,OAAO;AACL,iBAAW,KAAK,EAAE;AAAA,IACpB;AAAA,EACF;AAEA,QAAMC,WAAU,cAAc,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI;AACjE,EAAAH,KAAI,YAAY,MAAM,iCAAiC;AACvD,SAAO,EAAE,QAAQ,WAAW;AAC9B;AAEO,SAAS,sBAAsB,SAAwB,QAAQ,IAAY;AAChF,QAAM,QAAQ,QACX,MAAM,GAAG,KAAK,EACd,IAAI,CAAC,MAAM,OAAO,EAAE,EAAE,KAAK,EAAE,UAAU,MAAM,GAAG,EAAE,CAAC,MAAM,EAAE,UAAU,IAAI,MAAM,GAAG,EAAE,CAAC,EAAE;AAC1F,MAAI,QAAQ,SAAS,MAAO,OAAM,KAAK,kBAAa,QAAQ,SAAS,KAAK,OAAO;AACjF,SAAO,MAAM,KAAK,IAAI;AACxB;;;AEnOA,IAAM,aAAa,CAAC,MAClB,EAAE,QAAQ,YAAY,CAAC,OAAO,EAAE,KAAK,SAAS,KAAK,QAAQ,KAAK,QAAQ,KAAK,UAAU,KAAK,QAAQ,GAAG,CAAC,CAAE;AAYrG,SAAS,YAAY,QAA8B;AAKxD,QAAM,OAAO,OAAO,IAAI,CAAC,OAAO;AAAA,IAC9B,GAAG;AAAA,IACH,SAAS,WAAW,EAAE,OAAO;AAAA,IAC7B,SAAS,WAAW,EAAE,OAAO;AAAA,IAC7B,QAAQ,WAAW,EAAE,MAAM;AAAA,IAC3B,GAAI,EAAE,WACF;AAAA,MACE,UAAU;AAAA,QACR,GAAG,EAAE;AAAA,QACL,eAAe,WAAW,EAAE,SAAS,aAAa;AAAA,MACpD;AAAA,IACF,IACA,CAAC;AAAA,EACP,EAAE;AACF,QAAM,OAAO,KAAK,UAAU,IAAI,EAAE,QAAQ,QAAQ,MAAM;AACxD,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBA2GQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2MrB;;;AC5WA,SAAS,oBAAoB;AAC7B,SAAS,aAAa;AACtB,SAAS,YAAAI,kBAAgB;AAkClB,SAAS,gBAAyB,MAAsD;AAC7F,QAAMC,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AAEvC,SAAO,IAAI,QAAiB,CAAC,SAAS,WAAW;AAC/C,UAAM,SAAS,aAAa,OAAO,KAAK,QAAQ;AAC9C,UAAI,IAAI,WAAW,SAAS,IAAI,OAAO,KAAK,QAAQ,IAAI,IAAI,GAAG,GAAG;AAChE,YAAI;AACF,gBAAM,QAAQ,KAAK,OAAO,IAAI,IAAI,GAAG;AACrC,gBAAM,QAAQ,MAAMD,WAAS,MAAM,IAAI;AACvC,cAAI,UAAU,KAAK;AAAA,YACjB,gBAAgB,MAAM;AAAA,YACtB,iBAAiB;AAAA,YACjB,0BAA0B;AAAA,UAC5B,CAAC;AACD,cAAI,IAAI,KAAK;AAAA,QACf,QAAQ;AACN,cAAI,UAAU,KAAK,EAAE,gBAAgB,aAAa,CAAC;AACnD,cAAI,IAAI,6BAA6B;AAAA,QACvC;AACA;AAAA,MACF;AAEA,UAAI,IAAI,WAAW,UAAU,IAAI,QAAQ,OAAO,IAAI,KAAK,WAAW,IAAI,IAAI;AAC1E,YAAI,UAAU,KAAK,EAAE,gBAAgB,2BAA2B,CAAC;AACjE,YAAI,IAAI,KAAK,IAAI;AACjB;AAAA,MACF;AAEA,UAAI,IAAI,WAAW,UAAU,IAAI,QAAQ,UAAU;AACjD,cAAM,iBAAiB,IAAI,QAAQ,OAAO,UAAU,IAAI,QAAQ,IAAI,KAAK;AACzE,YAAI,IAAI,QAAQ,UAAU,IAAI,QAAQ,WAAW,gBAAgB;AAC/D,cAAI,UAAU,KAAK,EAAE,gBAAgB,aAAa,CAAC;AACnD,cAAI,IAAI,iDAAiD;AACzD;AAAA,QACF;AACA,YAAI,CAAC,IAAI,QAAQ,cAAc,GAAG,YAAY,EAAE,WAAW,kBAAkB,GAAG;AAC9E,cAAI,UAAU,KAAK,EAAE,gBAAgB,aAAa,CAAC;AACnD,cAAI,IAAI,8BAA8B;AACtC;AAAA,QACF;AACA,YAAI;AACF,gBAAM,SAAmB,CAAC;AAC1B,cAAI,QAAQ;AACZ,2BAAiB,KAAK,KAAK;AACzB,kBAAME,SAAQ;AACd,qBAASA,OAAM;AACf,gBAAI,QAAQ,KAAK,MAAM;AACrB,kBAAI,UAAU,KAAK,EAAE,gBAAgB,aAAa,CAAC;AACnD,kBAAI,IAAI,gCAAgC;AACxC;AAAA,YACF;AACA,mBAAO,KAAKA,MAAK;AAAA,UACnB;AACA,gBAAM,OAAgB,KAAK,MAAM,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM,CAAC;AACvE,gBAAM,SAAS,MAAM,KAAK,YAAY,IAAI;AAC1C,cAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,cAAI,IAAI,KAAK,UAAU,MAAM,CAAC;AAC9B,iBAAO,MAAM,MAAM,QAAQ,MAAM,CAAC;AAAA,QACpC,SAAS,KAAK;AACZ,gBAAMC,WAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,UAAAF,KAAI,mBAAmBE,QAAO,EAAE;AAChC,cAAI,UAAU,KAAK,EAAE,gBAAgB,aAAa,CAAC;AACnD,cAAI,IAAIA,QAAO;AAAA,QACjB;AACA;AAAA,MACF;AAEA,UAAI,UAAU,GAAG;AACjB,UAAI,IAAI;AAAA,IACV,CAAC;AAED,WAAO,GAAG,SAAS,MAAM;AACzB,WAAO,OAAO,KAAK,QAAQ,GAAG,aAAa,MAAM;AAC/C,YAAM,UAAU,OAAO,QAAQ;AAC/B,YAAM,OAAO,OAAO,YAAY,YAAY,UAAU,QAAQ,OAAO,KAAK;AAC1E,WAAK,QAAQ,oBAAoB,IAAI,GAAG;AACxC,UAAI,KAAK,SAAS,SAAS,QAAQ,aAAa,UAAU;AACxD,cAAM,QAAQ,CAAC,oBAAoB,IAAI,GAAG,GAAG,EAAE,OAAO,UAAU,UAAU,KAAK,CAAC,EAAE,MAAM;AAAA,MAC1F;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;;;AC7FA,eAAsB,UACpB,UACA,MACA,UACA,OAUI,CAAC,GACgB;AACrB,QAAMC,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AACvC,QAAM,eAAe,KAAK,OAAO,IAAI,IAAI,KAAK,IAAI,IAAI;AACtD,QAAM,YAAY,IAAI;AAAA,KACnB,KAAK,SAAS,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,KAAK,SAAS,KAAK,OAAO,GAAG,IAAI,CAAC;AAAA,EAC9E;AACA,QAAM,eAAe,oBAAI,IAAmD;AAE5E,QAAM,SAAuB,CAAC;AAC9B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,OAAO,GAAG;AACvD,QAAI,MAAM,aAAa,SAAS,MAAO,gBAAgB,CAAC,aAAa,IAAI,GAAG,EAAI;AAChF,QAAI,MAAM,WAAW,YAAY,CAAC,MAAM,eAAgB;AACxD,QAAI;AACF,YAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,YAAM,QAAQ,MAAM,SAAS,KAAK,MAAM,gBAAgB,MAAM,WAAW,EAAE,KAAK,CAAC;AACjF,UACG,MAAM,WAAW,YAAY,MAAM,WAAW,iBAC9C,MAAM,WAAW,WAAW,CAAC,MAAM,cAAc,SAAS,CAAC,MAAM,UAAU,QAC5E;AACF,YAAM,YAAY,MAAM,WAAW,WAAW,MAAM,gBAAgB,MAAM;AAC1E,YAAM,cAAc,MAAM,WACtB,oBAAoB,mBAAmB,OAAO,OAAO,MAAM,CAAC,CAAC,KAC7D;AACJ,UAAI,eAAe,MAAM,UAAU;AACjC,qBAAa,IAAI,aAAa;AAAA,UAC5B,MAAM,KAAK,SAAS;AAAA,UACpB,aAAa,KAAK,SAAS,iBAAiB,SAAS,eAAe;AAAA,QACtE,CAAC;AAAA,MACH;AACA,aAAO,KAAK;AAAA,QACV;AAAA,QACA,SAAS,MAAM;AAAA,QACf,SAAS,MAAM;AAAA,QACf,QAAQ,MAAM;AAAA,QACd,gBAAgB,MAAM;AAAA,QACtB;AAAA,QACA,OAAO,MAAM;AAAA,QACb,QAAQ,MAAM;AAAA,QACd,GAAI,MAAM,WAAW,eACjB;AAAA,UACE,MAAM;AAAA,UACN,aAAa,MAAM,QAAQ,IAAI,CAAC,QAAQ,UAAU,OAAO,QAAQ,SAAS,KAAK,EAAE;AAAA,UACjF,KAAK,MAAM;AAAA,QACb,IACA,EAAE,MAAM,aAAsB;AAAA,QAClC,GAAI,eAAe,MAAM,YAAY,KAAK,SAAS,eAAe,KAAK,SAAS,eAC5E;AAAA,UACE,UAAU;AAAA,YACR,MAAM,KAAK,SAAS;AAAA,YACpB,eAAe,KAAK,SAAS;AAAA,YAC7B,WAAW;AAAA,YACX,OAAO,KAAK,SAAS;AAAA,YACrB,QAAQ,KAAK,SAAS;AAAA,UACxB;AAAA,QACF,IACA,CAAC;AAAA,MACP,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,MAAAA,KAAI,mCAAmC,GAAG,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,IACnG;AAAA,EACF;AAEA,MAAI,OAAO,WAAW,EAAG,QAAO,EAAE,UAAU,GAAG,SAAS,EAAE;AAE1D,QAAM,OAAO,YAAY,MAAM;AAC/B,QAAM,QAAQ,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AAEnD,SAAO,gBAA4B;AAAA,IACjC;AAAA,IACA,MAAM,KAAK;AAAA,IACX,MAAM,KAAK;AAAA,IACX,YAAYA;AAAA,IACZ,QAAQ;AAAA,IACR,SAAS,CAAC,QAAQ;AAChB,YAAM,OAAO,EAAE,KAAK,MAAM,OAAO,IAAI,CAAC,UAAU,MAAM,GAAG,EAAE;AAC3D,UAAI,KAAK,SAAS;AAChB,aAAK,QAAQ,IAAI;AAAA,MACnB,OAAO;AACL,QAAAA,KAAI;AAAA,IAAO,OAAO,MAAM,iCAAiC,GAAG,EAAE;AAC9D,QAAAA,KAAI;AAAA,CAAmD;AAAA,MACzD;AAAA,IACF;AAAA,IACA,aAAa,OAAO,SAAS;AAC3B,YAAM,EAAE,WAAW,IAAI;AAEvB,UAAI,WAAW;AACf,iBAAW,EAAE,KAAK,MAAM,KAAK,YAAY;AACvC,cAAM,QAAQ,MAAM,IAAI,GAAG;AAC3B,cAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,YAAI,CAAC,SAAS,CAAC,OAAO,eAAgB;AACtC,YAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,KAAK,SAAS,MAAM,UAAU,OAAQ;AAE9E,YAAI,MAAM,SAAS,aAAa;AAC9B,gBAAM,OAAO,UAAU,IAAI,GAAG;AAC9B,gBAAM,QAAQ,MAAM,SAAS,KAAK,MAAM,gBAAgB,MAAM,WAAW,EAAE,KAAK,CAAC;AACjF,cAAI,MAAM,WAAW,cAAc;AACjC,kBAAM,IAAI,MAAM,aAAa,GAAG,gCAAgC;AAAA,UAClE;AACA,iBAAO,MAAM,KAAK;AAAA,YAChB,QAAQ;AAAA,YACR,UAAU,MAAM;AAAA,YAChB,gBAAgB;AAAA,YAChB,WAAW,MAAM,QAAQ,CAAC,GAAG,OAAO;AAAA,YACpC,YAAY,MAAM;AAAA,YAClB,UAAU,SAAS;AAAA,YACnB,kBAAkB,MAAM,WACpB;AAAA,cACE,GAAG,MAAM;AAAA,cACT,CAAC,SAAS,EAAE,GAAG;AAAA,gBACb,GAAG,MAAM,iBAAiB,SAAS,EAAE;AAAA,gBACrC,GAAG,MAAM;AAAA,cACX;AAAA,YACF,IACA,MAAM;AAAA,UACZ,CAAC;AACD;AACA,UAAAA,KAAI,cAAc,GAAG,WAAM,MAAM,QAAQ,MAAM,iBAAiB;AAChE;AAAA,QACF;AAIA,cAAM,EAAE,UAAU,WAAW,SAAS,IAAI,MAAM,uBAAuB,QAAQ;AAAA,UAC7E,MAAM;AAAA,UACN;AAAA,UACA,SAAS,MAAM,OAAO;AAAA,UACtB,MAAM;AAAA,QACR;AAEA,eAAO,MAAM,KAAK;AAAA,UAChB,QAAQ;AAAA,UACR;AAAA,UACA,gBAAgB;AAAA,UAChB,WAAW,aAAa,MAAM,UAAU,KAAK,KAAK;AAAA,UAClD,YAAY,CAAC;AAAA,UACb,UAAU,SAAS;AAAA,UACnB,kBAAkB,WACd;AAAA,YACE,GAAG,MAAM;AAAA,YACT,CAAC,SAAS,EAAE,GAAG;AAAA,cACb,GAAG,MAAM,iBAAiB,SAAS,EAAE;AAAA,cACrC,GAAG;AAAA,YACL;AAAA,UACF,IACA,MAAM;AAAA,QACZ,CAAC;AACD;AACA,QAAAA,KAAI,aAAa,GAAG,qBAAgB,QAAQ,CAAC,EAAE;AAAA,MACjD;AAEA,YAAM,SAAS,UAAU,IAAI;AAC7B,aAAO,EAAE,UAAU,SAAS,OAAO,SAAS,SAAS;AAAA,IACvD;AAAA,EACF,CAAC;AACH;;;ACjMA,SAAS,SAAS,YAAAC,YAAU,aAAAC,kBAAiB;AAC7C,SAAS,cAAAC,oBAAkB;AAC3B,OAAOC,YAAU;AAIV,SAAS,QAAQ,KAAuD;AAC7E,MAAI,IAAI,SAAS,GAAI,QAAO;AAC5B,QAAM,QAAQ,IAAI,aAAa,CAAC,MAAM,cAAc,IAAI,aAAa,CAAC,MAAM;AAC5E,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,IAAI,SAAS,SAAS,IAAI,EAAE,MAAM,OAAQ,QAAO;AACrD,SAAO,EAAE,OAAO,IAAI,aAAa,EAAE,GAAG,QAAQ,IAAI,aAAa,EAAE,EAAE;AACrE;AAGO,SAAS,QAAQ,OAAuB;AAC7C,SAAO,MACJ,QAAQ,WAAW,EAAE,EACrB,QAAQ,kBAAkB,GAAG,EAC7B,QAAQ,YAAY,EAAE,EACtB,YAAY;AACjB;AAUA,eAAe,KAAK,KAAa,SAAsC;AACrE,QAAM,MAAgB,CAAC;AACvB,aAAW,SAAS,MAAM,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAC/D,UAAM,OAAOA,OAAK,KAAK,KAAK,MAAM,IAAI;AACtC,QAAI,QAAQ,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,EAAG;AAC3C,QAAI,MAAM,YAAY,EAAG,KAAI,KAAK,GAAI,MAAM,KAAK,MAAM,OAAO,CAAE;AAAA,aACvD,MAAM,KAAK,YAAY,EAAE,SAAS,MAAM,EAAG,KAAI,KAAK,IAAI;AAAA,EACnE;AACA,SAAO;AACT;AAUA,eAAsB,WACpB,MACA,OAA+B,CAAC,GACwB;AACxD,QAAM,UAAU,KAAK,WAAW,CAAC;AACjC,QAAM,QAAQ,MAAM,KAAK,MAAM,OAAO;AACtC,QAAM,SAAyB,CAAC;AAChC,QAAM,UAAoB,CAAC;AAC3B,QAAM,OAAO,oBAAI,IAAoB;AAErC,aAAW,QAAQ,MAAM,KAAK,GAAG;AAC/B,UAAM,OAAO,QAAQ,MAAMH,WAAS,IAAI,CAAC;AACzC,QAAI,CAAC,MAAM;AACT,cAAQ,KAAK,GAAG,IAAI,uBAAuB;AAC3C;AAAA,IACF;AACA,UAAM,MAAMG,OAAK,SAAS,MAAM,IAAI;AACpC,UAAM,WAAWA,OAAK,QAAQ,GAAG,MAAM,MAAM,KAAKA,OAAK,QAAQ,GAAG;AAClE,QAAI,KAAK,QAAQA,OAAK,SAAS,GAAG,CAAC;AAGnC,QAAI,KAAK,IAAI,EAAE,GAAG;AAChB,YAAM,IAAI,KAAK,IAAI,EAAE,IAAK;AAC1B,WAAK,IAAI,IAAI,CAAC;AACd,WAAK,GAAG,QAAQ,SAAS,QAAQ,UAAU,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,QAAQ,OAAO,EAAE;AAAA,IAC5E,OAAO;AACL,WAAK,IAAI,IAAI,CAAC;AAAA,IAChB;AAEA,WAAO,KAAK,EAAE,IAAI,UAAU,MAAM,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO,CAAC;AAAA,EACjF;AAEA,SAAO,EAAE,QAAQ,QAAQ;AAC3B;AAEO,SAAS,cACd,MACA,SACA,WACA,QACA,SACU;AACV,QAAM,UAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM;AAC1D,QAAM,aAAa,QAAQ,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI;AAExE,QAAM,SAA6B,CAAC;AACpC,aAAW,SAAS,SAAS;AAC3B,WAAO,MAAM,EAAE,IAAI;AAAA,MACjB,QAAQ;AAAA,MACR,eAAe,CAAC;AAAA,MAChB,UAAU,MAAM,YAAY;AAAA,MAC5B,MAAM,MAAM;AAAA,MACZ,MAAM,CAAC;AAAA,MACP,QAAQ,CAAC;AAAA,MACT,gBAAgB,CAAC;AAAA,MACjB,GAAI,cAAc,QACd,EAAE,OAAO,MAAM,OAAO,QAAQ,MAAM,OAAO,IAC3C,MAAM,UAAU,MAAM,UAAU,MAAM,UAAU,aAC9C,EAAE,MAAM,MAAM,MAAM,IACpB,CAAC;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AAAA,IACV,QAAQ;AAAA,MACN,CAAC,OAAO,GAAG;AAAA,QACT;AAAA,QACA,MAAM;AAAA;AAAA;AAAA,QAGN,cAAc;AAAA,QACd,cAAc;AAAA,QACd,cAAc;AAAA,QACd,aAAa,CAAC;AAAA,QACd,SAAS,CAAC;AAAA,QACV;AAAA,QACA,MAAM,CAAC,IAAI;AAAA,QACX,iBAAiB,CAAC;AAAA,MACpB;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,KAAK,QAA0B;AACtC,QAAM,SAAS,oBAAI,IAAoB;AACvC,aAAW,KAAK,OAAQ,QAAO,IAAI,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,CAAC;AAC9D,SAAO,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK;AACtE;AAEA,eAAsB,kBAAkB,QAAgB,UAAmC;AACzF,MAAID,aAAW,MAAM,GAAG;AACtB,UAAM,IAAI,MAAM,GAAG,MAAM,oEAA+D;AAAA,EAC1F;AACA,QAAMD,WAAU,QAAQ,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AAClE;;;ACnJA,SAAS,YAAAG,kBAAgB;AACzB,SAAS,cAAAC,oBAAkB;AAC3B,OAAOC,YAAU;AA0BV,SAAS,gBAAgB,UAAkB,UAA0B;AAG1E,SAAO,GAAG,mBAAmB,QAAQ,CAAC,IAAI,mBAAmB,QAAQ,CAAC;AACxE;AAEA,eAAsB,WACpB,WACA,OAA0B,CAAC,GACL;AACtB,QAAM,UAAU,oBAAI,IAAY;AAChC,aAAW,KAAK,WAAW;AACzB,QAAI,CAACC,aAAW,CAAC,EAAG,OAAM,IAAI,MAAM,6BAA6B,CAAC,EAAE;AACpE,QAAI;AACJ,QAAI;AACF,eAAS,UAAU,KAAK,MAAM,MAAMC,WAAS,GAAG,MAAM,CAAC,CAAC;AAAA,IAC1D,QAAQ;AACN,YAAM,IAAI,MAAM,gCAAgC,CAAC,EAAE;AAAA,IACrD;AACA,eAAW,SAAS,OAAO,OAAO,OAAO,OAAO,GAAG;AACjD,UAAI,KAAK,YAAY,MAAM,aAAa,KAAK,SAAU;AACvD,YAAM,MAAM,CAAC,OAAsB;AACjC,YAAI,GAAI,SAAQ,IAAI,KAAK,UAAU,gBAAgB,MAAM,UAAU,EAAE,IAAI,EAAE;AAAA,MAC7E;AACA,UAAI,MAAM,QAAQ;AAClB,UAAI,MAAM,cAAc;AACxB,UAAI,MAAM,KAAK;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAYA,eAAsB,YACpB,UACA,SACA,OAA+C,CAAC,GACD;AAC/C,QAAMC,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AACvC,QAAM,MAAqB,CAAC;AAC5B,mBAAiB,OAAO,YAAY,QAAQ,EAAE,EAAG,KAAI,KAAK,GAAG;AAC7D,EAAAA,KAAI,aAAa,IAAI,MAAM,2BAA2B;AAEtD,QAAM,UAAU,IACb;AAAA,IAAO,CAAC,MACP,CAAC,QAAQ,IAAI,EAAE,EAAE,KACjB,CAAC,QAAQ,IAAI,gBAAgB,SAAS,IAAI,EAAE,EAAE,CAAC,KAC/C,EAAE,WAAW,eACb,EAAE;AAAA,EACJ,EACC,IAAI,CAAC,OAAO;AAAA,IACX,IAAI,EAAE;AAAA,IACN,QAAQ,EAAE,UAAU;AAAA,IACpB,OAAO,EAAE;AAAA,IACT,QAAQ,EAAE;AAAA,IACV,WAAW,EAAE;AAAA,IACb,YAAY,EAAE;AAAA,IACd,MAAM,EAAE,QAAQ,CAAC;AAAA,EACnB,EAAE,EAED,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,cAAc,EAAE,SAAS,CAAC;AAExD,SAAO,EAAE,SAAS,OAAO,IAAI,OAAO;AACtC;AAOA,IAAM,4BAA4B;AAUlC,SAAS,oBAAoB,QAAgB,UAAmC;AAC9E,QAAM,IAAI,OAAO,YAAY;AAC7B,aAAW,WAAW,OAAO,KAAK,SAAS,MAAM,GAAG;AAClD,UAAM,QAAQ,SAAS,OAAO,OAAO;AACrC,eAAW,OAAO,CAAC,MAAM,cAAc,MAAM,YAAY,GAAG;AAC1D,YAAM,OAAO,KAAK,KAAK,EAAE,YAAY;AACrC,UAAI,QAAQ,KAAK,UAAU,6BAA6B,EAAE,SAAS,IAAI,EAAG,QAAO;AAAA,IACnF;AAAA,EACF;AACA,SAAO;AACT;AAuCA,eAAsB,qBACpB,iBACA,wBACA,YAC4B;AAC5B,QAAM,MAAMC,OAAK,QAAQ,eAAe;AACxC,QAAM,uBAAuB;AAAA,IAC3B,GAAG,oBAAI,IAAI;AAAA,MACT,GAAG;AAAA,MACH,GAAG,WAAW,IAAI,CAAC,MAAMA,OAAK,KAAKA,OAAK,QAAQA,OAAK,QAAQ,CAAC,CAAC,GAAG,yBAAyB,CAAC;AAAA,IAC9F,CAAC;AAAA,EACH;AACA,QAAM,WAA8B,CAAC;AACrC,aAAW,uBAAuB,sBAAsB;AACtD,QAAIA,OAAK,QAAQ,mBAAmB,MAAM,IAAK;AAC/C,QAAI,CAACC,aAAW,mBAAmB,EAAG;AACtC,QAAI;AACF,YAAM,EAAE,SAAS,IAAI,MAAM,aAAa,mBAAmB;AAC3D,eAAS,KAAK,EAAE,OAAOD,OAAK,SAASA,OAAK,QAAQ,mBAAmB,CAAC,GAAG,SAAS,CAAC;AAAA,IACrF,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAgCO,SAAS,oBACd,SACA,UACA,WAA8B,CAAC,GACjB;AACd,QAAM,UAAU,oBAAI,IAAsB;AAC1C,QAAM,YAAY,oBAAI,IAAsB;AAC5C,QAAM,YAAsB,CAAC;AAC7B,QAAM,cAAc,OAAO,KAAK,SAAS,MAAM;AAC/C,aAAW,WAAW,YAAa,SAAQ,IAAI,SAAS,CAAC,CAAC;AAE1D,aAAW,KAAK,SAAS;AACvB,UAAM,MAAM,oBAAoB,EAAE,QAAQ,QAAQ;AAClD,QAAI,KAAK;AACP,cAAQ,IAAI,GAAG,EAAG,KAAK,CAAC;AACxB;AAAA,IACF;AAEA,UAAM,UAAU,SAAS,KAAK,CAAC,MAAM,oBAAoB,EAAE,QAAQ,EAAE,QAAQ,CAAC;AAC9E,QAAI,SAAS;AACX,YAAM,MAAM,GAAG,QAAQ,KAAK,KAAK,oBAAoB,EAAE,QAAQ,QAAQ,QAAQ,CAAC;AAChF,YAAM,OAAO,UAAU,IAAI,GAAG,KAAK,CAAC;AACpC,WAAK,KAAK,CAAC;AACX,gBAAU,IAAI,KAAK,IAAI;AACvB;AAAA,IACF;AAKA,QAAI,YAAY,UAAU,KAAK,YAAY,CAAC,EAAG,SAAQ,IAAI,YAAY,CAAC,CAAC,EAAG,KAAK,CAAC;AAAA,QAC7E,WAAU,KAAK,CAAC;AAAA,EACvB;AACA,aAAW,CAAC,SAAS,IAAI,KAAK,CAAC,GAAG,OAAO,EAAG,KAAI,CAAC,KAAK,OAAQ,SAAQ,OAAO,OAAO;AACpF,SAAO,EAAE,SAAS,WAAW,UAAU;AACzC;AAMA,IAAM,cAAc,oBAAI,IAAI;AAAA,EAC1B;AAAA,EAAK;AAAA,EAAM;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAS;AAAA,EAAU;AAAA,EAAY;AAAA,EAAU;AAAA,EAAQ;AAAA,EACjF;AAAA,EAAM;AAAA,EAAM;AAAA,EAAM;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAS;AAAA,EAAO;AAAA,EAAS;AAAA,EAAQ;AAAA,EACxE;AAAA,EAAe;AAAA,EAAc;AAAA,EAAM;AAAA,EAAW;AAAA,EAAS;AAAA,EAAe;AAAA,EACtE;AAAA,EAAa;AAAA,EAAW;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAO;AAAA,EAAY;AAAA,EAC1E;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAW;AAAA,EAAc;AAAA,EAAU;AAAA,EAAS;AACvE,CAAC;AAEM,SAAS,aAAa,QAAgB,OAA4B;AAIvE,QAAM,QAAQ,OAAO,QAAQ,GAAG;AAChC,QAAM,UAAU,SAAS,KAAK,QAAQ,OAAO,SAAS,KAAK,OAAO,MAAM,QAAQ,CAAC,IAAI;AAErF,QAAM,QAAQ,QACX,YAAY,EACZ,QAAQ,gBAAgB,GAAG,EAC3B,MAAM,KAAK,EACX,OAAO,CAAC,MAAM,EAAE,SAAS,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC,EACjD,MAAM,GAAG,CAAC;AAEb,MAAI,OAAO,MAAM,KAAK,GAAG,KAAK;AAC9B,MAAI,KAAK;AACT,MAAI,IAAI;AACR,SAAO,MAAM,IAAI,EAAE,EAAG,MAAK,GAAG,IAAI,IAAI,GAAG;AACzC,QAAM,IAAI,EAAE;AACZ,SAAO;AACT;AAQO,IAAM,qBAAqB;AAgBlC,eAAsB,UACpB,UACA,WACA,UACA,OAA+C,CAAC,GACH;AAC7C,QAAME,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AACvC,MAAI,SAAS;AACb,MAAI,SAAS;AAEb,aAAW,EAAE,IAAI,OAAO,KAAK,WAAW;AACtC,UAAM,WAAW,SAAS,IAAI,EAAE,KAAK,CAAC,GAAG;AAAA,MACvC,CAAC,MAAM,MAAM,oBAAoB,MAAM,uBAAuB,MAAM;AAAA,IACtE;AACA,UAAM,cAAc,aAAa,WAAW,WAAW,aAAa,MAAM;AAG1E,UAAM,OAAO,CAAC,GAAG,QAAQ,MAAM,GAAG,EAAE,GAAG,WAAW;AAClD,QAAI,CAAC,SAAS,QAAS,QAAO,EAAE,QAAQ,OAAO;AAC/C,QAAI;AACF,YAAM,SAAS,QAAQ,IAAI,IAAI;AAC/B;AAAA,IACF,SAAS,KAAK;AACZ;AACA,MAAAA,KAAI,gBAAgB,EAAE,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,IAC/E;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,OAAO;AAC1B;;;ACvVA,SAAS,SAAAC,QAAO,YAAAC,YAAU,UAAAC,SAAQ,MAAAC,KAAI,aAAAC,kBAAiB;AACvD,SAAS,cAAAC,oBAAkB;AAC3B,OAAOC,YAAU;AACjB,SAAS,KAAAC,UAAS;AAOX,IAAM,yBAAyBA,GACnC,OAAO;AAAA,EACN,IAAIA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAEpB,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAE1B,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,UAAUA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,UAAU;AAAA;AAAA,EAE9C,SAASA,GAAE,OAAO,EAAE,SAAS;AAC/B,CAAC,EACA,OAAO;AAEH,IAAM,kBAAkBA,GAC5B,OAAO;AAAA,EACN,SAASA,GAAE,QAAQ,CAAC;AAAA,EACpB,UAAUA,GAAE,MAAM,sBAAsB,EAAE,QAAQ,CAAC,CAAC;AACtD,CAAC,EACA,OAAO;AAWH,SAAS,eAAe,KAAyB;AACtD,QAAM,SAAS,gBAAgB,UAAU,GAAG;AAC5C,MAAI,OAAO,QAAS,QAAO,OAAO;AAClC,QAAM,IAAI;AAAA,IACR;AAAA,EAAuC,OAAO,MAAM,OACjD,MAAM,GAAG,CAAC,EACV,IAAI,CAAC,MAAM,KAAK,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAChD,KAAK,IAAI,CAAC;AAAA,EACf;AACF;AAEA,eAAsB,cAAc,eAA2C;AAC7E,MAAI,CAACF,aAAW,aAAa,EAAG,QAAO,EAAE,SAAS,GAAG,UAAU,CAAC,EAAE;AAClE,MAAI;AACJ,MAAI;AACF,UAAM,KAAK,MAAM,MAAMJ,WAAS,eAAe,MAAM,CAAC;AAAA,EACxD,SAAS,KAAK;AACZ,UAAM,IAAI;AAAA,MACR,wBAAwB,aAAa;AAAA,EAChC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACvD;AAAA,EACF;AACA,SAAO,eAAe,GAAG;AAC3B;AAGA,eAAsB,cAAc,eAAuB,IAA8B;AACvF,QAAM,SAAoB;AAAA,IACxB,SAAS;AAAA,IACT,UAAU,CAAC,GAAG,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC;AAAA,EACpE;AACA,QAAMD,OAAMM,OAAK,QAAQA,OAAK,QAAQ,aAAa,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;AAC1E,QAAM,MAAM,GAAG,aAAa,IAAI,QAAQ,GAAG,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAClF,MAAI;AACF,UAAMF,WAAU,KAAK,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAC3D,UAAMF,QAAO,KAAK,aAAa;AAAA,EACjC,UAAE;AACA,UAAMC,IAAG,KAAK,EAAE,OAAO,KAAK,CAAC;AAAA,EAC/B;AACF;AAGO,SAAS,eAAe,KAAa,UAA0B;AACpE,SAAOG,OAAK,SAAS,KAAK,QAAQ,EAAE,MAAMA,OAAK,GAAG,EAAE,KAAK,GAAG;AAC9D;AAGO,SAAS,eACd,KACA,SAC4C;AAC5C,SAAO;AAAA,IACL,cAAcA,OAAK,QAAQ,KAAK,QAAQ,SAAS,MAAM,GAAG,EAAE,KAAKA,OAAK,GAAG,CAAC;AAAA,IAC1E,UAAUA,OAAK,QAAQ,KAAK,QAAQ,KAAK,MAAM,GAAG,EAAE,KAAKA,OAAK,GAAG,CAAC;AAAA,EACpE;AACF;AAwBO,SAAS,kBAAkB,IAAe,KAAoC;AACnF,QAAM,cAAqC,CAAC;AAE5C,QAAM,WAAW,oBAAI,IAAoB;AACzC,QAAM,aAAa,oBAAI,IAAsB;AAC7C,QAAM,iBAAiB,oBAAI,IAAsB;AAEjD,aAAW,WAAW,GAAG,UAAU;AACjC,aAAS,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,EAAE,KAAK,KAAK,CAAC;AAE5D,UAAM,EAAE,cAAc,SAAS,IAAI,eAAe,KAAK,OAAO;AAC9D,eAAW,IAAI,UAAU,CAAC,GAAI,WAAW,IAAI,QAAQ,KAAK,CAAC,GAAI,QAAQ,EAAE,CAAC;AAC1E,mBAAe,IAAI,cAAc,CAAC,GAAI,eAAe,IAAI,YAAY,KAAK,CAAC,GAAI,QAAQ,EAAE,CAAC;AAE1F,QAAIA,OAAK,WAAW,QAAQ,QAAQ,KAAKA,OAAK,WAAW,QAAQ,IAAI,GAAG;AACtE,kBAAY,KAAK;AAAA,QACf,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,SACE,YAAY,QAAQ,EAAE;AAAA,MAE1B,CAAC;AAAA,IACH;AACA,QAAI,CAACD,aAAW,YAAY,GAAG;AAC7B,kBAAY,KAAK;AAAA,QACf,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,SAAS,YAAY,QAAQ,EAAE,yBAAyB,YAAY;AAAA,MACtE,CAAC;AAAA,IACH;AACA,QAAI,CAACA,aAAW,QAAQ,GAAG;AACzB,kBAAY,KAAK;AAAA,QACf,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,SAAS,YAAY,QAAQ,EAAE,yBAAyB,QAAQ;AAAA,MAClE,CAAC;AAAA,IACH;AAAA,EACF;AAEA,aAAW,CAAC,IAAI,KAAK,KAAK,UAAU;AAClC,QAAI,QAAQ,GAAG;AACb,kBAAY,KAAK;AAAA,QACf,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,SAAS,eAAe,EAAE,mBAAmB,KAAK;AAAA,MACpD,CAAC;AAAA,IACH;AAAA,EACF;AACA,aAAW,CAAC,UAAU,GAAG,KAAK,YAAY;AACxC,QAAI,IAAI,SAAS,GAAG;AAClB,kBAAY,KAAK;AAAA,QACf,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC,oCAAoC,QAAQ;AAAA,MACxE,CAAC;AAAA,IACH;AAAA,EACF;AACA,aAAW,CAAC,cAAc,GAAG,KAAK,gBAAgB;AAChD,QAAI,IAAI,SAAS,GAAG;AAClB,kBAAY,KAAK;AAAA,QACf,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,SACE,GAAG,IAAI,KAAK,IAAI,CAAC,mBAAmB,YAAY;AAAA,MAEpD,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,YAAY,IAAI,IAAI,GAAG,SAAS,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;AAC5D,MAAI,UAAU,OAAO,GAAG;AACtB,gBAAY,KAAK;AAAA,MACf,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,SACE,gDAAgD,CAAC,GAAG,SAAS,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC;AAAA,IAEpF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;;;ACxKA,eAAsB,gBAAgB,IAAe,KAAuC;AAC1F,QAAM,YAAsB,CAAC;AAC7B,QAAM,YAAoC,CAAC;AAC3C,QAAM,UAAU,oBAAI,IAAY;AAEhC,aAAW,WAAW,GAAG,UAAU;AACjC,UAAM,EAAE,SAAS,IAAI,eAAe,KAAK,OAAO;AAChD,cAAU,KAAK,QAAQ;AACvB,QAAI;AACJ,QAAI;AACF,sBAAgB,MAAM,WAAW,CAAC,QAAQ,GAAG,EAAE,SAAS,KAAK,CAAC;AAAA,IAChE,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,YAAY,QAAQ,EAAE,6BACjB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MACvD;AAAA,IACF;AACA,cAAU,QAAQ,EAAE,IAAI,cAAc;AACtC,eAAW,MAAM,cAAe,SAAQ,IAAI,EAAE;AAAA,EAChD;AAEA,SAAO,EAAE,SAAS,WAAW,UAAU;AACzC;AAEA,SAAS,mBAA8C;AACrD,SAAO;AAAA,IACL,IAAI;AAAA,IAAG,SAAS;AAAA,IAAG,WAAW;AAAA,IAAG,OAAO;AAAA,IAAG,UAAU;AAAA,IAAG,aAAa;AAAA,IACrE,aAAa;AAAA,IAAG,SAAS;AAAA,IAAG,QAAQ;AAAA,EACtC;AACF;AAsCA,eAAsB,gBAAgB,IAAe,KAA6C;AAChG,QAAM,cAAc,kBAAkB,IAAI,GAAG;AAC7C,QAAM,WAAqC,CAAC;AAC5C,QAAM,gBAAgB,iBAAiB;AACvC,QAAM,cAAwC,EAAE,aAAa,GAAG,KAAK,GAAG,MAAM,EAAE;AAEhF,aAAW,WAAW,GAAG,UAAU;AACjC,UAAM,EAAE,cAAc,SAAS,IAAI,eAAe,KAAK,OAAO;AAC9D,UAAM,OAAO;AAAA,MACX,IAAI,QAAQ;AAAA,MACZ,UAAU,QAAQ;AAAA,MAClB,SAAS,QAAQ,WAAW;AAAA,MAC5B,UAAU;AAAA,MACV,MAAM;AAAA,IACR;AACA,QAAI;AACF,YAAM,SAAS,MAAM,aAAa,YAAY;AAC9C,YAAM,QAAQ,MAAM,aAAa,MAAM;AACvC,YAAM,YAAY,CAAC,GAAG,IAAI;AAAA,QACxB,OAAO,OAAO,OAAO,SAAS,MAAM,EAAE;AAAA,UACpC,CAAC,UAAU,MAAM,YAAY,OAAO,SAAS;AAAA,QAC/C;AAAA,MACF,CAAC,EAAE,KAAK;AACR,UAAI,CAAC,UAAU,OAAQ,WAAU,KAAK,OAAO,SAAS,QAAQ;AAC9D,YAAM,OAAO,MAAM,SAAS,QAAQ;AACpC,+BAAyB,MAAM,KAAK;AACpC,YAAM,OAAO,MAAM,UAAU,OAAO,IAAI;AACxC,YAAM,UAAU,UAAU,IAAI;AAC9B,YAAM,QAAQ,YAAY,IAAI;AAC9B,iBAAW,SAAS,OAAO,KAAK,OAAO,GAAkB;AACvD,sBAAc,KAAK,KAAK,QAAQ,KAAK;AAAA,MACvC;AACA,iBAAW,QAAQ,OAAO,KAAK,KAAK,GAAiB;AACnD,oBAAY,IAAI,KAAK,YAAY,IAAI,KAAK,MAAM,MAAM,IAAI,KAAK;AAAA,MACjE;AACA,eAAS,KAAK;AAAA,QACZ,GAAG;AAAA,QACH,UAAU,UAAU,WAAW,IAAI,UAAU,CAAC,IAAK,QAAQ;AAAA,QAC3D;AAAA,QACA,SAAS,OAAO,KAAK,KAAK,OAAO,EAAE;AAAA,QACnC;AAAA,QACA,aAAa;AAAA,QACb,OAAO;AAAA,MACT,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,eAAS,KAAK;AAAA,QACZ,GAAG;AAAA,QACH,WAAW,CAAC,QAAQ,QAAQ;AAAA,QAC5B,SAAS;AAAA,QACT,SAAS,iBAAiB;AAAA,QAC1B,aAAa,EAAE,aAAa,GAAG,KAAK,GAAG,MAAM,EAAE;AAAA,QAC/C,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,MACxD,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,SAAS;AACb,MAAI;AACF,cAAU,MAAM,gBAAgB,IAAI,GAAG,GAAG,QAAQ;AAAA,EACpD,QAAQ;AAAA,EAGR;AAEA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,CAAC,YAAY,KAAK,CAAC,MAAM,EAAE,UAAU,OAAO,KAAK,SAAS,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK;AAAA,IACrF;AAAA,IACA;AAAA,IACA,QAAQ,EAAE,SAAS,eAAe,aAAa,aAAa,OAAO;AAAA,IACnE;AAAA,EACF;AACF;;;AC1KA,SAAS,cAAAG,oBAAkB;AAC3B,SAAS,YAAAC,YAAU,WAAAC,UAAS,MAAAC,WAAU;AACtC,OAAOC,YAAU;AA+DjB,eAAsB,cACpB,MACA,UACA,UAA8B,CAAC,GACH;AAC5B,MAAI,QAAQ,SAAS,CAACC,aAAW,QAAQ,GAAG;AAC1C,UAAM,IAAI,MAAM,qDAAqDC,OAAK,QAAQ,QAAQ,CAAC,EAAE;AAAA,EAC/F;AACA,QAAM,aAAaA,OAAK,QAAQA,OAAK,QAAQ,QAAQ,GAAG,cAAc,OAAO;AAC7E,QAAM,aAAaA,OAAK,QAAQ,aAAa,QAAQ,CAAC;AACtD,QAAM,aAAa,IAAI;AAAA,IACrB,OAAO,OAAO,KAAK,OAAO,EAAE,QAAQ,CAAC,UAAU,MAAM,QAAQ,IAAI,CAAC,WAAW,OAAO,MAAM,CAAC;AAAA,EAC7F;AAEA,MAAI,UAAU,MAAM,oBAAoB,YAAY,UAAU;AAC9D,MAAI,eAAe,MAAM,uBAAuB,UAAU;AAC1D,QAAM,UAAU,EAAE,cAAc,GAAG,mBAAmB,GAAG,sBAAsB,MAAM;AAErF,MAAI,QAAQ,OAAO;AACjB,UAAM,QAAQ,oBAAI,IAAI;AAAA,MACpB,GAAG,QAAQ;AAAA,MACX,GAAG,QAAQ,QAAQ,IAAI,CAAC,UAAU,MAAM,IAAI;AAAA,IAC9C,CAAC;AACD,eAAW,QAAQ,OAAO;AAGxB,UAAI;AACF,cAAMC,IAAGD,OAAK,KAAK,YAAY,IAAI,GAAG,EAAE,OAAO,KAAK,CAAC;AACrD,gBAAQ;AAAA,MACV,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,QAAI,aAAa,OAAO;AACtB,YAAM,UAAU,YAAY,EAAE,SAAS,GAAG,QAAQ,CAAC,EAAE,CAAC;AACtD,cAAQ,uBAAuB;AAAA,IACjC,WAAW,aAAa,WAAW,QAAQ;AACzC,YAAM,QAAQ,WAAW,KAAK,MAAM,MAAME,WAAS,YAAY,MAAM,CAAC,CAAC;AACvE,iBAAW,MAAM,aAAa,WAAY,QAAO,MAAM,OAAO,EAAE;AAChE,cAAQ,oBAAoB,aAAa,WAAW;AACpD,YAAM,UAAU,YAAY,KAAK;AAAA,IACnC;AAEA,cAAU,MAAM,oBAAoB,YAAY,UAAU;AAC1D,mBAAe,MAAM,uBAAuB,UAAU;AAAA,EACxD;AAEA,SAAO;AAAA,IACL,MAAM,QAAQ,QAAQ,WAAW,KAAK,CAAC,aAAa,SAAS,aAAa,WAAW,WAAW;AAAA,IAChG;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,oBACb,YACA,YAC6B;AAC7B,QAAM,SAA6B;AAAA,IACjC,MAAM;AAAA,IACN,QAAQH,aAAW,UAAU;AAAA,IAC7B,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,cAAc,CAAC;AAAA,IACf,mBAAmB,CAAC;AAAA,IACpB,SAAS,CAAC;AAAA,EACZ;AACA,MAAI,CAAC,OAAO,QAAQ;AAClB,WAAO,oBAAoB,CAAC,GAAG,UAAU,EAAE,KAAK;AAChD,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,UAAU,MAAMI,SAAQ,YAAY,EAAE,eAAe,KAAK,CAAC;AACjE,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,OAAO,GAAG;AACnB,aAAO,QAAQ,KAAK,EAAE,MAAM,MAAM,MAAM,QAAQ,qBAAqB,CAAC;AACtE;AAAA,IACF;AACA,WAAO;AACP,UAAM,OAAOH,OAAK,KAAK,YAAY,MAAM,IAAI;AAC7C,UAAM,YAAY,uBAAuB,MAAM,IAAI;AACnD,UAAM,WAAW,YAAY,MAAM,KAAK,MAAM,GAAG,EAAE,IAAI;AACvD,QAAI;AACJ,QAAI;AACF,cAAQ,MAAME,WAAS,IAAI;AAC3B,aAAO,SAAS,MAAM;AAAA,IACxB,SAAS,KAAK;AACZ,aAAO,QAAQ,KAAK;AAAA,QAClB,MAAM,MAAM;AAAA,QACZ,QAAQ,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MACzE,CAAC;AACD;AAAA,IACF;AACA,QAAI,CAAC,aAAa,QAAQ,GAAG;AAC3B,aAAO,QAAQ,KAAK,EAAE,MAAM,MAAM,MAAM,QAAQ,+CAA+C,CAAC;AAChG;AAAA,IACF;AACA,QAAI,OAAO,KAAK,MAAM,UAAU;AAC9B,aAAO,QAAQ,KAAK,EAAE,MAAM,MAAM,MAAM,QAAQ,mCAAmC,CAAC;AACpF;AAAA,IACF;AACA,QAAI;AACF,oBAAc,OAAO,SAAU;AAAA,IACjC,SAAS,KAAK;AACZ,aAAO,QAAQ,KAAK;AAAA,QAClB,MAAM,MAAM;AAAA,QACZ,QAAQ,WAAW,cAAc,cAAc,QAAQ,KAAK,KACvD,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,MACvD,CAAC;AACD;AAAA,IACF;AACA,YAAQ,IAAI,QAAQ;AACpB,WAAO;AACP,QAAI,WAAW,IAAI,QAAQ,EAAG,QAAO;AAAA,QAChC,QAAO,aAAa,KAAK,MAAM,IAAI;AAAA,EAC1C;AACA,SAAO,aAAa,KAAK;AACzB,SAAO,oBAAoB,CAAC,GAAG,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,QAAQ,IAAI,IAAI,CAAC,EAAE,KAAK;AACrF,SAAO;AACT;AAEA,eAAe,uBAAuB,YAAoD;AACxF,QAAM,SAAgC;AAAA,IACpC,MAAM;AAAA,IACN,QAAQH,aAAW,UAAU;AAAA,IAC7B,SAAS;AAAA,IACT,OAAO;AAAA,IACP,YAAY,CAAC;AAAA,IACb,OAAO;AAAA,EACT;AACA,MAAI,CAAC,OAAO,OAAQ,QAAO;AAC3B,MAAI;AACJ,MAAI;AACF,YAAQ,WAAW,KAAK,MAAM,MAAMG,WAAS,YAAY,MAAM,CAAC,CAAC;AAAA,EACnE,SAAS,KAAK;AACZ,WAAO,QAAQ,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC9D,WAAO;AAAA,EACT;AACA,SAAO,UAAU,OAAO,KAAK,MAAM,MAAM,EAAE;AAC3C,aAAW,CAAC,IAAI,IAAI,KAAK,OAAO,QAAQ,MAAM,MAAM,GAAG;AACrD,QAAI,aAAa,IAAI,EAAG,QAAO;AAAA,QAC1B,QAAO,WAAW,KAAK,EAAE;AAAA,EAChC;AACA,SAAO,WAAW,KAAK;AACvB,SAAO;AACT;;;AC7JO,SAAS,mBAAmB,KAA0C;AAC3E,MAAI,CAACE,UAAS,GAAG,EAAG,QAAO;AAC3B,QAAM,WAAW,IAAI;AACrB,QAAM,QAAQ,IAAI;AAClB,MAAI,aAAa,UAAU,aAAa,YAAY,aAAa,UAAW,QAAO;AACnF,MAAI,UAAU,KAAK,UAAU,EAAG,QAAO;AAEvC,QAAM,QAAgC,CAAC;AACvC,MAAIA,UAAS,IAAI,KAAK,GAAG;AACvB,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,KAAK,GAAG;AACpD,YAAM,QAAQ,UAAU,GAAG;AAC3B,YAAM,OAAO,OAAO,UAAU,WAC1B,QACAA,UAAS,KAAK,KAAK,OAAO,MAAM,YAAY,WAC1C,MAAM,UACNA,UAAS,KAAK,KAAK,OAAO,MAAM,SAAS,WACvC,MAAM,OACN;AACR,UAAI,UAAU,QAAQ,SAAS,QAAQ,OAAO,UAAU,IAAI,KAAK,QAAQ,EAAG,OAAM,KAAK,IAAI;AAAA,IAC7F;AAAA,EACF;AAEA,QAAM,eAAe,IAAI,iBAAiB,UAAU,IAAI,iBAAiB,UACrE,IAAI,eACJ;AACJ,QAAM,WAAW,MAAM,QAAQ,IAAI,QAAQ,IACvC,IAAI,SAAS,OAAO,CAAC,SAAyB,OAAO,SAAS,QAAQ,IACtE,CAAC;AACL,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGO,SAAS,cACd,OACA,MACA,SACe;AACf,QAAM,UAAU,wBAAwB,OAAO,IAAI;AACnD,MAAI,CAAC,QAAQ,OAAQ,OAAM,IAAI,MAAM,GAAG,KAAK,OAAO,IAAI,KAAK,OAAO,4BAA4B;AAEhG,QAAM,SAAS;AAAA,IACb,QAAQ,IAAI,CAAC,YAAY;AAAA,MACvB,IAAI,OAAO,QAAQ,mBAAmB,OAAO,KAAK;AAAA,MAClD,MAAM,OAAO;AAAA,IACf,EAAE;AAAA,IACF,EAAE,SAAS,QAAQ,SAAS,OAAO,QAAQ;AAAA,EAC7C;AACA,MAAI,OAAO,QAAQ,QAAQ;AACzB,UAAM,IAAI;AAAA,MACR,iBAAiB,KAAK,OAAO,IAAI,KAAK,OAAO,OAC3C,OAAO,QAAQ,IAAI,CAAC,SAAS,GAAG,KAAK,EAAE,KAAK,KAAK,MAAM,EAAE,EAAE,KAAK,IAAI;AAAA,IACxE;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,mBAAmB,MAAM,QAAQ;AACxD,QAAM,WAAWA,UAAS,QAAQ,IAAI,SAAS,YAAY;AAC3D,QAAM,QAAQ,mBAAmB,QAAQ;AACzC,QAAM,SAAS,OAAO,MAAM;AAC5B,QAAM,UAAU;AAAA,IACd;AAAA,IACA,QAAQ;AAAA,IACR,OAAO;AAAA,IACP;AAAA,IACAA,UAAS,QAAQ,IAAI,WAAW;AAAA,IAChC;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,WAAW;AAChC,WAAO;AAAA,MACL,KAAK,OAAO;AAAA,MACZ,WAAW;AAAA,MACX,UAAU,KAAK,UAAU,SAAS,MAAM,CAAC,IAAI;AAAA,MAC7C;AAAA,MACA,SAAS,OAAO;AAAA,IAClB;AAAA,EACF;AAEA,qBAAmB,OAAO;AAC1B,OAAK,aAAa,UAAa,MAAM,gBAAgB,CAAC,OAAO;AAC3D,UAAM,IAAI;AAAA,MACR,GAAG,QAAQ,MAAM;AAAA,IAEnB;AAAA,EACF;AACA,MAAI,OAAO,UAAU,GAAG;AACtB,UAAM,IAAI;AAAA,MACR,GAAG,QAAQ,MAAM;AAAA,IACnB;AAAA,EACF;AACA,MAAI,OAAO,aAAa,WAAW;AACjC,UAAM,IAAI;AAAA,MACR,GAAG,QAAQ,MAAM;AAAA,IACnB;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,SAAS;AAC9B,WAAO;AAAA,MACL,KAAK,OAAO;AAAA,MACZ,WAAW;AAAA,MACX,UAAU,KAAK,UAAU,WAAW,OAAO,GAAG,MAAM,CAAC,IAAI;AAAA,MACzD;AAAA,MACA,SAAS,OAAO;AAAA,IAClB;AAAA,EACF;AACA,SAAO;AAAA,IACL,KAAK,OAAO;AAAA,IACZ,WAAW;AAAA,IACX,UAAU,WAAW,SAAS,IAAI;AAAA,IAClC;AAAA,IACA,SAAS,OAAO;AAAA,EAClB;AACF;AAEA,SAAS,aACP,MACA,WACA,OACA,QACA,eACA,OACgB;AAChB,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,MAAM,GAAG,KAAK,OAAO,IAAI,KAAK,OAAO;AAAA,IACrC,OAAO,KAAK;AAAA,IACZ,OAAO,KAAK;AAAA,IACZ,OAAO;AAAA,IACP,MAAM,EAAE,GAAG,MAAM,KAAK;AAAA,IACtB,OAAO,EAAE,GAAG,MAAM,OAAO,SAAS,MAAM,QAAQ;AAAA,IAChD,OAAO,OAAO,IAAI,CAAC,OAAO,UAAU;AAClC,YAAM,cAAc,UAAU,MAAM,EAAE,KAAK;AAC3C,aAAO;AAAA,QACL,IAAI;AAAA,QACJ;AAAA,QACA,MAAM,MAAM;AAAA,QACZ,GAAG,MAAM;AAAA,QACT,GAAG,MAAM;AAAA,QACT,OAAO,MAAM;AAAA,QACb,QAAQ,MAAM;AAAA,QACd,GAAI,OAAO,MAAM,WAAW,MAAM,SAAY,EAAE,SAAS,MAAM,MAAM,WAAW,EAAE,IAAI,CAAC;AAAA,QACvF,WAAW,QAAQ,MAAM,MAAM,WAAW,MAAM,SAAY;AAAA,MAC9D;AAAA,IACF,CAAC;AAAA,IACD;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,WAAW,SAAkD;AACpE,QAAM,QAAQ,QAAQ;AACtB,QAAM,QAAiC;AAAA,IACrC,MAAM;AAAA,IACN,SAAS;AAAA,IACT,cAAc;AAAA,IACd,MAAM,QAAQ,KAAK,QAAQ,KAAK,GAAG;AAAA,IACnC,WAAW,QAAQ,KAAK;AAAA,IACxB,YAAY,QAAQ,KAAK;AAAA,IACzB,WAAW,QAAQ,MAAM;AAAA,IACzB,SAAS,QAAQ,MAAM;AAAA,IACvB,OAAO,QAAQ;AAAA,IACf,YAAY,QAAQ,MAAM;AAAA,IAC1B,aAAa,QAAQ,MAAM;AAAA,IAC3B,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AACA,MAAI,CAAC,SAAS,MAAM,aAAa,UAAW,QAAO;AAEnD,QAAM,eAAe,gBAAgB,KAAK;AAC1C,QAAM,WAAW,CAAC;AAAA,IAChB,MAAM,QAAQ;AAAA,IACd,MAAM,MAAM;AAAA,IACZ,MAAM,mBAAmB,SAAS,CAAC;AAAA,IACnC,QAAQ,aAAa,IAAI,CAAC,MAAM,WAAW;AAAA,MACzC;AAAA,MACA,OAAO,UAAU,IAAI,YAAY;AAAA,MACjC,MAAM,mBAAmB,SAAS,KAAK;AAAA,MACvC,aAAa;AAAA,IACf,EAAE;AAAA,IACF,YAAY,MAAM,eACd,CAAC,EAAE,MAAM,0BAA0B,MAAM,UAAU,OAAO,MAAM,aAAa,CAAC,IAC9E,CAAC;AAAA,IACL,WAAW,QAAQ,MAChB,OAAO,CAAC,SAAS,KAAK,YAAY,MAAS,EAC3C,IAAI,CAAC,UAAU,EAAE,QAAQ,KAAK,IAAI,QAAQ,YAAY,OAAO,KAAK,OAAQ,EAAE,EAAE;AAAA,EACnF,CAAC;AACD,SAAO;AACT;AAEA,SAAS,YAAY,OAA4B,MAAwB;AACvE,QAAM,WAAW,CAAC,SAAkB,OAAQ,KAAK,SAAU,IAAI,IAAI;AACnE,MAAI,MAAM,aAAa,UAAU;AAE/B,WAAO,CAAC,GAAG,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC;AAAA,EACxE;AAEA,SAAO,CAAC,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC;AACxE;AAEA,SAAS,WAAW,SAAyB,MAA4B;AACvE,QAAM,QAAQ,QAAQ;AACtB,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA,uCAAuC,KAAK,UAAU,KAAK,QAAQ,KAAK,EAAE,CAAC;AAAA,IAC3E;AAAA,IACA;AAAA,IACA;AAAA,IACA,kCAAkC,QAAQ,KAAK,KAAK,KAAK,QAAQ,KAAK,MAAM;AAAA,EAC9E;AAEA,aAAW,QAAQ,QAAQ,OAAO;AAChC,UAAM,IAAI,KAAK,KAAK,QAAQ,MAAM;AAClC,UAAM,IAAI,KAAK,MAAM,KAAK,KAAK,QAAQ,MAAM,OAAO;AACpD,UAAM,KAAK,GAAG,CAAC,IAAI,CAAC,QAAQ;AAC5B,QAAI,CAAC,SAAS,KAAK,YAAY,UAAa,MAAM,aAAa,UAAW;AAC1E,UAAM,SAAS,iBAAiB,OAAO,KAAK,OAAO;AACnD,UAAM,KAAK,GAAG,CAAC,IAAI,CAAC,oBAAoB;AACxC,UAAM,KAAK,GAAG,CAAC,IAAI,CAAC,gBAAgB,gBAAgB,MAAM,CAAC,EAAE;AAC7D,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAClD,YAAM,KAAK,GAAG,CAAC,IAAI,CAAC,2BAA2B,IAAI,MAAM,KAAK,EAAE;AAAA,IAClE;AAAA,EACF;AAEA,QAAM,KAAK,IAAI,YAAY;AAC3B,QAAM,KAAK,wBAAwB,QAAQ,KAAK,KAAK,KAAK,QAAQ,KAAK,MAAM,GAAG;AAChF,QAAM,QAAQ,eAAe,KAAK,YAAY,WAAW;AACzD,MAAI,UAAU,EAAG,OAAM,KAAK,gBAAgB,KAAK,EAAE;AACnD,MAAI,SAAS,MAAM,aAAa,WAAW;AACzC,UAAM,KAAK,wBAAwB,MAAM,aAAa,WAAW,IAAI,CAAC,EAAE;AACxE,eAAW,CAAC,OAAO,IAAI,KAAK,gBAAgB,KAAK,EAAE,QAAQ,GAAG;AAC5D,YAAM,KAAK,yBAAyB,KAAK,WAAW,KAAK,UAAU,IAAI,CAAC,EAAE;AAC1E,YAAM;AAAA,QACJ,yBAAyB,KAAK,eAC3B,UAAU,IAAI,qCAAqC;AAAA,MACxD;AAAA,IACF;AAAA,EACF;AACA,QAAM,KAAK,2DAA2D,EAAE;AACxE,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,iBAAiB,OAA4B,MAAsC;AAC1F,QAAM,UAAU,CAAC,SAAkB,OAAQ,KAAK,SAAU,IAAI,IAAI;AAClE,MAAI,MAAM,aAAa,UAAU;AAC/B,WAAO;AAAA,MACL,iBAAiB,QAAQ,CAAC;AAAA,MAC1B,kBAAkB,QAAQ,CAAC;AAAA,MAC3B,oBAAoB,QAAQ,CAAC;AAAA,MAC7B,qBAAqB,QAAQ,CAAC;AAAA,IAChC;AAAA,EACF;AACA,SAAO;AAAA,IACL,UAAU,QAAQ,CAAC;AAAA,IACnB,YAAY,QAAQ,CAAC;AAAA,IACrB,aAAa,QAAQ,CAAC;AAAA,IACtB,WAAW,QAAQ,CAAC;AAAA,EACtB;AACF;AAEA,SAAS,gBAAgB,QAAwC;AAC/D,QAAM,cAAc,OAAO,OAAO,MAAM,EAAE,OAAO,CAAC,UAAU,UAAU,CAAC,EAAE;AACzE,SAAO,cAAc,KAAK,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI;AAC7D;AAEA,SAAS,eAAe,UAAsC;AAC5D,MAAI,aAAa,eAAe,aAAa,UAAW,QAAO;AAC/D,MAAI,aAAa,SAAS,aAAa,aAAc,QAAO;AAC5D,SAAO;AACT;AAEA,SAAS,mBAAmB,SAAyB,cAA8B;AACjF,QAAM,QAAQ,QAAQ;AACtB,QAAM,QAAQ,KAAK,MAAM,SAAS;AAClC,QAAM,SAAS,iBAAiB,IAAI,OAAO;AAC3C,SAAO,QAAQ,MAAM,KAAK,CAAC,SAAS,KAAK,YAAY,MAAM,GAAG,MAAM;AACtE;AAEA,SAAS,gBAAgB,OAAsC;AAC7D,SAAO,CAAC,MAAM,SAAS,CAAC,KAAK,WAAW,MAAM,SAAS,CAAC,KAAK,YAAY;AAC3E;AAEA,SAAS,mBAAmB,SAA+B;AACzD,QAAM,aAAa,QAAQ,MAAM;AAAA,IAC/B,CAAC,SAAS,KAAK,UAAU,QAAQ,KAAK,SAAS,KAAK,WAAW,QAAQ,KAAK;AAAA,EAC9E;AACA,MAAI,WAAW,QAAQ;AACrB,UAAM,IAAI;AAAA,MACR,mCAAmC,QAAQ,KAAK,KAAK,IAAI,QAAQ,KAAK,MAAM,uBAC3D,WAAW,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,KAAK,IAAI,CAAC;AAAA,IACjE;AAAA,EACF;AACF;AAEA,SAAS,UAAU,KAA4B;AAC7C,QAAM,QAAQ,IAAI,MAAM,kBAAkB;AAC1C,SAAO,QAAQ,OAAO,MAAM,CAAC,CAAC,IAAI;AACpC;AAEA,SAASA,UAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;;;AC9WA,SAAS,SAAAC,QAAO,aAAAC,YAAW,YAAAC,kBAAgB;AAC3C,OAAOC,YAAU;;;ACCjB,IAAMC,cAAa,CAAC,MAClB,EAAE,QAAQ,YAAY,CAAC,OAAO,EAAE,KAAK,SAAS,KAAK,QAAQ,KAAK,QAAQ,KAAK,UAAU,KAAK,QAAQ,GAAG,CAAC,CAAE;AAwBrG,SAAS,mBAAmB,SAAmB,KAAmC;AACvF,QAAM,OAAO,QAAQ,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,QAAQA,YAAW,EAAE,MAAM,EAAE,EAAE;AACxE,QAAM,OAAO,KAAK,UAAU,IAAI,EAAE,QAAQ,QAAQ,MAAM;AACxD,QAAM,UAAU,MAAMA,YAAW,IAAI,OAAO,IAAI;AAChD,QAAM,YAAY,MAAMA,YAAW,IAAI,SAAS,IAAI;AAEpD,SAAO;AAAA;AAAA;AAAA;AAAA,0BAIiB,UAAU,WAAM,OAAO,KAAK,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAoDpD,UACI,6BAAwB,OAAO,8BAAyB,SAAS,8BACjE,EACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAec,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA6EpB;;;ADrKA,IAAMC,iBAAgB,OAAO,KAAK,CAAC,KAAM,IAAM,IAAM,IAAM,IAAM,IAAM,IAAM,EAAI,CAAC;AAiBlF,eAAsB,WACpB,UACA,SACA,KAQA,OAA8E,CAAC,GACvD;AACxB,QAAMC,OAAM,KAAK,eAAe,MAAM;AAAA,EAAC;AACvC,QAAM,OAAO,mBAAmB,SAAS;AAAA,IACvC,SAAS,IAAI;AAAA,IACb,WAAWC,OAAK,SAAS,QAAQ,IAAI,GAAG,IAAI,SAAS,KAAK;AAAA,EAC5D,CAAC;AACD,QAAM,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;AAClD,QAAM,eAAe,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAE/D,SAAO,gBAA+B;AAAA,IACpC;AAAA,IACA,MAAM,KAAK;AAAA,IACX,MAAM,KAAK;AAAA,IACX,YAAYD;AAAA,IACZ,SAAS,CAAC,QAAQ;AAChB,MAAAA,KAAI;AAAA,IAAO,QAAQ,MAAM,mCAAmC,GAAG,EAAE;AACjE,MAAAA,KAAI;AAAA,CAAmD;AAAA,IACzD;AAAA,IACA,aAAa,OAAO,SAAS;AAC3B,YAAM,EAAE,UAAU,IAAI;AAEtB,YAAM,SAAwB,EAAE,UAAU,GAAG,MAAM,GAAG,WAAW,GAAG,QAAQ,EAAE;AAC9E,YAAM,QAAQ,IAAI,IAAI,OAAO,KAAK,IAAI,SAAS,MAAM,CAAC;AACtD,YAAM,mBAA6B,CAAC;AAEpC,iBAAW,YAAY,WAAW;AAChC,cAAM,SAAS,KAAK,IAAI,SAAS,EAAE;AACnC,YAAI,CAAC,OAAQ;AAEb,YAAI,SAAS,WAAW,UAAU;AAChC,cAAI;AACF,kBAAM,MAAM,MAAM,SAAS,SAAS,OAAO,UAAU;AACrD,gBAAI,CAAC,IAAI,SAAS,GAAG,CAAC,EAAE,OAAOD,cAAa,EAAG,OAAM,IAAI,MAAM,WAAW;AAC1E,sBAAU,GAAG;AAEb,kBAAM,UAAU,aAAa,OAAO,QAAQ,KAAK;AACjD,kBAAM,MAAME,OAAK,KAAK,aAAa,GAAG,OAAO,MAAM;AACnD,kBAAM,UAAUA,OAAK,QAAQ,IAAI,WAAW,GAAG;AAC/C,kBAAMC,OAAMD,OAAK,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AACtD,kBAAME,WAAU,SAAS,GAAG;AAE5B,gBAAI,SAAS,OAAO,OAAO,IAAI;AAAA,cAC7B,QAAQ,OAAO;AAAA,cACf,eAAe,CAAC;AAAA,cAChB,UAAU;AAAA,cACV,MAAM;AAAA,cACN,MAAM,CAAC,UAAU;AAAA,cACjB,QAAQ,CAAC,IAAI,OAAO;AAAA,cACpB,gBAAgB,CAAC;AAAA,cACjB,GAAI,OAAO,UAAU,OAAO,SACxB,EAAE,MAAM,OAAO,MAAM,IACrB,EAAE,OAAO,OAAO,OAAO,QAAQ,OAAO,OAAO;AAAA,YACnD;AAEA,kBAAM,gBAAgB,uBAAuB,OAAO,UAAU,IAC1D,OAAO,aACP;AAEJ,mBAAO,IAAI,MAAM,QAAQ,IAAI,SAAS,OAAO,GAAG;AAAA,cAC9C,SAAS,IAAI;AAAA,cACb;AAAA,cACA,UAAU;AAAA,cACV,WAAW,OAAO,UAAU,OAAO,SAAS,SAAS;AAAA,cACrD,QAAQ,OAAO;AAAA,cACf,OAAO,OAAO;AAAA,cACd,QAAQ,OAAO;AAAA,cACf,OAAO,OAAO;AAAA,cACd,gBAAgB;AAAA,cAChB,UAAU,OAAO;AAAA,cACjB,gBAAgB;AAAA,cAChB,QAAQ;AAAA,cACR,OAAO;AAAA;AAAA;AAAA,cAGP,WAAW;AAAA,cACX,YAAY,gBAAgB,CAAC,EAAE,KAAK,cAAc,CAAC,IAAI,CAAC;AAAA,cACxD,SAAS,CAAC;AAAA,gBACR,MAAM,mBAAmB,SAASF,OAAK,QAAQ,IAAI,YAAY,CAAC;AAAA,gBAChE,QAAQ,OAAO,GAAG;AAAA,cACpB,CAAC;AAAA,cACD,aAAa,OAAO;AAAA,cACpB,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,cACrC,MAAM;AAAA;AAAA,cACN,UAAU;AAAA,cACV,UAAU,SAAS;AAAA,YACrB,CAAC;AACD,6BAAiB,KAAK,OAAO;AAC7B,mBAAO;AACP,YAAAD,KAAI,cAAc,OAAO,WAAM,OAAO,EAAE,EAAE;AAAA,UAC5C,SAAS,KAAK;AACZ,mBAAO;AACP,YAAAA,KAAI,mBAAmB,OAAO,EAAE,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,UACzF;AAAA,QACF,WAAW,SAAS,WAAW,QAAQ;AACrC,iBAAO;AAAA,QACT,OAAO;AACL,iBAAO;AAAA,QACT;AAAA,MACF;AAEA,YAAM,UAAU,UAAU,WAAW,cAAc,EAAE,YAAYA,KAAI,CAAC;AAOtE,YAAM,MAAM,KAAK,MAAM,MAAMI,WAAS,IAAI,cAAc,MAAM,CAAC;AAC/D,iBAAW,MAAM,iBAAkB,KAAI,OAAO,EAAE,IAAI,IAAI,SAAS,OAAO,EAAE;AAC1E,YAAMD,WAAU,IAAI,cAAc,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI;AACrE,YAAM,SAAS,IAAI,UAAU,IAAI,IAAI;AAErC,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;;;AEnKA,OAAOE,YAAU;AACjB,SAAS,cAAAC,oBAAkB;AAC3B,SAAS,WAAAC,UAAS,YAAAC,kBAAgB;AAClC,SAAS,qBAAqB;AAC9B,SAAS,KAAAC,UAAS;AAKlB,IAAM,YAAY;AAClB,IAAM,eAAe;AACrB,IAAM,aAAa;AACnB,IAAM,cAAc;AACpB,IAAM,mBAAmB;AAEzB,IAAM,qBAAqBC,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,UAAU;AAC7D,MAAI,MAAM,SAAS,IAAI,KAAKC,OAAK,MAAM,WAAW,KAAK,EAAG,QAAO;AACjE,QAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,SAAO,CAAC,MAAM,SAAS,EAAE,KAAK,CAAC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,SAAS,IAAI;AAC5E,GAAG,qEAAqE;AAExE,IAAM,sBAAsBD,GAAE,OAAO;AAAA,EACnC,QAAQA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACxB,OAAOA,GAAE,OAAO,EAAE,IAAI,CAAC;AACzB,CAAC,EAAE,OAAO;AAEH,IAAM,eAAeA,GAAE,OAAO;AAAA,EACnC,SAASA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACnC,QAAQA,GAAE,QAAQ,kBAAkB;AAAA,EACpC,eAAeA,GAAE,QAAQ,CAAC;AAAA,EAC1B,IAAIA,GAAE,OAAO,EAAE,MAAM,cAAc,wBAAwB;AAAA,EAC3D,SAASA,GAAE,OAAO,EAAE,MAAM,YAAY,gBAAgB;AAAA,EACtD,UAAUA,GAAE,OAAO,EAAE,MAAM,sBAAsB;AAAA,EACjD,SAASA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EAClC,OAAOA,GAAE,MAAMA,GAAE,OAAO;AAAA,IACtB,MAAM;AAAA,IACN,MAAMA,GAAE,KAAK,CAAC,YAAY,WAAW,CAAC;AAAA,IACtC,QAAQA,GAAE,OAAO,EAAE,MAAM,SAAS;AAAA,EACpC,CAAC,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EACvB,QAAQA,GAAE,MAAMA,GAAE,OAAO;AAAA,IACvB,MAAM;AAAA,IACN,QAAQA,GAAE,OAAO,EAAE,MAAM,SAAS;AAAA,IAClC,QAAQA,GAAE,OAAO,EAAE,IAAI;AAAA,IACvB,SAASA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC3B,CAAC,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EACvB,SAASA,GAAE,OAAO,EAAE,MAAM,sBAAsB;AAAA,EAChD,OAAO;AAAA,EACP,UAAUA,GAAE,OAAO;AAAA,IACjB,MAAM;AAAA,IACN,cAAcA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IAC9B,WAAWA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE;AAAA,IACzC,UAAUA,GAAE,OAAO;AAAA,MACjB,QAAQ;AAAA,MACR,OAAO,oBAAoB,SAAS;AAAA,MACpC,QAAQ,oBAAoB,SAAS;AAAA,MACrC,WAAW,oBAAoB,SAAS;AAAA,MACxC,MAAM,oBAAoB,SAAS;AAAA,MACnC,aAAa,oBAAoB,SAAS;AAAA,MAC1C,WAAW,oBAAoB,SAAS;AAAA,MACxC,UAAU,oBAAoB,SAAS;AAAA,IACzC,CAAC,EAAE,OAAO;AAAA,EACZ,CAAC,EAAE,OAAO,EAAE,SAAS;AAAA,EACrB,SAASA,GAAE,OAAO;AAAA,IAChB,OAAOA,GAAE,KAAK,CAAC,sBAAsB,sBAAsB,CAAC;AAAA,IAC5D,eAAeA,GAAE,OAAO;AAAA,MACtB,OAAOA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE;AAAA,MAC9B,QAAQA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE;AAAA,IACjC,CAAC,EAAE,OAAO;AAAA,IACV,uBAAuBA,GAAE,OAAO;AAAA,MAC9B,KAAKA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,MAC3B,KAAKA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAC7B,CAAC,EAAE,OAAO;AAAA,IACV,eAAeA,GAAE,OAAO;AAAA,MACtB,KAAKA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,MAC3B,KAAKA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,IAC7B,CAAC,EAAE,OAAO;AAAA,IACV,YAAYA,GAAE,KAAK,CAAC,UAAU,eAAe,YAAY,CAAC;AAAA,IAC1D,QAAQA,GAAE,MAAMA,GAAE,KAAK;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC,CAAC,EAAE,IAAI,CAAC;AAAA,IACT,OAAOA,GAAE,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EAC9C,CAAC,EAAE,OAAO;AAAA,EACV,WAAWA,GAAE,OAAO;AAAA,IAClB,WAAWA,GAAE,QAAQ,QAAQ;AAAA,IAC7B,QAAQA,GAAE,OAAO,EAAE,MAAM,SAAS;AAAA,EACpC,CAAC,EAAE,OAAO;AACZ,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,QAAQ,YAAY;AAC3C,MAAI,OAAO,MAAM,YAAY,OAAO,MAAM,aAAa,OAAO,UAAU;AACtE,YAAQ,SAAS;AAAA,MACf,MAAMA,GAAE,aAAa;AAAA,MACrB,MAAM,CAAC,SAAS,UAAU;AAAA,MAC1B,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACA,QAAM,YAAY,OAAO,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI;AACtD,MAAI,IAAI,IAAI,SAAS,EAAE,SAAS,UAAU,QAAQ;AAChD,YAAQ,SAAS,EAAE,MAAMA,GAAE,aAAa,QAAQ,MAAM,CAAC,OAAO,GAAG,SAAS,sBAAsB,CAAC;AAAA,EACnG;AACA,QAAM,aAAa,OAAO,OAAO,IAAI,CAAC,UAAU,MAAM,IAAI;AAC1D,MAAI,IAAI,IAAI,UAAU,EAAE,SAAS,WAAW,QAAQ;AAClD,YAAQ,SAAS,EAAE,MAAMA,GAAE,aAAa,QAAQ,MAAM,CAAC,QAAQ,GAAG,SAAS,uBAAuB,CAAC;AAAA,EACrG;AACA,MAAI,UAAU,SAAS,WAAW,GAAG;AACnC,YAAQ,SAAS;AAAA,MACf,MAAMA,GAAE,aAAa;AAAA,MACrB,MAAM,CAAC,OAAO;AAAA,MACd,SAAS,GAAG,WAAW;AAAA,IACzB,CAAC;AAAA,EACH;AACA,MAAI,OAAO,QAAQ,sBAAsB,MAAM,OAAO,QAAQ,sBAAsB,KAAK;AACvF,YAAQ,SAAS;AAAA,MACf,MAAMA,GAAE,aAAa;AAAA,MACrB,MAAM,CAAC,WAAW,uBAAuB;AAAA,MACzC,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACA,MAAI,OAAO,QAAQ,cAAc,MAAM,OAAO,QAAQ,cAAc,KAAK;AACvE,YAAQ,SAAS;AAAA,MACf,MAAMA,GAAE,aAAa;AAAA,MACrB,MAAM,CAAC,WAAW,eAAe;AAAA,MACjC,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACA,MAAI,OAAO,YAAY,CAAC,OAAO,MAAM;AAAA,IACnC,CAAC,SAAS,KAAK,SAAS,OAAO,SAAU,QAAQ,KAAK,SAAS;AAAA,EACjE,GAAG;AACD,YAAQ,SAAS;AAAA,MACf,MAAMA,GAAE,aAAa;AAAA,MACrB,MAAM,CAAC,YAAY,MAAM;AAAA,MACzB,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACA,MAAI,OAAO,aAAa,WAAW;AACjC,QAAI,CAAC,OAAO,UAAU;AACpB,cAAQ,SAAS;AAAA,QACf,MAAMA,GAAE,aAAa;AAAA,QACrB,MAAM,CAAC,UAAU;AAAA,QACjB,SAAS;AAAA,MACX,CAAC;AACD;AAAA,IACF;AACA,UAAM,UAAU,OAAO,MAAM,gBAAgB;AAC7C,QAAI,CAAC,WAAW,OAAO,YAAY,YAAY,MAAM,QAAQ,OAAO,GAAG;AACrE,cAAQ,SAAS;AAAA,QACf,MAAMA,GAAE,aAAa;AAAA,QACrB,MAAM,CAAC,SAAS,mBAAmB,SAAS;AAAA,QAC5C,SAAS;AAAA,MACX,CAAC;AACD;AAAA,IACF;AACA,UAAM,WAAW;AAAA,MACf,cAAc,GAAG,gBAAgB,IAAI,OAAO,SAAS,IAAI;AAAA,MACzD,cAAc,OAAO,SAAS;AAAA,MAC9B,WAAW,OAAO,SAAS;AAAA,MAC3B,UAAU,OAAO,SAAS;AAAA,IAC5B;AACA,QAAI,KAAK,UAAUE,WAAU,OAAO,CAAC,MAAM,KAAK,UAAUA,WAAU,QAAQ,CAAC,GAAG;AAC9E,cAAQ,SAAS;AAAA,QACf,MAAMF,GAAE,aAAa;AAAA,QACrB,MAAM,CAAC,SAAS,mBAAmB,SAAS;AAAA,QAC5C,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AACF,CAAC;AA8DD,SAASE,WAAU,OAAyB;AAC1C,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO;AACtF,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,CAAC,OAAO,SAAS,KAAK,EAAG,OAAM,IAAI,MAAM,gCAAgC;AAC7E,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAIA,UAAS;AACpD,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,SAAkC,CAAC;AACzC,eAAW,OAAO,OAAO,KAAK,KAAK,EAAE,KAAK,GAAG;AAC3C,YAAM,OAAQ,MAAkC,GAAG;AACnD,UAAI,SAAS,OAAW,QAAO,GAAG,IAAIA,WAAU,IAAI;AAAA,IACtD;AACA,WAAO;AAAA,EACT;AACA,QAAM,IAAI,MAAM,kCAAkC,OAAO,KAAK,UAAU;AAC1E;AAEO,SAAS,aAAa,QAAwB;AACnD,QAAM,EAAE,WAAW,YAAY,GAAG,QAAQ,IAAI;AAC9C,SAAO,OAAO,KAAK,UAAUA,WAAU,OAAO,CAAC,CAAC;AAClD;AAEA,SAASC,SAAQ,OAAwB;AACvC,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAEA,eAAe,eAAe,YAAoB,SAAyC;AACzF,QAAM,WAAWF,OAAK,QAAQ,UAAU;AACxC,MAAI;AACJ,MAAI;AACF,UAAM,KAAK,MAAM,MAAMG,WAAS,UAAU,MAAM,CAAC;AAAA,EACnD,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,yBAAyB,QAAQ,KAAKD,SAAQ,KAAK,CAAC,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,EAC1F;AACA,QAAM,SAAS,aAAa,UAAU,GAAG;AACzC,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI;AAAA,MACR,kBAAkB,QAAQ;AAAA,IACxB,OAAO,MAAM,OAAO,IAAI,CAAC,UAAU,KAAK,MAAM,KAAK,KAAK,GAAG,KAAK,GAAG,KAAK,MAAM,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,IACtG;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,OAAO,MAAM,MAAM,UAAU,KAAKF,OAAK,QAAQ,QAAQ,GAAG,QAAQ;AACrF;AAEA,eAAe,gBAAgB,MAAiC;AAC9D,MAAI,CAACI,aAAW,IAAI,EAAG,QAAO,CAAC;AAC/B,QAAM,MAAgB,CAAC;AACvB,aAAW,SAAS,MAAMC,SAAQ,MAAM,EAAE,eAAe,KAAK,CAAC,GAAG;AAChE,UAAM,WAAWL,OAAK,KAAK,MAAM,MAAM,IAAI;AAC3C,QAAI,MAAM,YAAY,EAAG,KAAI,KAAK,GAAG,MAAM,gBAAgB,QAAQ,CAAC;AAAA,aAC3D,MAAM,OAAO,KAAK,MAAM,SAAS,YAAa,KAAI,KAAK,QAAQ;AAAA,EAC1E;AACA,SAAO;AACT;AAEO,SAAS,oBAA4B;AAC1C,SAAO,cAAc,IAAI,IAAI,eAAe,YAAY,GAAG,CAAC;AAC9D;AAEA,eAAsB,mBAAmB,OAAO,kBAAkB,GAA4B;AAC5F,QAAM,UAAU,MAAM,QAAQ;AAAA,KAC3B,MAAM,gBAAgBA,OAAK,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,eAAe,MAAM,IAAI,CAAC;AAAA,EACtF;AACA,SAAO,QAAQ;AAAA,IAAK,CAAC,GAAG,MACtB,EAAE,OAAO,GAAG,cAAc,EAAE,OAAO,EAAE,KAAK,gBAAgB,EAAE,OAAO,SAAS,EAAE,OAAO,OAAO;AAAA,EAC9F;AACF;AAEA,SAAS,gBAAgB,GAAW,GAAmB;AACrD,QAAM,KAAK,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AAClC,QAAM,KAAK,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM;AAClC,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,aAAa,GAAG,CAAC,IAAK,GAAG,CAAC;AAChC,QAAI,WAAY,QAAO;AAAA,EACzB;AACA,SAAO;AACT;AAEA,SAAS,cAAc,UAAoD;AACzE,QAAM,QAAQ,SAAS,MAAM,iCAAiC;AAC9D,MAAI,CAAC,SAAS,CAAC,aAAa,KAAK,MAAM,CAAC,CAAE,GAAG;AAC3C,UAAM,IAAI,MAAM,4BAA4B,QAAQ,mDAAmD;AAAA,EACzG;AACA,SAAO,EAAE,IAAI,MAAM,CAAC,GAAI,SAAS,MAAM,CAAC,EAAE;AAC5C;AAEA,eAAsB,cACpB,QACA,cAAc,kBAAkB,GACT;AACvB,QAAM,QAAQA,OAAK,QAAQ,MAAM;AACjC,MAAII,aAAW,KAAK,GAAG;AACrB,UAAM,aAAaJ,OAAK,SAAS,KAAK,MAAM,cAAc,QAAQA,OAAK,KAAK,OAAO,WAAW;AAC9F,WAAO,eAAe,YAAY,KAAK;AAAA,EACzC;AACA,MAAI,OAAO,WAAW,GAAG,KAAK,OAAO,WAAW,GAAG,KAAK,OAAO,SAAS,IAAI,GAAG;AAC7E,UAAM,IAAI,MAAM,0BAA0B,KAAK,EAAE;AAAA,EACnD;AACA,QAAM,WAAW,cAAc,MAAM;AACrC,QAAM,WAAW,MAAM,mBAAmB,WAAW,GAAG;AAAA,IAAO,CAAC,UAC9D,MAAM,OAAO,OAAO,SAAS,OAC5B,SAAS,YAAY,UAAa,MAAM,OAAO,YAAY,SAAS;AAAA,EACvE;AACA,MAAI,CAAC,QAAQ,OAAQ,OAAM,IAAI,MAAM,6BAA6B,MAAM,EAAE;AAC1E,SAAO,QAAQ,CAAC;AAClB;AAEA,eAAe,WAAW,MAAc,MAAyE;AAC/G,QAAM,WAAWA,OAAK,QAAQ,MAAM,GAAG,KAAK,KAAK,MAAM,GAAG,CAAC;AAC3D,MAAI,CAACI,aAAW,QAAQ,GAAG;AACzB,WAAO,EAAE,MAAM,KAAK,MAAM,gBAAgB,KAAK,QAAQ,cAAc,MAAM,QAAQ,UAAU;AAAA,EAC/F;AACA,QAAM,eAAe,MAAM,WAAW,QAAQ;AAC9C,SAAO;AAAA,IACL,MAAM,KAAK;AAAA,IACX,gBAAgB,KAAK;AAAA,IACrB;AAAA,IACA,QAAQ,iBAAiB,KAAK,SAAS,OAAO;AAAA,EAChD;AACF;AAEA,eAAsB,aACpB,QACA,UAAwD,CAAC,GAC5B;AAC7B,QAAM,SAAS,MAAM,cAAc,QAAQ,QAAQ,WAAW;AAC9D,QAAM,kBAAkB,aAAa,OAAO,MAAM;AAClD,QAAM,QAAQ,MAAM,QAAQ,IAAI,OAAO,OAAO,MAAM,IAAI,CAAC,SAAS,WAAW,OAAO,KAAK,IAAI,CAAC,CAAC;AAC/F,QAAM,YAAY,QAAQ,YAAYJ,OAAK,QAAQ,QAAQ,SAAS,IAAI;AACxE,QAAM,SAAoC,YACtC,MAAM,QAAQ,IAAI,OAAO,OAAO,OAAO,IAAI,OAAO,WAAW;AAAA,IAC3D,GAAG,MAAM,WAAW,WAAW,KAAK;AAAA,IACpC,QAAQ,MAAM;AAAA,IACd,SAAS,MAAM;AAAA,EACjB,EAAE,CAAC,IACH,OAAO,OAAO,OAAO,IAAI,CAAC,WAAW;AAAA,IACnC,MAAM,MAAM;AAAA,IACZ,gBAAgB,MAAM;AAAA,IACtB,cAAc;AAAA,IACd,QAAQ,MAAM;AAAA,IACd,SAAS,MAAM;AAAA,IACf,QAAQ;AAAA,EACV,EAAE;AACN,QAAM,kBAAkB,oBAAoB,OAAO,OAAO,UAAU,SAAS,OAAO;AACpF,SAAO;AAAA,IACL,SAAS;AAAA,IACT,IACE,oBAAoB,QACpB,MAAM,MAAM,CAAC,SAAS,KAAK,WAAW,IAAI,MACzC,CAAC,aAAa,OAAO,MAAM,CAAC,UAAU,MAAM,WAAW,IAAI;AAAA,IAC9D,QAAQ;AAAA,MACN,IAAI,OAAO,OAAO;AAAA,MAClB,SAAS,OAAO,OAAO;AAAA,MACvB,MAAM,OAAO;AAAA,MACb,SAAS,OAAO;AAAA,IAClB;AAAA,IACA,WAAW;AAAA,MACT,gBAAgB,OAAO,OAAO,UAAU;AAAA,MACxC,cAAc;AAAA,MACd,QAAQ;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,YAAY,OAAc,aAAqB,KAAoB;AAC1E,QAAM,cAAcA,OAAK,SAAS,KAAK,WAAW,EAAE,MAAMA,OAAK,GAAG,EAAE,KAAK,GAAG,KAAK;AACjF,QAAM,UAAU,CAAC,UAA4B;AAC3C,QAAI,OAAO,UAAU,SAAU,QAAO,MAAM,WAAW,kBAAkB,WAAW;AACpF,QAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,OAAO;AAClD,QAAI,SAAS,OAAO,UAAU,UAAU;AACtC,aAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC;AAAA,IAC5F;AACA,WAAO;AAAA,EACT;AACA,SAAO,QAAQ,KAAK;AACtB;AAEA,eAAsB,cACpB,QACA,UAAgC,CAAC,GACH;AAC9B,QAAM,MAAMA,OAAK,QAAQ,QAAQ,OAAO,QAAQ,IAAI,CAAC;AACrD,QAAM,SAAS,MAAM,cAAc,QAAQ,QAAQ,WAAW;AAC9D,QAAM,eAAe,MAAM,aAAa,OAAO,IAAI;AACnD,MAAI,CAAC,aAAa,IAAI;AACpB,UAAM,IAAI,MAAM,UAAU,OAAO,OAAO,EAAE,IAAI,OAAO,OAAO,OAAO,iCAAiC;AAAA,EACtG;AACA,QAAM,cAAc,QAAQ,MACxBA,OAAK,QAAQ,KAAK,QAAQ,GAAG,IAC7BA,OAAK,KAAK,KAAK,qBAAqB,GAAG,OAAO,OAAO,GAAG,MAAM,GAAG,GAAG,OAAO,OAAO,OAAO;AAC7F,QAAM,UAAU;AAAA,IACd,EAAE,MAAM,aAAa,QAAQ,OAAO,KAAK;AAAA,IACzC,GAAG,OAAO,OAAO,MAAM,IAAI,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,QAAQA,OAAK,KAAK,OAAO,KAAK,GAAG,KAAK,KAAK,MAAM,GAAG,CAAC,EAAE,EAAE;AAAA,EACpH;AACA,QAAM,QAAQ,MAAM,QAAQ,IAAI,QAAQ,IAAI,OAAO,UAAU;AAAA,IAC3D,MAAMA,OAAK,KAAK,aAAa,GAAG,KAAK,KAAK,MAAM,GAAG,CAAC;AAAA,IACpD,MAAM,MAAMG,WAAS,KAAK,MAAM;AAAA,EAClC,EAAE,CAAC;AAEH,MAAI,CAAC,QAAQ,OAAO;AAClB,eAAW,QAAQ,OAAO;AACxB,UAAI,CAACC,aAAW,KAAK,IAAI,EAAG;AAC5B,YAAM,UAAU,MAAMD,WAAS,KAAK,IAAI;AACxC,UAAI,CAAC,QAAQ,OAAO,KAAK,IAAI,GAAG;AAC9B,cAAM,IAAI;AAAA,UACR,yCAAyC,KAAK,IAAI;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,oBAAoB,KAAK;AAC/C,QAAM,gBAAgB,YAAY,OAAO,OAAO,OAAO,aAAa,GAAG;AACvE,SAAO;AAAA,IACL,QAAQ,OAAO;AAAA,IACf;AAAA,IACA,SAAS,QAAQ;AAAA,IACjB,WAAW,QAAQ;AAAA,IACnB,SAAS,OAAO,OAAO;AAAA;AAAA;AAAA,IAGvB,OAAO,EAAE,GAAG,eAAe,UAAU,cAAc,YAAY,OAAO,OAAO,SAAS;AAAA,EACxF;AACF;;;ACzcA,OAAOG,YAAU;AACjB,SAAS,cAAAC,oBAAkB;AAC3B,SAAS,YAAAC,kBAAgB;AACzB,SAAS,KAAAC,UAAS;AAUlB,IAAMC,aAAY;AAClB,IAAM,SAAS;AACf,IAAM,uBAAuB;AAE7B,IAAM,oBAAoBC,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE;AAAA,EAC1C,CAAC,UAAU,CAACC,OAAK,MAAM,WAAW,KAAK,KAAK,CAAC,MAAM,SAAS,IAAI;AAAA,EAChE;AACF;AAEO,IAAM,6BAA6B;AAAA,EACxC,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,cAAc;AAAA,EACd,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,0BAA0B;AAC5B;AAEO,IAAM,yBAAyBD,GAAE,OAAO;AAAA,EAC7C,kBAAkBA,GAAE,QAAQ;AAAA,EAC5B,uBAAuBA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAC7C,cAAcA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EACpC,sBAAsBA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC7C,yBAAyBA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAChD,qBAAqBA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC5C,qBAAqBA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EAC5C,0BAA0BA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AACnD,CAAC,EAAE,OAAO;AAIH,IAAM,4BAA4BA,GAAE,OAAO;AAAA,EAChD,QAAQA,GAAE,OAAO,EAAE,MAAMD,UAAS;AAAA,EAClC,OAAOC,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAC7B,QAAQA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAC9B,YAAYA,GAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;AAAA,EAClC,QAAQA,GAAE,MAAMA,GAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAAA,EACxC,cAAcA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EACrC,cAAcA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EACrC,aAAaA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EACpC,kBAAkBA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EACzC,oBAAoBA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC;AAC7C,CAAC,EAAE,OAAO;AAIV,IAAM,4BAA4BA,GAAE,OAAO;AAAA,EACzC,IAAIA,GAAE,OAAO,EAAE,MAAM,wBAAwB;AAAA,EAC7C,MAAM;AAAA,EACN,QAAQA,GAAE,OAAO;AAAA,IACf,MAAM;AAAA,IACN,QAAQA,GAAE,OAAO,EAAE,MAAMD,UAAS;AAAA,EACpC,CAAC,EAAE,OAAO,EAAE,SAAS;AAAA,EACrB,UAAU;AAAA,EACV,YAAY;AACd,CAAC,EAAE,OAAO;AAEH,IAAM,wBAAwBC,GAAE,OAAO;AAAA,EAC5C,SAASA,GAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AAAA,EACnC,QAAQA,GAAE,QAAQ,4BAA4B;AAAA,EAC9C,eAAeA,GAAE,QAAQ,CAAC;AAAA,EAC1B,OAAOA,GAAE,MAAM,yBAAyB,EAAE,IAAI,CAAC;AACjD,CAAC,EAAE,OAAO,EAAE,YAAY,CAAC,UAAU,YAAY;AAC7C,QAAM,MAAM,SAAS,MAAM,IAAI,CAAC,UAAU,MAAM,EAAE;AAClD,MAAI,IAAI,IAAI,GAAG,EAAE,SAAS,IAAI,QAAQ;AACpC,YAAQ,SAAS,EAAE,MAAMA,GAAE,aAAa,QAAQ,MAAM,CAAC,OAAO,GAAG,SAAS,oBAAoB,CAAC;AAAA,EACjG;AACF,CAAC;AAID,IAAM,qBAAqBA,GAAE,OAAO;AAAA,EAClC,IAAIA,GAAE,OAAO,EAAE,MAAM,wBAAwB;AAAA,EAC7C,MAAMA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,QAAQA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACnC,YAAY,uBAAuB,QAAQ,EAAE,SAAS;AACxD,CAAC,EAAE,OAAO;AAuCV,SAASE,SAAQ,OAAwB;AACvC,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAEA,SAAS,MAAM,OAAuB;AACpC,SAAO,OAAO,MAAM,QAAQ,CAAC,CAAC;AAChC;AAEA,SAAS,SAAS,QAAgB,QAAwB;AACxD,QAAM,QAAQ,OAAO,SAAS,CAAC;AAC/B,MAAI,UAAU,EAAG,QAAO;AACxB,UACI,OAAO,MAAM,KAAM,OAAQ,IAC5B,OAAO,SAAS,CAAC,KAAM,KACvB,OAAO,SAAS,CAAC,KAAM,IACxB,WACI;AACR;AAEA,SAAS,aAAa,QAAgB,GAAW,GAAmB;AAClE,QAAM,SAAS,OAAO,IAAI,CAAC;AAC3B,QAAM,SAAS,OAAO,IAAI,CAAC;AAC3B,QAAM,gBAAgB,KAAK,IAAI,SAAS,MAAM,IAAI;AAClD,MAAI,WAAW,KAAK,WAAW,EAAG,QAAO;AACzC,QAAM,cAAc;AAAA,IAClB,EAAE,GAAG,OAAO,CAAC,GAAI,GAAG,OAAO,IAAI,CAAC,GAAI,GAAG,OAAO,IAAI,CAAC,EAAG;AAAA,IACtD,EAAE,GAAG,OAAO,CAAC,GAAI,GAAG,OAAO,IAAI,CAAC,GAAI,GAAG,OAAO,IAAI,CAAC,EAAG;AAAA,EACxD,IAAI;AACJ,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,eAAe,WAAW,CAAC;AACzD;AAEO,SAAS,2BACd,KACAC,SACqB;AACrB,QAAM,SAAS,oBAAI,IAAY;AAC/B,MAAI,cAAc;AAClB,MAAI,eAAe;AACnB,MAAI,UAAU;AACd,MAAI,WAAW;AAEf,WAAS,SAAS,GAAG,SAAS,IAAI,OAAO,QAAQ,UAAU,GAAG;AAC5D,UAAM,QAAQ,IAAI,OAAO,SAAS,CAAC;AACnC,QAAI,UAAU,GAAG;AACf;AACA;AAAA,IACF;AACA;AACA,QAAI,QAAQ,IAAK;AACjB,WAAO,IAAK,IAAI,OAAO,MAAM,KAAM,KAAO,IAAI,OAAO,SAAS,CAAC,KAAM,IAAK,IAAI,OAAO,SAAS,CAAC,CAAE;AAEjG,UAAM,QAAQ,SAAS;AACvB,UAAM,IAAI,QAAQ,IAAI;AACtB,UAAM,IAAI,KAAK,MAAM,QAAQ,IAAI,KAAK;AACtC,UAAM,MAAM,SAAS,IAAI,QAAQ,MAAM;AACvC,UAAM,kBACH,IAAI,KAAK,SAAS,IAAI,QAAQ,SAAS,CAAC,MAAM,OAC9C,IAAI,IAAI,IAAI,SAAS,SAAS,IAAI,QAAQ,SAAS,CAAC,MAAM,OAC1D,IAAI,KAAK,SAAS,IAAI,QAAQ,SAAS,IAAI,QAAQ,CAAC,MAAM,OAC1D,IAAI,IAAI,IAAI,UAAU,SAAS,IAAI,QAAQ,SAAS,IAAI,QAAQ,CAAC,MAAM;AAC1E,QAAI,CAAC,iBAAiB;AACpB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,gBAAgB;AACpB,MAAI,eAAe;AACnB,MAAI,gBAAgB;AACpB,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,aAAS,IAAI,GAAG,IAAI,IAAI,OAAO,KAAK;AAClC,YAAM,UAAU,IAAI,IAAI,QAAQ,KAAK;AACrC,UAAI,IAAI,IAAI,IAAI,OAAO;AACrB,cAAM,WAAW,SAAS;AAC1B;AACA,YAAI,SAAS,IAAI,QAAQ,MAAM,MAAM,SAAS,IAAI,QAAQ,QAAQ,GAAG;AACnE;AACA,2BAAiB,aAAa,IAAI,QAAQ,QAAQ,QAAQ;AAAA,QAC5D;AAAA,MACF;AACA,UAAI,IAAI,IAAI,IAAI,QAAQ;AACtB,cAAM,WAAW,SAAS,IAAI,QAAQ;AACtC;AACA,YAAI,SAAS,IAAI,QAAQ,MAAM,MAAM,SAAS,IAAI,QAAQ,QAAQ,GAAG;AACnE;AACA,2BAAiB,aAAa,IAAI,QAAQ,QAAQ,QAAQ;AAAA,QAC5D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,IAAI,QAAQ,IAAI;AAC9B,SAAO;AAAA,IACL,QAAQA;AAAA,IACR,OAAO,IAAI;AAAA,IACX,QAAQ,IAAI;AAAA,IACZ,YAAY,OAAO;AAAA,IACnB,QAAQ,CAAC,GAAG,MAAM,EACf,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,EACpB,IAAI,CAAC,UAAU,IAAI,MAAM,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE;AAAA,IAC3D,cAAc,MAAM,QAAQ,cAAc,QAAQ,CAAC;AAAA,IACnD,cAAc,MAAM,QAAQ,eAAe,QAAQ,CAAC;AAAA,IACpD,aAAa,MAAM,gBAAgB,eAAe,gBAAgB,CAAC;AAAA,IACnE,kBAAkB,MAAM,eAAe,gBAAgB,eAAe,CAAC;AAAA,IACvE,oBAAoB,MAAM,UAAU,WAAW,UAAU,CAAC;AAAA,EAC5D;AACF;AAEA,eAAsB,oBAAoB,MAA4C;AACpF,QAAM,WAAWF,OAAK,QAAQ,IAAI;AAClC,MAAI;AACJ,MAAI;AACF,YAAQ,MAAMG,WAAS,QAAQ;AAAA,EACjC,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,6BAA6B,QAAQ,KAAKF,SAAQ,KAAK,CAAC,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,EAC9F;AACA,MAAI;AACF,WAAO,2BAA2B,UAAU,KAAK,GAAG,OAAO,KAAK,CAAC;AAAA,EACnE,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,gCAAgC,QAAQ,KAAKA,SAAQ,KAAK,CAAC,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,EACjG;AACF;AAEO,SAAS,qBAAqB,KAAc,gBAAgD;AACjG,QAAM,SAASF,GAAE,MAAM,kBAAkB,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG;AAC/D,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI;AAAA,MACR,gEACE,OAAO,MAAM,OAAO,IAAI,CAAC,UAAU,KAAK,MAAM,KAAK,KAAK,GAAG,KAAK,GAAG,KAAK,MAAM,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,IACtG;AAAA,EACF;AACA,QAAM,MAAM,OAAO,KAAK,IAAI,CAAC,UAAU,MAAM,EAAE;AAC/C,MAAI,IAAI,IAAI,GAAG,EAAE,SAAS,IAAI,OAAQ,OAAM,IAAI,MAAM,gDAAgD;AACtG,QAAM,OAAOC,OAAK,QAAQA,OAAK,QAAQ,cAAc,CAAC;AACtD,SAAO,OAAO,KAAK,IAAI,CAAC,WAAW;AAAA,IACjC,IAAI,MAAM;AAAA,IACV,MAAMA,OAAK,QAAQ,MAAM,MAAM,IAAI;AAAA,IACnC,GAAI,MAAM,SAAS,EAAE,QAAQA,OAAK,QAAQ,MAAM,MAAM,MAAM,EAAE,IAAI,CAAC;AAAA,IACnE,YAAY,uBAAuB,MAAM;AAAA,MACvC,GAAG;AAAA,MACH,GAAG,MAAM;AAAA,IACX,CAAC;AAAA,EACH,EAAE;AACJ;AAEA,SAASI,kBAAiB,MAAc,IAAoB;AAC1D,SAAOJ,OAAK,SAAS,MAAMA,OAAK,QAAQ,EAAE,CAAC,EAAE,MAAMA,OAAK,GAAG,EAAE,KAAK,GAAG,KAAK;AAC5E;AAEA,eAAe,qBAAqB,YAAoB,WAAkC;AACxF,QAAM,eAAe,MAAM,qBAAqB,UAAU;AAC1D,MAAI,CAAC,aAAa,SAAS;AACzB,UAAM,UAAU,CAAC,GAAG,aAAa,gBAAgB,GAAG,aAAa,cAAc;AAC/E,UAAM,IAAI;AAAA,MACR,kCAAkC,UAAU,MACzC,QAAQ,SAAS,KAAK,QAAQ,KAAK,IAAI,CAAC,MAAM;AAAA,IACnD;AAAA,EACF;AACA,QAAM,SAAS,MAAM,2BAA2B,UAAU;AAC1D,QAAM,UAAU,OAAO;AACvB,MACE,OAAO,SAAS,YAChB,YAAY,QACZ,OAAO,YAAY,YAClB,QAAiC,WAAW,qBAC7C;AACA,UAAM,IAAI,MAAM,kBAAkB,UAAU,wCAAwC;AAAA,EACtF;AACA,QAAM,UAAU,OAAO,QAAQ,IAAI,CAAC,WAAWA,OAAK,QAAQA,OAAK,QAAQ,UAAU,GAAG,OAAO,IAAI,CAAC;AAClG,MAAI,CAAC,QAAQ,SAASA,OAAK,QAAQ,SAAS,CAAC,GAAG;AAC9C,UAAM,IAAI,MAAM,kBAAkB,UAAU,iBAAiB,SAAS,GAAG;AAAA,EAC3E;AACF;AAEA,eAAsB,wBACpB,QACA,cACA,UAA+B,CAAC,GACA;AAChC,MAAI,CAAC,OAAO,OAAQ,OAAM,IAAI,MAAM,4CAA4C;AAChF,QAAM,WAAWA,OAAK,QAAQ,YAAY;AAC1C,aAAW,SAAS,QAAQ;AAC1B,QACEA,OAAK,QAAQ,MAAM,IAAI,MAAM,YAC5B,MAAM,UAAUA,OAAK,QAAQ,MAAM,MAAM,MAAM,UAChD;AACA,YAAM,IAAI,MAAM,qDAAqD,QAAQ,GAAG;AAAA,IAClF;AAAA,EACF;AACA,QAAM,OAAOA,OAAK,QAAQ,QAAQ;AAClC,QAAM,QAAQ,CAAC;AACf,aAAW,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,GAAG,cAAc,EAAE,EAAE,CAAC,GAAG;AACxE,UAAM,WAAW,MAAM,oBAAoB,MAAM,IAAI;AACrD,QAAI;AACJ,QAAI,MAAM,QAAQ;AAChB,YAAM,qBAAqB,MAAM,QAAQ,MAAM,IAAI;AACnD,eAAS;AAAA,QACP,MAAMI,kBAAiB,MAAM,MAAM,MAAM;AAAA,QACzC,QAAQ,MAAM,WAAW,MAAM,MAAM;AAAA,MACvC;AAAA,IACF;AACA,UAAM,KAAK;AAAA,MACT,IAAI,MAAM;AAAA,MACV,MAAMA,kBAAiB,MAAM,MAAM,IAAI;AAAA,MACvC,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B;AAAA,MACA,YAAY,MAAM;AAAA,IACpB,CAAC;AAAA,EACH;AACA,QAAM,WAAW,sBAAsB,MAAM;AAAA,IAC3C,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,eAAe;AAAA,IACf;AAAA,EACF,CAAC;AACD,QAAM,OAAO,OAAO,KAAK,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AACjE,MAAIC,aAAW,QAAQ,KAAK,CAAC,QAAQ,OAAO;AAC1C,UAAM,UAAU,MAAMF,WAAS,QAAQ;AACvC,QAAI,CAAC,QAAQ,OAAO,IAAI,GAAG;AACzB,YAAM,IAAI,MAAM,2DAA2D,QAAQ,+BAA+B;AAAA,IACpH;AAAA,EACF;AACA,QAAM,SAAS,MAAM,oBAAoB,CAAC,EAAE,MAAM,UAAU,KAAK,CAAC,CAAC;AACnE,SAAO,EAAE,UAAU,MAAM,UAAU,SAAS,OAAO,QAAQ,SAAS,EAAE;AACxE;AAEA,eAAsB,oBAAoB,cAAgD;AACxF,QAAM,WAAWH,OAAK,QAAQ,YAAY;AAC1C,MAAI;AACJ,MAAI;AACF,UAAM,KAAK,MAAM,MAAMG,WAAS,UAAU,MAAM,CAAC;AAAA,EACnD,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,mCAAmC,QAAQ,KAAKF,SAAQ,KAAK,CAAC,IAAI,EAAE,OAAO,MAAM,CAAC;AAAA,EACpG;AACA,QAAM,SAAS,sBAAsB,UAAU,GAAG;AAClD,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,IAAI;AAAA,MACR,4BAA4B,QAAQ;AAAA,IAClC,OAAO,MAAM,OAAO,IAAI,CAAC,UAAU,KAAK,MAAM,KAAK,KAAK,GAAG,KAAK,GAAG,KAAK,MAAM,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,IACtG;AAAA,EACF;AACA,SAAO,OAAO;AAChB;AAEA,SAAS,qBACP,UACA,QACA,YAC8C;AAC9C,QAAM,aAAuB,CAAC;AAC9B,QAAM,WAAqB,CAAC;AAC5B,QAAM,UAAU,OAAO,WAAW,SAAS;AAC3C,MAAI,SAAS,UAAU,OAAO,SAAS,SAAS,WAAW,OAAO,QAAQ;AACxE,eAAW;AAAA,MACT,2BAA2B,SAAS,KAAK,IAAI,SAAS,MAAM,OAAO,OAAO,KAAK,IAAI,OAAO,MAAM;AAAA,IAClG;AAAA,EACF;AACA,MAAI,WAAW,WAAW,iBAAkB,YAAW,KAAK,oBAAoB;AAAA,WACvE,QAAS,UAAS,KAAK,wDAAwD;AAExF,QAAM,gBAAgB,OAAO,aAAa,SAAS;AACnD,MAAI,gBAAgB,WAAW,uBAAuB;AACpD,eAAW;AAAA,MACT,4BAA4B,aAAa,aAAa,WAAW,qBAAqB;AAAA,IACxF;AAAA,EACF;AACA,QAAM,iBAAiB,IAAI,IAAI,SAAS,MAAM;AAC9C,QAAM,YAAY,OAAO,OAAO,OAAO,CAAC,UAAU,CAAC,eAAe,IAAI,KAAK,CAAC;AAC5E,MAAI,UAAU,SAAS,WAAW,cAAc;AAC9C,eAAW;AAAA,MACT,GAAG,UAAU,MAAM,wBAAwB,WAAW,YAAY,KAAK,UAAU,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC;AAAA,IACzG;AAAA,EACF;AACA,QAAM,oBAAoB,KAAK,IAAI,OAAO,eAAe,SAAS,YAAY;AAC9E,MAAI,oBAAoB,WAAW,sBAAsB;AACvD,eAAW;AAAA,MACT,4BAA4B,oBAAoB,KAAK,QAAQ,CAAC,CAAC,qBAChD,WAAW,uBAAuB,KAAK,QAAQ,CAAC,CAAC;AAAA,IAClE;AAAA,EACF;AACA,QAAM,uBAAuB,OAAO,eAAe,SAAS;AAC5D,MAAI,uBAAuB,WAAW,yBAAyB;AAC7D,eAAW;AAAA,MACT,sCAAsC,uBAAuB,KAAK,QAAQ,CAAC,CAAC,qBAC7D,WAAW,0BAA0B,KAAK,QAAQ,CAAC,CAAC;AAAA,IACrE;AAAA,EACF;AACA,QAAM,mBAAmB,KAAK,IAAI,OAAO,cAAc,SAAS,WAAW;AAC3E,MAAI,mBAAmB,WAAW,qBAAqB;AACrD,eAAW;AAAA,MACT,4BAA4B,mBAAmB,KAAK,QAAQ,CAAC,CAAC,qBAC/C,WAAW,sBAAsB,KAAK,QAAQ,CAAC,CAAC;AAAA,IACjE;AAAA,EACF;AACA,QAAM,mBAAmB,SAAS,mBAAmB,OAAO;AAC5D,MAAI,mBAAmB,WAAW,qBAAqB;AACrD,eAAW;AAAA,MACT,kCAAkC,mBAAmB,KAAK,QAAQ,CAAC,CAAC,qBACrD,WAAW,sBAAsB,KAAK,QAAQ,CAAC,CAAC;AAAA,IACjE;AAAA,EACF;AACA,QAAM,mBAAmB,OAAO,qBAAqB,SAAS;AAC9D,MAAI,mBAAmB,WAAW,0BAA0B;AAC1D,eAAW;AAAA,MACT,sCAAsC,mBAAmB,KAAK,QAAQ,CAAC,CAAC,qBACzD,WAAW,2BAA2B,KAAK,QAAQ,CAAC,CAAC;AAAA,IACtE;AAAA,EACF;AACA,SAAO,EAAE,YAAY,SAAS;AAChC;AAEA,eAAsB,qBAAqB,cAAwD;AACjG,QAAM,WAAWD,OAAK,QAAQ,YAAY;AAC1C,QAAM,WAAW,MAAM,oBAAoB,QAAQ;AACnD,QAAM,OAAOA,OAAK,QAAQ,QAAQ;AAClC,QAAM,QAAuC,CAAC;AAE9C,aAAW,SAAS,SAAS,OAAO;AAClC,UAAM,OAAOA,OAAK,QAAQ,MAAM,MAAM,IAAI;AAC1C,QAAI,SAAqC;AACzC,UAAM,aAAuB,CAAC;AAC9B,UAAM,WAAqB,CAAC;AAC5B,QAAI;AACF,eAAS,MAAM,oBAAoB,IAAI;AACvC,YAAM,aAAa,qBAAqB,MAAM,UAAU,QAAQ,MAAM,UAAU;AAChF,iBAAW,KAAK,GAAG,WAAW,UAAU;AACxC,eAAS,KAAK,GAAG,WAAW,QAAQ;AAAA,IACtC,SAAS,OAAO;AACd,iBAAW,KAAKC,SAAQ,KAAK,CAAC;AAAA,IAChC;AAEA,QAAI,MAAM,QAAQ;AAChB,YAAM,aAAaD,OAAK,QAAQ,MAAM,MAAM,OAAO,IAAI;AACvD,UAAI;AACF,cAAM,aAAa,MAAM,WAAW,UAAU;AAC9C,YAAI,eAAe,MAAM,OAAO,OAAQ,YAAW,KAAK,6BAA6B;AACrF,cAAM,qBAAqB,YAAY,IAAI;AAAA,MAC7C,SAAS,OAAO;AACd,mBAAW,KAAKC,SAAQ,KAAK,CAAC;AAAA,MAChC;AAAA,IACF;AAEA,UAAM,KAAK;AAAA,MACT,IAAI,MAAM;AAAA,MACV;AAAA,MACA,QAAQ,WAAW,SAAS,SAAS;AAAA,MACrC,aAAa,WAAW,QAAQ,OAAO,WAAW,MAAM,SAAS;AAAA,MACjE,UAAU,MAAM;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AAEA,QAAM,SAAS,MAAM,OAAO,CAAC,UAAU,MAAM,WAAW,MAAM,EAAE;AAChE,SAAO;AAAA,IACL,SAAS;AAAA,IACT,MAAM,WAAW;AAAA,IACjB,UAAU;AAAA,IACV,SAAS;AAAA,MACP,OAAO,MAAM;AAAA,MACb,QAAQ,MAAM,SAAS;AAAA,MACvB;AAAA,MACA,SAAS,MAAM,OAAO,CAAC,UAAU,MAAM,WAAW,EAAE;AAAA,IACtD;AAAA,IACA;AAAA,EACF;AACF;;;A1CzZA,IAAM,MAAM,CAAC,MAAM,OAAO,QAAQ,IAAI,GAAG;AAYlC,SAAS,oBACd,MACA,SAAsB,QAAQ,QAC9B,SAAsB,QAAQ,QACxB;AACN,QAAM,SAAS,OAAO,QAAQ,SAAS;AACvC,QAAM,QAAQ,KAAK,KAAK;AACxB,SAAO;AAAA,IACL;AAAA,IAAO,KAAK,SAAS,UAAU,IAAI,KAAK,GAAG,wBAAwB,KAAK,GAAG;AAAA;AAAA;AAAA;AAAA,EAE7E;AACF;AAEA,eAAe,eAAe,IAAY,MAAuC;AAC/E,QAAM,WAAWK,OAAK,QAAQ,IAAI;AAClC,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,QAAQC,aAAW,QAAQ,IAAI,MAAM,WAAW,QAAQ,IAAI;AAAA,IAC5D,UAAU;AAAA,EACZ;AACF;AAgEA,IAAM,cAAc;AAAA,EAClB;AAAA,EAAc;AAAA,EAAU;AAAA,EAAW;AAAA,EAAU;AAAA,EAAY;AAAA,EACzD;AAAA,EAAU;AAAA,EAAS;AAAA,EAAe;AAAA,EAAa;AAAA,EAAU;AAAA,EAAY;AAAA,EAAa;AAAA,EAAY;AAAA,EAC9F;AAAA,EAAiB;AAAA,EAAkB;AAAA,EAAsB;AAAA,EAAgB;AAAA,EAAW;AAAA,EACpF;AAAA,EAAc;AAAA,EAAa;AAAA,EAAa;AAAA,EAAkB;AAAA,EAAoB;AAAA,EAC9E;AAAA,EAAc;AAAA,EACd;AACF;AACA,IAAM,aAAa;AAAA,EACjB;AAAA,EAAW;AAAA,EAAS;AAAA,EAAM;AAAA,EAAa;AAAA,EAAS;AAAA,EAAU;AAAA,EAAW;AAAA,EAAa;AAAA,EAAS;AAAA,EAAmB;AAAA,EAAkB;AAClI;AAEO,IAAM,WAAW;AAAA,EACtB;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAU;AAAA,EAAO;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAW;AAAA,EAAS;AAAA,EACxF;AAAA,EAAW;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAU;AAAA,EAAO;AAAA,EAAW;AAAA,EAC5F;AAAA,EAAW;AAAA,EAAU;AAAA,EAAU;AAAA,EAAa;AAAA,EAAQ;AAAA,EAAU;AAAA,EAAM;AAAA,EAAa;AACnF;AAEA,IAAM,wBAAwB,CAAC,OAAO,UAAU,QAAQ,UAAU,QAAQ;AAC1E,IAAM,qBAAqB,CAAC,OAAO,WAAW,OAAO;AACrD,IAAM,qBAAqB,CAAC,QAAQ,WAAW,WAAW,QAAQ;AAClE,IAAM,sBAAsB,CAAC,YAAY,OAAO;AAQzC,SAAS,UAAU,MAAsB;AAC9C,QAAM,CAAC,UAAU,MAAM,IAAI;AAC3B,MAAI,CAAE,SAA+B,SAAS,OAAO,GAAG;AACtD,UAAM,IAAI,MAAM,oBAAoB,OAAO,yCAAyC;AAAA,EACtF;AAEA,MAAI,OAAO,KAAK,MAAM,CAAC;AACvB,MAAI;AACJ,MAAI;AACJ,MAAI,YAAY,WAAW;AACzB,iBAAa,KAAK,CAAC;AACnB,QAAI,eAAe,UAAa,WAAW,WAAW,GAAG,GAAG;AAC1D,YAAM,IAAI,MAAM,+BAA+B,oBAAoB,KAAK,IAAI,CAAC,EAAE;AAAA,IACjF;AACA,QAAI,CAAE,oBAA0C,SAAS,UAAU,GAAG;AACpE,YAAM,IAAI;AAAA,QACR,+BAA+B,UAAU,aAAa,oBAAoB,KAAK,IAAI,CAAC;AAAA,MACtF;AAAA,IACF;AACA,WAAO,KAAK,MAAM,CAAC;AAAA,EACrB,WAAW,YAAY,UAAU;AAC/B,iBAAa,KAAK,CAAC;AACnB,QAAI,eAAe,UAAa,WAAW,WAAW,GAAG,GAAG;AAC1D,YAAM,IAAI,MAAM,8BAA8B,mBAAmB,KAAK,IAAI,CAAC,EAAE;AAAA,IAC/E;AACA,QAAI,CAAE,mBAAyC,SAAS,UAAU,GAAG;AACnE,YAAM,IAAI;AAAA,QACR,8BAA8B,UAAU,aAAa,mBAAmB,KAAK,IAAI,CAAC;AAAA,MACpF;AAAA,IACF;AACA,WAAO,KAAK,MAAM,CAAC;AACnB,QAAI,eAAe,QAAQ;AACzB,eAAS,KAAK,CAAC;AACf,UAAI,WAAW,UAAa,OAAO,WAAW,GAAG,GAAG;AAClD,cAAM,IAAI,MAAM,UAAU,UAAU,wCAAwC;AAAA,MAC9E;AACA,aAAO,KAAK,MAAM,CAAC;AAAA,IACrB;AAAA,EACF,WAAW,YAAY,aAAa;AAClC,iBAAa,KAAK,CAAC;AACnB,QAAI,eAAe,UAAa,WAAW,WAAW,GAAG,GAAG;AAC1D,YAAM,IAAI,MAAM,iCAAiC,sBAAsB,KAAK,IAAI,CAAC,EAAE;AAAA,IACrF;AACA,QAAI,CAAE,sBAA4C,SAAS,UAAU,GAAG;AACtE,YAAM,IAAI;AAAA,QACR,iCAAiC,UAAU,aAAa,sBAAsB,KAAK,IAAI,CAAC;AAAA,MAC1F;AAAA,IACF;AACA,WAAO,KAAK,MAAM,CAAC;AACnB,QAAI,eAAe,SAAS,eAAe,UAAU;AACnD,eAAS,KAAK,CAAC;AACf,UAAI,WAAW,UAAa,OAAO,WAAW,GAAG,GAAG;AAClD,cAAM,IAAI;AAAA,UACR,eAAe,QACX,yCACA;AAAA,QACN;AAAA,MACF;AACA,aAAO,KAAK,MAAM,CAAC;AAAA,IACrB;AAAA,EACF,WAAW,YAAY,UAAU;AAC/B,iBAAa,KAAK,CAAC,GAAG,WAAW,GAAG,KAAK,KAAK,CAAC,MAAM,SAAY,QAAQ,KAAK,CAAC;AAC/E,QAAI,CAAE,mBAAyC,SAAS,UAAU,GAAG;AACnE,YAAM,IAAI;AAAA,QACR,8BAA8B,UAAU,aAAa,mBAAmB,KAAK,IAAI,CAAC;AAAA,MACpF;AAAA,IACF;AACA,QAAI,KAAK,CAAC,MAAM,WAAY,QAAO,KAAK,MAAM,CAAC;AAAA,EACjD;AAEA,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,QAAQ,KAAK,CAAC;AACpB,QAAI,CAAC,MAAM,WAAW,GAAG,GAAG;AAC1B,YAAM,IAAI,MAAM,wBAAwB,KAAK,8CAA8C;AAAA,IAC7F;AACA,QAAK,WAAiC,SAAS,KAAK,EAAG;AACvD,QAAK,YAAkC,SAAS,KAAK,GAAG;AACtD,YAAM,QAAQ,KAAK,IAAI,CAAC;AAGxB,YAAM,gBAAgB,UAAU,UAAa,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,SAAS,OAAO,KAAK,CAAC;AACpG,UAAI,UAAU,UAAa,eAAe;AACxC,cAAM,IAAI,MAAM,GAAG,KAAK,iBAAiB;AAAA,MAC3C;AACA;AACA;AAAA,IACF;AACA,UAAM,IAAI;AAAA,MACR,iBAAiB,KAAK,mBAAmB,CAAC,GAAG,aAAa,GAAG,UAAU,EAAE,KAAK,IAAI,CAAC;AAAA,IACrF;AAAA,EACF;AAEA,QAAM,MAAM,CAAC,SAAiB;AAC5B,UAAM,IAAI,KAAK,QAAQ,IAAI;AAC3B,WAAO,KAAK,IAAI,KAAK,IAAI,CAAC,IAAI;AAAA,EAChC;AASA,QAAM,OAAO,CAAC,SAAiB;AAC7B,UAAM,MAAgB,CAAC;AACvB,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAI,KAAK,CAAC,MAAM,KAAM;AACtB,iBAAW,SAAS,KAAK,IAAI,CAAC,KAAK,IAAI,MAAM,GAAG,GAAG;AACjD,cAAM,IAAI,KAAK,KAAK;AACpB,YAAI,EAAG,KAAI,KAAK,CAAC;AAAA,MACnB;AAAA,IACF;AACA,WAAO,CAAC,GAAG,IAAI,IAAI,GAAG,CAAC;AAAA,EACzB;AAEA,QAAM,aAAa,IAAI,WAAW;AAClC,MAAI;AACJ,MAAI,eAAe,QAAW;AAC5B,cAAU,OAAO,UAAU;AAG3B,QAAI,CAAC,OAAO,UAAU,OAAO,KAAK,UAAU,KAAK,UAAU,MAAM;AAC/D,YAAM,IAAI,MAAM,6DAA6D,UAAU,GAAG;AAAA,IAC5F;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,QAAQ;AAC5B,MAAI;AACJ,MAAI,YAAY,QAAW;AACzB,WAAO,OAAO,OAAO;AACrB,QAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAAQ;AACxD,YAAM,IAAI,MAAM,2DAA2D,OAAO,GAAG;AAAA,IACvF;AAAA,EACF;AAEA,MAAI;AAIJ,QAAM,kBAA0C,uBAAO,OAAO,IAAI;AAClE,QAAM,aAAa,KAAK,QAAQ,CAAC,OAAO,UAAU,UAAU,aAAa,CAAC,KAAK,QAAQ,CAAC,CAAE,IAAI,CAAC,CAAC;AAChG,aAAW,aAAa,YAAY;AAClC,UAAM,YAAY,UAAU,QAAQ,GAAG;AACvC,QAAI,aAAa,GAAG;AAClB,YAAM,aAAa,UAAU,MAAM,GAAG,SAAS,EAAE,KAAK;AACtD,YAAM,YAAY,UAAU,MAAM,YAAY,CAAC,EAAE,KAAK;AACtD,YAAMC,UAAS,OAAO,SAAS;AAC/B,UAAI,CAAC,cAAc,QAAQ,KAAK,UAAU,KAAK,CAAC,OAAO,SAASA,OAAM,KAAKA,UAAS,GAAG;AACrF,cAAM,IAAI;AAAA,UACR,mEAAmE,SAAS;AAAA,QAC9E;AAAA,MACF;AACA,UAAI,OAAO,OAAO,iBAAiB,UAAU,GAAG;AAC9C,cAAM,IAAI,MAAM,8BAA8B,UAAU,IAAI;AAAA,MAC9D;AACA,sBAAgB,UAAU,IAAIA;AAC9B;AAAA,IACF;AACA,UAAM,SAAS,OAAO,SAAS;AAC/B,QAAI,CAAC,OAAO,SAAS,MAAM,KAAK,SAAS,GAAG;AAC1C,YAAM,IAAI,MAAM,gDAAgD,SAAS,IAAI;AAAA,IAC/E;AACA,QAAI,WAAW,OAAW,OAAM,IAAI,MAAM,0CAA0C;AACpF,aAAS;AAAA,EACX;AACA,MAAI,WAAW,UAAa,OAAO,KAAK,eAAe,EAAE,QAAQ;AAC/D,UAAM,IAAI,MAAM,6DAA6D;AAAA,EAC/E;AAEA,QAAM,WAAW,IAAI,YAAY,KAAK;AACtC,QAAM,YAAY,IAAI,UAAU;AAChC,MAAI,aAAa,cAAc,aAAa,cAAc,WAAW,cAAc,SAAS;AAC1F,UAAM,IAAI,MAAM,mDAAmD,SAAS,GAAG;AAAA,EACjF;AACA,QAAM,eAAe,CACnB,MACA,SACuB;AACvB,UAAM,MAAM,IAAI,IAAI;AACpB,QAAI,QAAQ,OAAW,QAAO;AAC9B,UAAM,QAAQ,OAAO,GAAG;AACxB,QACE,CAAC,OAAO,SAAS,KAAK,KACtB,QAAQ,KAAK,OACZ,KAAK,QAAQ,UAAa,QAAQ,KAAK,OACvC,KAAK,WAAW,CAAC,OAAO,UAAU,KAAK,GACxC;AACA,YAAM,QAAQ,KAAK,QAAQ,SAAY,YAAY,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,OAAO,KAAK,GAAG;AAC1F,YAAM,IAAI,MAAM,GAAG,IAAI,YAAY,KAAK,UAAU,oBAAoB,WAAW,GAAG,KAAK,UAAU,GAAG,GAAG;AAAA,IAC3G;AACA,WAAO;AAAA,EACT;AACA,QAAM,oBAAoB,IAAI,uBAAuB;AACrD,MACE,sBAAsB,UACtB,sBAAsB,SAAS,sBAAsB,YAAY,sBAAsB,QACvF;AACA,UAAM,IAAI;AAAA,MACR,4DAA4D,iBAAiB;AAAA,IAC/E;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM,IAAI,QAAQ,KAAKF,OAAK,KAAKA,OAAK,QAAQA,OAAK,QAAQ,QAAQ,CAAC,GAAG,qBAAqB;AAAA,IAC5F,cAAc,IAAI,QAAQ;AAAA,IAC1B,QAAQ,KAAK,SAAS;AAAA,IACtB,QAAQ,KAAK,QAAQ;AAAA,IACrB,OAAO,KAAK,SAAS,SAAS;AAAA,IAC9B,KAAK,KAAK,SAAS,OAAO,KAAK,KAAK,SAAS,IAAI;AAAA,IACjD;AAAA,IACA;AAAA,IACA,QAAQ,KAAK,SAAS,WAAW;AAAA,IACjC,KAAK,KAAK,SAAS,OAAO;AAAA,IAC1B,MAAM,KAAK,SAAS,QAAQ;AAAA,IAC5B,OAAO,KAAK,SAAS,SAAS;AAAA,IAC9B,QAAQ,KAAK,SAAS,WAAW;AAAA,IACjC,KAAK,KAAK,SAAS,OAAO;AAAA,IAC1B,MAAM,IAAI,QAAQ;AAAA,IAClB,KAAK,IAAI,OAAO;AAAA,IAChB,WAAW,IAAI,aAAa;AAAA,IAC5B,SAAS,KAAK,WAAW;AAAA,IACzB,MAAM,IAAI,QAAQ;AAAA,IAClB,cAAc,KAAK,SAAS,iBAAiB;AAAA,IAC7C;AAAA,IACA;AAAA,IACA,QAAQ,IAAI,UAAU;AAAA,IACtB,QAAQ,KAAK,UAAU;AAAA,IACvB,QAAQ;AAAA,IACR,aAAa,KAAK,eAAe;AAAA,IACjC,aAAa,KAAK,SAAS,gBAAgB;AAAA,IAC3C,OAAO,KAAK,SAAS,SAAS;AAAA,IAC9B,aAAa,aAAa,kBAAkB,EAAE,KAAK,EAAE,CAAC;AAAA,IACtD,iBAAiB,aAAa,sBAAsB,EAAE,KAAK,GAAG,KAAK,EAAE,CAAC;AAAA,IACtE,WAAW,aAAa,gBAAgB,EAAE,KAAK,GAAG,SAAS,KAAK,CAAC;AAAA,IACjE,OAAO,aAAa,WAAW,EAAE,KAAK,OAAO,QAAQ,CAAC;AAAA,IACtD,SAAS,KAAK,WAAW;AAAA,IACzB,aAAa,IAAI,gBAAgB;AAAA,IACjC,eAAe,IAAI,kBAAkB;AAAA,IACrC,mBAAmB;AAAA,IACnB,UAAU,IAAI,YAAY;AAAA,IAC1B,MAAM,IAAI,QAAQ;AAAA,IAClB,WAAW,IAAI,cAAc;AAAA,IAC7B;AAAA,IACA,WAAW,IAAI,aAAa;AAAA,IAC5B;AAAA,IACA,UAAU,IAAI,YAAY;AAAA,IAC1B,SAAS,IAAI,WAAW;AAAA,EAC1B;AACF;AAEA,IAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqGb,SAAS,UAAU,MAAkB;AACnC,QAAM,SAAS,UAAU,IAAI;AAC7B,QAAM,QAAQ;AAAA,IACZ;AAAA,IAAW;AAAA,IAAW;AAAA,IAAa;AAAA,IAAS;AAAA,IAAU;AAAA,IAAe;AAAA,IAAa;AAAA,IAAY;AAAA,EAChG;AACA,aAAW,SAAS,OAAO;AACzB,UAAM,QAAQ,KAAK,MAAM,OAAO,CAAC,MAAM,EAAE,UAAU,KAAK;AACxD,QAAI,CAAC,MAAM,OAAQ;AACnB,QAAI;AAAA,IAAO,KAAK,MAAM,MAAM,MAAM,GAAG;AACrC,eAAW,QAAQ,MAAM,MAAM,GAAG,EAAE,GAAG;AACrC,UAAI,OAAO,KAAK,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,MAAM,EAAE;AAAA,IACjD;AACA,QAAI,MAAM,SAAS,GAAI,KAAI,kBAAa,MAAM,SAAS,EAAE,OAAO;AAAA,EAClE;AACA;AAAA,IACE;AAAA,YAAe,OAAO,EAAE,YAAS,OAAO,OAAO,iBAAc,OAAO,OAAO,iBAAc,OAAO,SAAS,mBACpG,OAAO,KAAK,eAAY,OAAO,WAAW,CAAC,mBAAgB,OAAO,QAAQ,kBAC1E,OAAO,WAAW,qBAAkB,OAAO,MAAM;AAAA,EACxD;AACA,MAAI,KAAK,WAAW,QAAQ;AAC1B,eAAW,SAAS,KAAK,QAAQ;AAC/B;AAAA,QACE,KAAK,MAAM,QAAQ,KAAK,MAAM,WAAW,MAAM,oBAC1C,WAAW,MAAM,UAAU,MAAM,IAAI,CAAC,KACtC,MAAM,UAAU;AAAA,MACvB;AAAA,IACF;AAAA,EACF,OAAO;AACL,QAAI,uBAAuB;AAAA,EAC7B;AACA,QAAM,eAAe,KAAK,MAAM,QAAQ,CAAC,SAAS,KAAK,UAAU,CAAC,KAAK,OAAO,IAAI,CAAC,CAAC;AACpF,MAAI,aAAa,QAAQ;AACvB,UAAM,WAAW,aAAa,OAAO,CAAC,SAAS,KAAK,UAAU,UAAU,EAAE;AAC1E,QAAI;AAAA,aAAgB,QAAQ,IAAI,aAAa,MAAM,WAAW;AAC9D,eAAW,QAAQ,aAAa,OAAO,CAACG,UAASA,MAAK,UAAU,UAAU,EAAE,MAAM,GAAG,EAAE,GAAG;AACxF,UAAI,OAAO,KAAK,MAAM,OAAO,EAAE,CAAC,IAAI,KAAK,GAAG,KAAK,KAAK,MAAM,EAAE;AAAA,IAChE;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,OAAuB,MAAoB;AACrE,QAAM,UAAU,cAAc,OAAO,IAAI;AACzC,aAAW,UAAU,SAAS;AAC5B,UAAM,QAAQ,OAAO,KAAK,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI;AAC/C,UAAM,OAAO,OAAO,KAAK,SAAS,IAAI,MAAM,OAAO,KAAK,SAAS,CAAC,UAAU;AAC5E;AAAA,MACE,qBAAqB,OAAO,OAAO,WAAM,OAAO,KAAK,MAAM,SACtD,OAAO,KAAK,WAAW,IAAI,KAAK,GAAG,KAAK,KAAK,GAAG,IAAI;AAAA,IAC3D;AAAA,EACF;AACA,SAAO,QAAQ;AACjB;AAEA,SAAS,oBAAoB,UAA8B;AACzD,SAAO,CAAC,GAAG,IAAI;AAAA,IACb,OAAO,OAAO,SAAS,MAAM,EAAE,IAAI,CAAC,UAAU,MAAM,YAAY,SAAS,QAAQ;AAAA,EACnF,CAAC,EAAE,KAAK;AACV;AAEA,SAAS,wBAAwB,OAAuB,MAAyC;AAC/F,QAAM,UAAU,oBAAI,IAA4B;AAChD,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,QAAQ,KAAK,SAAS,KAAK,OAAO;AAC9C,UAAM,WAAW,KAAK,QAAQ,GAAG,GAAG,YAAY,KAAK;AACrD,YAAQ,IAAI,UAAU,CAAC,GAAI,QAAQ,IAAI,QAAQ,KAAK,CAAC,GAAI,IAAI,CAAC;AAAA,EAChE;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,UAAoB,WAA+B,SAAyB;AACrG,QAAM,YAAY,oBAAoB,QAAQ;AAC9C,MAAI,WAAW;AACb,QAAI,CAAC,UAAU,SAAS,SAAS,GAAG;AAClC,YAAM,IAAI;AAAA,QACR,aAAa,SAAS,yCAAyC,UAAU,KAAK,IAAI,CAAC;AAAA,MACrF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,MAAI,UAAU,SAAS,GAAG;AACxB,UAAM,IAAI;AAAA,MACR,GAAG,OAAO,6CAA6C,UAAU,KAAK,IAAI,CAAC;AAAA,IAE7E;AAAA,EACF;AACA,SAAO,UAAU,CAAC,KAAK,SAAS;AAClC;AAEA,SAAS,eAAe,MAAY,MAA6C;AAC/E,QAAM,cAAc,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC,UAAU,MAAM,QAAQ,CAAC;AACtE,QAAM,QAAQ,OAAO,QAAQ,KAAK,eAAe;AACjD,aAAW,CAAC,QAAQ,KAAK,OAAO;AAC9B,QAAI,CAAC,YAAY,IAAI,QAAQ,GAAG;AAC9B,YAAM,IAAI;AAAA,QACR,0BAA0B,QAAQ,qCAC7B,CAAC,GAAG,WAAW,EAAE,KAAK,IAAI,KAAK,cAAc;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AACA,MAAI,KAAK,OAAO,SAAS,KAAK,KAAK,WAAW,QAAW;AACvD,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,QAAM,MAAM,oBAAI,IAAgC;AAChD,aAAW,SAAS,KAAK,QAAQ;AAC/B,UAAM,UAAU,KAAK,gBAAgB,MAAM,QAAQ;AACnD,QACE,KAAK,OAAO,SAAS,KACrB,MAAM,aAAa,UACnB,MAAM,OAAO,KACb,YAAY,QACZ;AACA,YAAM,IAAI;AAAA,QACR,0CAA0C,MAAM,QAAQ,iBACnD,WAAW,MAAM,UAAU,MAAM,IAAI,CAAC;AAAA,MAC7C;AAAA,IACF;AACA,QAAI,IAAI,MAAM,UAAU,YAAY,KAAK,OAAO,WAAW,IAAI,KAAK,SAAS,OAAU;AAAA,EACzF;AACA,SAAO;AACT;AAEA,eAAe,QAAQ,UAAkB,MAAiC;AACxE,MAAI,KAAM,QAAO;AACjB,MAAI,CAAC,QAAQ,MAAM,OAAO;AACxB,QAAI,4CAA4C;AAChD,WAAO;AAAA,EACT;AACA,UAAQ,OAAO,MAAM,GAAG,QAAQ,SAAS;AACzC,QAAM,SAAS,MAAM,IAAI,QAAgB,CAAC,YAAY;AACpD,YAAQ,MAAM,YAAY,MAAM;AAChC,YAAQ,MAAM,KAAK,QAAQ,CAAC,MAAM,QAAQ,OAAO,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;AAAA,EAC3E,CAAC;AACD,UAAQ,MAAM,MAAM;AACpB,SAAO,WAAW,OAAO,WAAW;AACtC;AAeA,eAAe,+BAA+B,eAAuB;AACnE,MAAI,CAACF,aAAW,aAAa,GAAG;AAC9B,UAAM,IAAI,MAAM,gCAAgC,aAAa,EAAE;AAAA,EACjE;AACA,QAAM,MAAMD,OAAK,QAAQA,OAAK,QAAQ,aAAa,CAAC;AACpD,QAAM,KAAK,MAAM,cAAc,aAAa;AAC5C,QAAM,cAAc,kBAAkB,IAAI,GAAG;AAC7C,QAAM,SAAS,YAAY,OAAO,CAAC,MAAM,EAAE,UAAU,OAAO;AAC5D,MAAI,OAAO,QAAQ;AACjB,UAAM,IAAI;AAAA,MACR,wBAAwB,aAAa;AAAA,IACnC,OAAO,IAAI,CAAC,MAAM,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AAAA,IAC1D;AAAA,EACF;AACA,QAAM,SAAS,MAAM,gBAAgB,IAAI,GAAG;AAC5C,SAAO,EAAE,IAAI,KAAK,aAAa,OAAO;AACxC;AAEA,eAAe,OAAO;AACpB,QAAM,OAAO,UAAU,QAAQ,KAAK,MAAM,CAAC,CAAC;AAC5C,MAAI,KAAK,YAAY,UAAU,KAAK,YAAY,YAAY,KAAK,YAAY,MAAM;AACjF,QAAI,IAAI;AACR;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,eAAe,KAAK,YAAY,MAAM;AACzD,UAAM,MAAM,KAAK;AAAA,MACf,MAAMI,WAAS,IAAI,IAAI,mBAAmB,YAAY,GAAG,GAAG,MAAM;AAAA,IACpE;AACA,QAAI,GAAG,IAAI,IAAI,IAAI,IAAI,OAAO,EAAE;AAChC;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,WAAW;AAC9B,QAAI,KAAK,eAAe,YAAY;AAClC,UAAI,CAAC,KAAK,OAAQ,OAAM,IAAI,MAAM,wDAAwD;AAC1F,UAAI,CAAC,KAAK,IAAK,OAAM,IAAI,MAAM,wDAAwD;AACvF,UAAI;AACJ,UAAI;AACF,cAAM,KAAK,MAAM,MAAMA,WAASJ,OAAK,QAAQ,KAAK,MAAM,GAAG,MAAM,CAAC;AAAA,MACpE,SAAS,OAAO;AACd,cAAM,IAAI;AAAA,UACR,iCAAiCA,OAAK,QAAQ,KAAK,MAAM,CAAC,KACrD,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,UAC3D,EAAE,OAAO,MAAM;AAAA,QACjB;AAAA,MACF;AACA,YAAM,SAAS,qBAAqB,KAAK,KAAK,MAAM;AACpD,UAAIA,OAAK,QAAQ,KAAK,MAAM,MAAMA,OAAK,QAAQ,KAAK,GAAG,GAAG;AACxD,cAAM,IAAI,MAAM,8DAA8D;AAAA,MAChF;AACA,YAAM,SAAS,MAAM,wBAAwB,QAAQ,KAAK,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC;AACpF,UAAI,KAAK,MAAM;AACb,YAAI,KAAK,UAAU;AAAA,UACjB,SAAS;AAAA,UACT,MAAM,OAAO;AAAA,UACb,SAAS,OAAO;AAAA,UAChB,UAAU,OAAO;AAAA,QACnB,GAAG,MAAM,CAAC,CAAC;AAAA,MACb,OAAO;AACL;AAAA,UACE,KAAK,OAAO,UAAU,UAAU,WAAW,IACtCA,OAAK,SAAS,QAAQ,IAAI,GAAG,OAAO,IAAI,CAAC,KAAK,OAAO,SAAS,MAAM,MAAM;AAAA,QACjF;AACA,YAAI,6EAA6E;AAAA,MACnF;AACA;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,KAAM,OAAM,IAAI,MAAM,sDAAsD;AACtF,UAAM,SAAS,MAAM,qBAAqB,KAAK,IAAI;AACnD,QAAI,KAAK,MAAM;AACb,UAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,IACrC,OAAO;AACL,iBAAW,SAAS,OAAO,OAAO;AAChC,YAAI,KAAK,MAAM,WAAW,SAAS,OAAO,OAAO,KAAK,MAAM,EAAE,EAAE;AAChE,mBAAW,aAAa,MAAM,WAAY,KAAI,YAAY,SAAS,EAAE;AACrE,mBAAW,WAAW,MAAM,SAAU,KAAI,YAAY,OAAO,EAAE;AAAA,MACjE;AACA;AAAA,QACE;AAAA,IAAO,OAAO,QAAQ,MAAM,IAAI,OAAO,QAAQ,KAAK,aACjD,OAAO,QAAQ,UAAU,SAAM,OAAO,QAAQ,OAAO,4BAA4B;AAAA,MACtF;AACA,UAAI,yEAAyE;AAAA,IAC/E;AACA,QAAI,CAAC,OAAO,KAAM,SAAQ,WAAW;AACrC;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,UAAU;AAC7B,QAAI,KAAK,eAAe,QAAQ;AAC9B,YAAM,UAAU,MAAM,mBAAmB;AACzC,UAAI,KAAK,MAAM;AACb,YAAI,KAAK,UAAU;AAAA,UACjB,SAAS;AAAA,UACT,SAAS,QAAQ,IAAI,CAAC,EAAE,OAAO,OAAO;AAAA,YACpC,IAAI,OAAO;AAAA,YACX,SAAS,OAAO;AAAA,YAChB,UAAU,OAAO;AAAA,YACjB,SAAS,OAAO;AAAA,YAChB,UAAU,GAAG,OAAO,EAAE,IAAI,OAAO,OAAO;AAAA,UAC1C,EAAE;AAAA,QACJ,GAAG,MAAM,CAAC,CAAC;AAAA,MACb,OAAO;AACL,YAAI,KAAK,QAAQ,MAAM,qBAAqB;AAC5C,mBAAW,EAAE,OAAO,KAAK,SAAS;AAChC,cAAI,QAAQ,OAAO,KAAK,MAAM,OAAO,SAAS,OAAO,EAAE,CAAC,IAAI,OAAO,OAAO,EAAE;AAAA,QAC9E;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,KAAK;AACpB,QAAI,KAAK,eAAe,WAAW;AACjC,YAAM,EAAE,QAAQ,MAAM,YAAY,QAAQ,IAAI,MAAM,cAAc,MAAM;AACxE,UAAI,KAAK,MAAM;AACb,YAAI,KAAK,UAAU,EAAE,GAAG,QAAQ,MAAM,YAAY,QAAQ,GAAG,MAAM,CAAC,CAAC;AAAA,MACvE,OAAO;AACL,YAAI,KAAK,OAAO,EAAE,IAAI,OAAO,OAAO,EAAE;AACtC,YAAI,KAAK,OAAO,OAAO,EAAE;AACzB,YAAI,eAAe,OAAO,QAAQ,gBAAa,OAAO,OAAO,gBAAa,OAAO,QAAQ,KAAK,EAAE;AAChG;AAAA,UACE,oBAAoB,OAAO,QAAQ,sBAAsB,GAAG,SACvD,OAAO,QAAQ,sBAAsB,GAAG,oBACxC,OAAO,QAAQ,cAAc,GAAG,SAAI,OAAO,QAAQ,cAAc,GAAG;AAAA,QAC3E;AACA,YAAI,OAAO,SAAU,KAAI,eAAe,OAAO,SAAS,IAAI,SAAM,OAAO,SAAS,SAAS,eAAe;AAC1G,mBAAW,SAAS,OAAO,OAAQ,KAAI,YAAY,MAAM,IAAI,SAAM,MAAM,OAAO,EAAE;AAClF,YAAI,aAAa,UAAU,GAAG,UAAU,eAAe,EAAE,EAAE;AAAA,MAC7D;AACA;AAAA,IACF;AAEA,QAAI,KAAK,eAAe,UAAU;AAChC,YAAM,SAAS,MAAM,aAAa,QAAQ,EAAE,WAAW,KAAK,UAAU,CAAC;AACvE,UAAI,KAAK,MAAM;AACb,YAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,MACrC,OAAO;AACL,YAAI,KAAK,OAAO,KAAK,OAAO,OAAO,KAAK,OAAO,OAAO,EAAE,IAAI,OAAO,OAAO,OAAO,EAAE;AACnF,YAAI,KAAK,OAAO,UAAU,OAAO,OAAO,CAAC,CAAC,kBAAkB;AAC5D,mBAAW,QAAQ,OAAO,MAAO,KAAI,KAAK,KAAK,OAAO,OAAO,CAAC,CAAC,IAAI,KAAK,IAAI,EAAE;AAC9E,mBAAW,SAAS,OAAO,OAAQ,KAAI,KAAK,MAAM,OAAO,OAAO,CAAC,CAAC,IAAI,MAAM,IAAI,EAAE;AAClF,YAAI,CAAC,OAAO,aAAa,OAAO,OAAO,QAAQ;AAC7C,cAAI,0FAA0F;AAAA,QAChG;AAAA,MACF;AACA,UAAI,CAAC,OAAO,GAAI,SAAQ,WAAW;AACnC;AAAA,IACF;AAEA,QAAI,KAAK,eAAe,WAAW;AACjC,YAAM,SAAS,MAAM,cAAc,QAAQ,EAAE,KAAK,KAAK,KAAK,OAAO,KAAK,MAAM,CAAC;AAC/E,UAAI,KAAK,MAAM;AACb,YAAI,KAAK,UAAU;AAAA,UACjB,SAAS;AAAA,UACT,QAAQ,GAAG,OAAO,OAAO,EAAE,IAAI,OAAO,OAAO,OAAO;AAAA,UACpD,aAAa,OAAO;AAAA,UACpB,SAAS,OAAO;AAAA,UAChB,WAAW,OAAO;AAAA,UAClB,SAAS,OAAO;AAAA,UAChB,OAAO,OAAO;AAAA,QAChB,GAAG,MAAM,CAAC,CAAC;AAAA,MACb,OAAO;AACL,YAAI,eAAe,OAAO,OAAO,EAAE,IAAI,OAAO,OAAO,OAAO,EAAE;AAC9D,YAAI,KAAKA,OAAK,SAAS,QAAQ,IAAI,GAAG,OAAO,WAAW,KAAK,GAAG,EAAE;AAClE,YAAI;AAAA,sDAAyD;AAC7D,YAAI,KAAK,UAAU,EAAE,CAAC,OAAO,OAAO,GAAG,OAAO,MAAM,GAAG,MAAM,CAAC,CAAC;AAC/D,YAAI,OAAO,OAAO,OAAO,QAAQ;AAC/B,cAAI;AAAA,6DAAgE;AACpE,cAAI,6BAA6BA,OAAK,SAAS,QAAQ,IAAI,GAAG,OAAO,WAAW,CAAC,gCAAgC;AAAA,QACnH;AAAA,MACF;AACA;AAAA,IACF;AAAA,EACF;AAIA,MAAI,KAAK,YAAY,aAAa,KAAK,QAAQ,KAAK,eAAe,YAAY;AAC7E,QAAI,CAAC,KAAK,MAAM;AACd,YAAM,IAAI;AAAA,QACR,KAAK,eAAe,QAChB,sCACA,UAAU,KAAK,UAAU;AAAA,MAC/B;AAAA,IACF;AAEA,QAAI,KAAK,eAAe,OAAO;AAC7B,UAAI,CAAC,KAAK,IAAK,OAAM,IAAI,MAAM,iCAAiC;AAChE,UAAI,CAAC,KAAK,QAAQ,QAAQ;AACxB,cAAM,IAAI,MAAM,qEAAqE;AAAA,MACvF;AACA,YAAMK,UAAS,MAAM,YAAY;AAAA,QAC/B,QAAQ,KAAK;AAAA,QACb,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,aAAa,KAAK;AAAA,QAClB,eAAe,KAAK;AAAA,QACpB,mBAAmB,KAAK;AAAA,QACxB,iBAAiB,KAAK;AAAA,QACtB,OAAO,KAAK;AAAA,MACd,CAAC;AACD,UAAI,KAAK,MAAM;AACb,YAAI,KAAK,UAAUA,SAAQ,MAAM,CAAC,CAAC;AAAA,MACrC,OAAO;AACL;AAAA,UACE,eAAeA,QAAO,UAAU,OAAO,IAAIA,QAAO,UAAU,IAAI,iBAC1DA,QAAO,UAAU,UAAU,KAAKA,QAAO,UAAU,SAAS;AAAA,QAClE;AACA,YAAI,cAAcA,QAAO,QAAQ,MAAM,kCAAkC;AACzE,YAAI,WAAWL,OAAK,SAAS,QAAQ,IAAI,GAAGK,QAAO,MAAM,CAAC,EAAE;AAC5D,YAAI,qBAAqBL,OAAK,SAAS,QAAQ,IAAI,GAAGK,QAAO,MAAM,CAAC,EAAE;AACtE,YAAI;AAAA,iEAAiE;AACrE;AAAA,UACE,uCAAuCL,OAAK,SAAS,QAAQ,IAAI,GAAGK,QAAO,MAAM,CAAC;AAAA,QAEpF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,KAAK,eAAe,WAAW;AACjC,UAAI,CAAC,KAAK,UAAU,KAAK,GAAG;AAC1B,cAAM,IAAI,MAAM,yCAAyC;AAAA,MAC3D;AACA,YAAM,UAAU,MAAM,mBAAmB,KAAK,IAAI;AAClD;AAAA,QACE,QAAQ,QAAQ,WACZ,iBAAiB,QAAQ,QAAQ,SAAS,KAAK,gEAC/C;AAAA,MACN;AACA,UAAI,8EAA8E;AAClF,UAAI,CAAE,MAAM;AAAA,QACV,QAAQ,QAAQ,WACZ,wDACA;AAAA,QACJ,KAAK;AAAA,MACP,GAAI;AACF,YAAI,yBAAyB;AAC7B;AAAA,MACF;AACA,YAAMA,UAAS,MAAM,qBAAqB,KAAK,MAAM;AAAA,QACnD,UAAU,KAAK;AAAA,QACf,MAAM,KAAK;AAAA,MACb,CAAC;AACD,UAAI,KAAK,KAAM,KAAI,KAAK,UAAUA,SAAQ,MAAM,CAAC,CAAC;AAAA,WAC7C;AACH;AAAA,UACEA,QAAO,QAAQ,WACX,cAAcA,QAAO,QAAQ,MAAM,cAAcL,OAAK,SAAS,QAAQ,IAAI,GAAGK,QAAO,MAAM,CAAC,OAAO,KAAK,SAAS,KAAK,CAAC,KACvH,cAAcL,OAAK,SAAS,QAAQ,IAAI,GAAGK,QAAO,MAAM,CAAC,OAAO,KAAK,SAAS,KAAK,CAAC;AAAA,QAC1F;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,mBAAmB,KAAK,IAAI;AACjD,QAAI,KAAK,MAAM;AACb,UAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,IACrC,OAAO;AACL,UAAI,KAAK,OAAO,OAAO,kBAAkB,mBAAmB,KAAKL,OAAK,SAAS,QAAQ,IAAI,GAAG,OAAO,UAAU,OAAO,MAAM,CAAC,EAAE;AAC/H,iBAAW,UAAU,OAAO,QAAS,KAAI,OAAO,MAAM,EAAE;AAAA,IAC1D;AACA,QAAI,CAAC,OAAO,KAAM,SAAQ,WAAW;AACrC;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,WAAW;AAC9B,iBAAaA,OAAK,QAAQA,OAAK,QAAQ,KAAK,QAAQ,CAAC,CAAC;AACtD,iBAAa,QAAQ,IAAI,CAAC;AAC1B,UAAMM,UAAS,MAAM,aAAa,KAAK,QAAQ;AAC/C,UAAM,mBAAmB,kBAAkBA,QAAO,UAAU,KAAK,UAAU,SAAS;AACpF,UAAM,IAAI,eAAe,kBAAkB,QAAQ;AACnD,UAAM,IAAI,MAAM,eAAe,CAAC,EAAE;AAClC,QAAI,gBAAgB,EAAE,EAAE,EAAE;AAC1B,QAAI,gBAAgB,EAAE,QAAQ,KAAK,EAAE;AACrC,QAAI,gBAAgB,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,GAAG,EAAE,QAAQ,OAAO,EAAE,KAAK,KAAK,EAAE,EAAE;AACvF;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,QAAQ;AAC3B,QAAI,CAAC,KAAK,KAAM,OAAM,IAAI,MAAM,yDAAyD;AACzF,UAAM,OAAON,OAAK,QAAQ,KAAK,IAAI;AACnC,QAAI,CAACC,aAAW,IAAI,EAAG,OAAM,IAAI,MAAM,mBAAmB,IAAI,EAAE;AAEhE,UAAM,YAAa,KAAK,aAAa;AACrC,QAAI,cAAc,UAAU,cAAc,OAAO;AAC/C,YAAM,IAAI,MAAM,6CAA6C,KAAK,SAAS,IAAI;AAAA,IACjF;AAEA,UAAM,SAASD,OAAK,QAAQ,KAAK,OAAO,yBAAyB;AACjE,UAAM,EAAE,QAAQ,QAAQ,IAAI,MAAM,WAAW,MAAM,EAAE,SAAS,KAAK,QAAQ,CAAC;AAC5E,QAAI,CAAC,OAAO,OAAQ,OAAM,IAAI,MAAM,uBAAuB,IAAI,EAAE;AAEjE,UAAM,WAAW;AAAA,MACf,KAAK,QAAQA,OAAK,SAASA,OAAK,QAAQ,MAAM,CAAC;AAAA,MAC/C,KAAK,OAAO,CAAC,KAAK;AAAA,MAClB;AAAA,MACAA,OAAK,SAASA,OAAK,QAAQ,MAAM,GAAG,IAAI,KAAK;AAAA,MAC7C;AAAA,IACF;AACA,UAAM,kBAAkB,QAAQ,QAAQ;AAExC,QAAI,aAAa,OAAO,MAAM,iBAAiBA,OAAK,SAAS,QAAQ,IAAI,GAAG,IAAI,CAAC,EAAE;AACnF,QAAI,QAAQ,OAAQ,KAAI,aAAa,QAAQ,MAAM,qBAAqB;AACxE,QAAI,WAAWA,OAAK,SAAS,QAAQ,IAAI,GAAG,MAAM,CAAC,EAAE;AACrD,QAAI;AAAA,sEAAyE;AAC7E,QAAI,+CAA+C;AACnD,QAAI;AAAA,iCAAoCA,OAAK,SAAS,QAAQ,IAAI,GAAG,MAAM,CAAC;AAAA,CAAoB;AAChG;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,SAAS;AAC5B,UAAMO,QAAO,MAAM,SAAS,KAAK,IAAI;AACrC,UAAM,SAAS,MAAM,cAAcA,OAAM,KAAK,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;AACzE,QAAI,KAAK,MAAM;AACb,UAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,IACrC,OAAO;AACL,YAAM,OAAO,OAAO,QAAQ,QAAQ,OAChC,GAAG,OAAO,QAAQ,KAAK,OACvB,IAAI,OAAO,QAAQ,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAC/C,UAAI,oBAAoB,OAAO,QAAQ,IAAI,EAAE;AAC7C;AAAA,QACE,OAAO,QAAQ,SACX,OAAO,OAAO,QAAQ,KAAK,kBAAkB,OAAO,QAAQ,UAAU,gBACnE,OAAO,QAAQ,aAAa,MAAM,wBAAmB,IAAI,KAC5D;AAAA,MACN;AACA,UAAI,OAAO,QAAQ,kBAAkB,QAAQ;AAC3C,YAAI,OAAO,OAAO,QAAQ,kBAAkB,MAAM,2CAA2C;AAAA,MAC/F;AACA,iBAAW,SAAS,OAAO,QAAQ,QAAQ,MAAM,GAAG,EAAE,GAAG;AACvD,YAAI,eAAe,MAAM,IAAI,KAAK,MAAM,MAAM,EAAE;AAAA,MAClD;AACA,UAAI,OAAO,QAAQ,QAAQ,SAAS,IAAI;AACtC,YAAI,kBAAa,OAAO,QAAQ,QAAQ,SAAS,EAAE,yBAAyB;AAAA,MAC9E;AAEA,UAAI,+BAA+B,OAAO,aAAa,IAAI,EAAE;AAC7D,UAAI,CAAC,OAAO,aAAa,OAAQ,KAAI,qBAAqB;AAAA,eACjD,OAAO,aAAa,OAAO;AAClC,YAAI,sBAAsB,OAAO,aAAa,MAAM,MAAM,IAAI,EAAE,CAAC,CAAC,EAAE;AAAA,MACtE,OAAO;AACL;AAAA,UACE,OAAO,OAAO,aAAa,KAAK,qBAC3B,OAAO,aAAa,WAAW,MAAM;AAAA,QAC5C;AAAA,MACF;AACA,UAAI,KAAK,OAAO;AACd;AAAA,UACE,YAAY,OAAO,QAAQ,YAAY,qBAClC,OAAO,QAAQ,iBAAiB,oCAClC,OAAO,QAAQ,uBAAuB,qCAAqC;AAAA,QAChF;AAAA,MACF;AACA,UAAI,KAAK,OAAO,OAAO,+BAA+B,iCAAiC,EAAE;AAAA,IAC3F;AACA,QAAI,KAAK,SAAS,CAAC,OAAO,KAAM,SAAQ,WAAW;AACnD;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,UAAU,KAAK,QAAQ;AAQ1C,QAAI,CAAC,KAAK,IAAK,OAAM,IAAI,MAAM,yBAAyB;AACxD,QAAI,KAAK,eAAe,KAAK,YAAY,QAAQ;AAC/C,YAAM,IAAI,MAAM,+DAA+D;AAAA,IACjF;AAEA,UAAM,MAAM,KAAK,MAAM,MAAMH,WAASJ,OAAK,QAAQ,KAAK,MAAM,GAAG,MAAM,CAAC;AACxE,UAAM,SAAS,kBAAkB,KAAK,KAAK,MAAM;AAEjD,UAAM,EAAE,KAAK,OAAO,SAAS,QAAQ,IAAI,YAAY,QAAQ,EAAE,SAAS,KAAK,QAAQ,CAAC;AACtF,UAAM,OAAOA,OAAK,QAAQ,KAAK,IAAI,QAAQ,UAAU,EAAE,CAAC;AACxD,UAAM,UAA0B;AAAA,MAC9B,EAAE,MAAM,GAAG,IAAI,QAAQ,MAAM,IAAI;AAAA,MACjC,EAAE,MAAM,GAAG,IAAI,SAAS,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC,IAAI,KAAK;AAAA,IACtE;AACA,UAAM,2BAA2B,GAAG,IAAI,mBAAmB,SAAS;AAAA,MAClE,MAAM;AAAA,MACN,SAAS,CAAC,MAAM,eAAe,WAAW,KAAK,MAAM,GAAG,GAAG,OAAO;AAAA,MAClE,SAAS,EAAE,SAAS,KAAK,WAAW,MAAM,OAAO,MAAM,OAAO,KAAK;AAAA,IACrE,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;AACxB;AAAA,MACE,KAAK,MAAM,OAAO,MAAM,eAAe,MAAM,MAAM,KAAK,IAAI,MAAM,MAAM,MAAM,OACtE,MAAM,OAAO,sBAAiB,IAAI,SAAS,MAAM,QAAQ,CAAC,CAAC;AAAA,IACrE;AACA,QAAI,OAAOA,OAAK,SAAS,QAAQ,IAAI,GAAG,IAAI,CAAC,gCAAgC;AAC7E,eAAW,KAAK,QAAS,KAAI,eAAe,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;AAC/D;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,aAAa;AAGhC,UAAM,gBAAgBA,OAAK,QAAQ,KAAK,aAAa,0BAA0B;AAC/E,UAAM,MAAMA,OAAK,QAAQ,aAAa;AAEtC,QAAI,KAAK,eAAe,OAAO;AAC7B,YAAM,eAAeA,OAAK,QAAQ,KAAK,MAAO;AAC9C,YAAM,eAAe,MAAM,aAAa,YAAY;AACpD,YAAM,WAAW,KAAK,eAClBA,OAAK,QAAQ,KAAK,YAAY,IAC9BA,OAAK,KAAKA,OAAK,QAAQ,YAAY,GAAG,qBAAqB;AAE/D,YAAM,KAAK,MAAM,cAAc,aAAa;AAC5C,YAAM,KAAK,KAAK,QAAQ,aAAa,SAAS;AAC9C,UAAI,GAAG,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG;AACxC,cAAM,IAAI;AAAA,UACR,eAAe,EAAE,8BAA8B,aAAa;AAAA,QAC9D;AAAA,MACF;AACA,YAAM,YAAY,GAAG,SAAS,KAAK,CAAC,MAAM,eAAe,KAAK,CAAC,EAAE,aAAa,QAAQ;AACtF,UAAI,WAAW;AACb,cAAM,IAAI,MAAM,YAAY,QAAQ,4CAA4C,UAAU,EAAE,IAAI;AAAA,MAClG;AAEA,YAAM,UAA4B;AAAA,QAChC;AAAA,QACA,UAAU,eAAe,KAAK,YAAY;AAAA,QAC1C,MAAM,eAAe,KAAK,QAAQ;AAAA,QAClC,UAAU,KAAK,YAAY,aAAa,SAAS;AAAA,QACjD,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,MAClD;AACA,YAAM,cAAc,eAAe,EAAE,SAAS,GAAG,UAAU,CAAC,GAAG,GAAG,UAAU,OAAO,EAAE,CAAC;AACtF,UAAI,iBAAiB,EAAE,QAAQA,OAAK,SAAS,QAAQ,IAAI,GAAG,aAAa,CAAC,EAAE;AAC5E,UAAI,iBAAiB,QAAQ,QAAQ,EAAE;AACvC,UAAI,iBAAiB,QAAQ,IAAI,EAAE;AACnC,UAAI,CAACC,aAAW,QAAQ,GAAG;AACzB;AAAA,UACE;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI,KAAK,eAAe,UAAU;AAChC,YAAM,KAAK,MAAM,cAAc,aAAa;AAC5C,YAAM,iBAAiBD,OAAK,QAAQ,KAAK,MAAO;AAChD,YAAM,QAAQ,GAAG,SAAS;AAAA,QACxB,CAAC,MAAM,EAAE,OAAO,KAAK,UAAU,eAAe,KAAK,CAAC,EAAE,iBAAiB;AAAA,MACzE;AACA,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,kCAAkC,KAAK,MAAM,mCAAmC;AAAA,MAClG;AACA,YAAM,cAAc,eAAe;AAAA,QACjC,SAAS;AAAA,QACT,UAAU,GAAG,SAAS,OAAO,CAAC,MAAM,MAAM,KAAK;AAAA,MACjD,CAAC;AACD,UAAI,cAAc,MAAM,EAAE,UAAUA,OAAK,SAAS,QAAQ,IAAI,GAAG,aAAa,CAAC,EAAE;AACjF;AAAA,IACF;AAEA,QAAI,KAAK,eAAe,QAAQ;AAC9B,UAAI,CAACC,aAAW,aAAa,GAAG;AAC9B,cAAM,IAAI,MAAM,gCAAgC,aAAa,EAAE;AAAA,MACjE;AACA,YAAM,KAAK,MAAM,cAAc,aAAa;AAC5C,YAAM,cAAc,kBAAkB,IAAI,GAAG;AAC7C,UAAI,KAAK,MAAM;AACb,YAAI,KAAK,UAAU,EAAE,SAAS,GAAG,WAAW,eAAe,UAAU,GAAG,UAAU,YAAY,GAAG,MAAM,CAAC,CAAC;AAAA,MAC3G,WAAW,CAAC,GAAG,SAAS,QAAQ;AAC9B,YAAI,+BAA+BD,OAAK,SAAS,QAAQ,IAAI,GAAG,aAAa,CAAC,EAAE;AAAA,MAClF,OAAO;AACL,YAAI,KAAK,GAAG,SAAS,MAAM,kBAAkBA,OAAK,SAAS,QAAQ,IAAI,GAAG,aAAa,CAAC,GAAG;AAC3F,mBAAW,KAAK,GAAG,UAAU;AAC3B,cAAI,OAAO,EAAE,GAAG,OAAO,EAAE,CAAC,IAAI,EAAE,SAAS,OAAO,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,EAAE,UAAU,KAAK,EAAE,OAAO,KAAK,EAAE,GAAG;AAAA,QAC3G;AACA,mBAAW,KAAK,YAAa,KAAI,KAAK,EAAE,UAAU,UAAU,UAAU,OAAO,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE;AAAA,MACjH;AACA,UAAI,KAAK,SAAS,YAAY,KAAK,CAAC,MAAM,EAAE,UAAU,OAAO,EAAG,SAAQ,WAAW;AACnF;AAAA,IACF;AAEA,QAAI,KAAK,eAAe,UAAU;AAChC,UAAI,CAACC,aAAW,aAAa,GAAG;AAC9B,cAAM,IAAI,MAAM,gCAAgC,aAAa,EAAE;AAAA,MACjE;AACA,YAAM,KAAK,MAAM,cAAc,aAAa;AAC5C,YAAM,SAAS,MAAM,gBAAgB,IAAI,GAAG;AAC5C,UAAI,KAAK,MAAM;AACb,YAAI,KAAK,UAAU,EAAE,GAAG,QAAQ,WAAW,cAAc,GAAG,MAAM,CAAC,CAAC;AAAA,MACtE,OAAO;AACL,YAAI,gBAAgBD,OAAK,SAAS,QAAQ,IAAI,GAAG,aAAa,CAAC,EAAE;AACjE,mBAAW,KAAK,OAAO,UAAU;AAC/B,cAAI,EAAE,OAAO;AACX,gBAAI;AAAA,IAAO,EAAE,EAAE,kBAAa,EAAE,KAAK,EAAE;AACrC;AAAA,UACF;AACA;AAAA,YACE;AAAA,IAAO,EAAE,EAAE,MAAM,EAAE,UAAU,KAAK,KAAK,CAAC,GACnC,EAAE,UAAU,KAAK,EAAE,OAAO,KAAK,EAAE;AAAA,UACxC;AACA,cAAI,OAAO,EAAE,OAAO,eAAe;AACnC,qBAAW,CAAC,OAAO,CAAC,KAAK,OAAO,QAAQ,EAAE,OAAO,EAAG,KAAI,EAAG,KAAI,SAAS,MAAM,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE;AAC/F,qBAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,EAAE,WAAW,EAAE,KAAK,GAAG;AACjE,gBAAI,OAAQ,KAAI,cAAc,WAAW,MAAM,MAAM,CAAC,EAAE;AAAA,UAC1D;AAAA,QACF;AACA,YAAI;AAAA,UAAa;AACjB,mBAAW,CAAC,OAAO,CAAC,KAAK,OAAO,QAAQ,OAAO,OAAO,OAAO,EAAG,KAAI,EAAG,KAAI,OAAO,MAAM,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE;AACzG,mBAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,OAAO,WAAW,EAAE,KAAK,GAAG;AAC7E,cAAI,OAAQ,KAAI,cAAc,WAAW,MAAM,MAAM,CAAC,EAAE;AAAA,QAC1D;AACA,YAAI,eAAe,OAAO,OAAO,MAAM,EAAE;AACzC,mBAAW,KAAK,OAAO,YAAa,KAAI,KAAK,EAAE,UAAU,UAAU,UAAU,OAAO,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE;AAAA,MACxH;AACA,UAAI,KAAK,SAAS,CAAC,OAAO,KAAM,SAAQ,WAAW;AACnD;AAAA,IACF;AAEA,QAAI,KAAK,eAAe,UAAU;AAChC,YAAM,EAAE,QAAQ,YAAY,IAAI,MAAM,+BAA+B,aAAa;AAClF,UAAI,KAAK,MAAM;AACb,YAAI,KAAK,UAAU;AAAA,UACjB,SAAS;AAAA,UACT,SAAS,CAAC,GAAG,OAAO,OAAO,EAAE,KAAK;AAAA,UAClC,WAAW,OAAO;AAAA,UAClB,WAAW,OAAO;AAAA,QACpB,GAAG,MAAM,CAAC,CAAC;AAAA,MACb,OAAO;AACL,YAAI,KAAK,OAAO,QAAQ,IAAI,yBAAyB,OAAO,UAAU,MAAM,eAAe;AAC3F,mBAAW,CAAC,IAAI,CAAC,KAAK,OAAO,QAAQ,OAAO,SAAS,EAAE,KAAK,EAAG,KAAI,OAAO,GAAG,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE;AAC9F,mBAAW,KAAK,YAAa,KAAI,WAAW,EAAE,GAAG,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE;AAAA,MAC5E;AACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAACC,aAAWD,OAAK,QAAQ,KAAK,QAAQ,CAAC,GAAG;AAC5C,UAAM,IAAI;AAAA,MACR,kBAAkBA,OAAK,QAAQ,KAAK,QAAQ,CAAC;AAAA,IAC/C;AAAA,EACF;AAIA,QAAM,cAAcA,OAAK,QAAQA,OAAK,QAAQ,KAAK,QAAQ,CAAC;AAC5D,QAAM,WAAW,CAAC,GAAG,aAAa,WAAW,CAAC;AAC9C,MAAIA,OAAK,QAAQ,QAAQ,IAAI,CAAC,MAAM,YAAa,UAAS,KAAK,GAAG,aAAa,QAAQ,IAAI,CAAC,CAAC;AAE7F,QAAM,SAAS,MAAM,aAAa,KAAK,QAAQ;AAC/C,MAAI,QAAQ,MAAM,aAAa,QAAQ;AAAA,IACrC,QAAQ,KAAK;AAAA,IACb,QAAQ,KAAK;AAAA,EACf,CAAC;AACD,QAAM,kBAAkB,oBAAI,IAAI,CAAC,SAAS,WAAW,OAAO,CAAC;AAC7D,QAAM,0BAA0B,gBAAgB,IAAI,KAAK,OAAO,IAC5D,kBAAkB,OAAO,UAAU,KAAK,UAAU,KAAK,OAAO,IAC9D;AACJ,MAAI,KAAK,YAAY,CAAC,yBAAyB;AAC7C,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,yBAAyB;AAC3B,YAAQ,MAAM,OAAO,CAAC,SAAS,KAAK,aAAa,uBAAuB;AAAA,EAC1E;AACA,QAAM,kBAA4B,0BAC9B;AAAA,IACE,GAAG,OAAO;AAAA,IACV,UAAU;AAAA,IACV,QAAQ,OAAO;AAAA,MACb,OAAO,QAAQ,OAAO,SAAS,MAAM,EAAE;AAAA,QACrC,CAAC,CAAC,EAAE,KAAK,OAAO,MAAM,YAAY,OAAO,SAAS,cAAc;AAAA,MAClE;AAAA,IACF;AAAA,EACF,IACA,OAAO;AACX,MACE,2BACA,KAAK,OAAO,KAAK,CAAC,YAAY,CAAC,gBAAgB,OAAO,OAAO,CAAC,GAC9D;AACA,UAAM,IAAI;AAAA,MACR,+CAA+C,uBAAuB;AAAA,IACxE;AAAA,EACF;AACA,QAAM,OAAO,MAAM,SAAS,KAAK,IAAI;AACrC,2BAAyB,MAAM,KAAK;AAEpC,MAAI,KAAK,YAAY,UAAU;AAC7B,UAAM,WAAmC,CAAC;AAC1C,eAAW,KAAK,OAAO,OAAO,KAAK,OAAO,EAAG,UAAS,EAAE,MAAM,KAAK,SAAS,EAAE,MAAM,KAAK,KAAK;AAC9F,QAAI,KAAK,MAAM;AACb,UAAI,KAAK,UAAU,EAAE,SAAS,OAAO,KAAK,KAAK,OAAO,EAAE,QAAQ,UAAU,aAAa,YAAY,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC;AACpH;AAAA,IACF;AACA,QAAI,KAAK,OAAO,KAAK,KAAK,OAAO,EAAE,MAAM,eAAe;AACxD,eAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,QAAQ,EAAE,KAAK,EAAG,KAAI,OAAO,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE;AACpF,UAAM,QAAQ,YAAY,IAAI;AAC9B,QAAI,WAAW;AACf,eAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,KAAK,EAAE,KAAK,GAAG;AACzD,UAAI,QAAQ;AACV,YAAI,sCAAsC,WAAW,MAAM,MAAM,CAAC,EAAE;AACpE,mBAAW;AAAA,MACb;AAAA,IACF;AACA,QAAI,CAAC,SAAU,KAAI,0CAA0C;AAC7D;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,UAAU,OAAO,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;AAE/D,MAAI,KAAK,YAAY,UAAU;AAC7B,UAAM,iBAAiB;AAAA,MACrB,KAAK,MAAM,UAAU;AAAA,MACrB,KAAK,QAAQ,SAAS,cAAc;AAAA,MACpC,KAAK,gBAAgB,qBAAqB;AAAA,MAC1C,KAAK,oBAAoB,0BAA0B;AAAA,MACnD,KAAK,mBAAmB,OAAO,uBAAuB;AAAA,IACxD,EAAE,OAAO,OAAO;AAChB,QAAI,eAAe,QAAQ;AACzB,YAAM,IAAI;AAAA,QACR,GAAG,eAAe,KAAK,IAAI,CAAC;AAAA,MAE9B;AAAA,IACF;AAEA,QAAI,KAAK,eAAe,SAAS;AAC/B,YAAM,eAAe,MAAM,QAAQ;AAAA,QACjC,MAAM,OAAO,CAAC,SAAS,KAAK,OAAO,EAAE,IAAI,CAAC,SAAS,sBAAsB,MAAM,IAAI,CAAC;AAAA,MACtF,GAAG,OAAO,CAAC,SAAS,SAAS,IAAI;AACjC,UAAI,CAAC,YAAY,OAAQ,OAAM,IAAI,MAAM,0CAA0C;AACnF,YAAM,OAAO,YAAY,MAAM,CAAC,SAAS,KAAK,UAAU,UAAU;AAClE,UAAI,KAAK,MAAM;AACb,YAAI,KAAK,UAAU,EAAE,SAAS,GAAG,MAAM,OAAO,YAAY,GAAG,MAAM,CAAC,CAAC;AAAA,MACvE,OAAO;AACL,mBAAW,QAAQ,aAAa;AAC9B,cAAI,KAAK,KAAK,MAAM,OAAO,EAAE,CAAC,IAAI,KAAK,GAAG,KAAK,KAAK,MAAM,EAAE;AAAA,QAC9D;AAAA,MACF;AACA,UAAI,CAAC,KAAM,SAAQ,WAAW;AAC9B;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,sBAAsB,OAAO,MAAM;AAAA,MACtD,aAAa,KAAK;AAAA,MAClB,OAAO,KAAK;AAAA,IACd,CAAC;AACD,QAAI,KAAK,MAAM;AACb,UAAI,KAAK,UAAU,EAAE,SAAS,GAAG,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC;AAAA,IACxD,OAAO;AACL,iBAAW,QAAQ,OAAO,OAAO;AAC/B,YAAI,KAAK,KAAK,MAAM,OAAO,EAAE,CAAC,IAAI,KAAK,GAAG,KAAK,KAAK,MAAM,EAAE;AAC5D,YAAI,KAAK,UAAU,kBAAkB;AACnC;AAAA,YACE,uCAAuCA,OAAK,SAAS,QAAQ,IAAI,GAAG,KAAK,MAAM,CAAC;AAAA,UAElF;AAAA,QACF;AAAA,MACF;AACA,UAAI;AAAA,IAAO,OAAO,SAAS,aAAa,OAAO,OAAO,eAAe,OAAO,MAAM,SAAS;AAAA,IAC7F;AACA,QAAI,OAAO,OAAQ,SAAQ,WAAW;AACtC;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,UAAU;AAC7B,UAAM,mBAAmB,KAAK,OAAO,SACjC,KAAK,SACL,OAAO,KAAK,OAAO,SAAS,MAAM;AACtC,UAAM,cAAc,CAAC,GAAG,IAAI;AAAA,MAC1B,iBAAiB,IAAI,CAAC,YACpB,OAAO,SAAS,OAAO,OAAO,GAAG,YAAY,OAAO,SAAS,QAAQ;AAAA,IACzE,CAAC,EAAE,KAAK;AACR,UAAMQ,aAAY,YAAY,IAAI,CAAC,OAAO;AACxC,YAAM,UAAU,gBAAgB,EAAE;AAClC,YAAM,iBAAiB,uBAAuB,OAAO;AACrD,YAAM,wBAAwB,eAAe,OAAO,CAAC,SAAS,CAAC,QAAQ,IAAI,IAAI,CAAC;AAChF,YAAM,gBAAgB,sBAAsB,WAAW;AACvD,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,eAAe,QAAQ;AAAA,QACvB;AAAA,QACA,UAAU,CAAC,KAAK,UAAU,gBAAgB,eAAe,IAAI,QAAQ,IAAI;AAAA,MAC3E;AAAA,IACF,CAAC;AACD,UAAM,SAAS,MAAM,OAAO,QAAQ,OAAO,MAAM,KAAK,MAAM;AAAA,MAC1D,WAAAA;AAAA,MACA,SAAS,KAAK;AAAA,IAChB,CAAC;AACD,QAAI,KAAK,MAAM;AACb,UAAI,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,IACrC,OAAO;AACL,iBAAW,SAAS,OAAO,QAAQ;AACjC,cAAM,OAAO,MAAM,UAAU,OAAO,OAAO,MAAM,UAAU,YAAY,SAAS;AAChF,YAAI,KAAK,KAAK,OAAO,CAAC,CAAC,IAAI,MAAM,GAAG,OAAO,EAAE,CAAC,IAAI,MAAM,OAAO,EAAE;AAAA,MACnE;AAAA,IACF;AACA,QAAI,CAAC,OAAO,GAAI,SAAQ,WAAW;AACnC;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,QAAQ;AAC3B,QAAI,KAAK,MAAM;AACb,UAAI,KAAK,UAAU;AAAA,QACjB,QAAQ,UAAU,IAAI;AAAA,QACtB,MAAM,KAAK;AAAA,QACX,UAAU,KAAK;AAAA,QACf,YAAY,KAAK;AAAA,QACjB,QAAQ,KAAK,OAAO,IAAI,CAAC,WAAW;AAAA,UAClC,UAAU,MAAM;AAAA,UAChB,MAAM,MAAM;AAAA,UACZ,UAAU,MAAM;AAAA,UAChB,YAAY,MAAM;AAAA,UAClB,YAAY,MAAM,WAAW,IAAI,CAAC,SAAS,KAAK,GAAG;AAAA,QACrD,EAAE;AAAA,QACF,YAAY,KAAK,WAAW,IAAI,CAAC,MAAM,EAAE,GAAG;AAAA,QAC5C,OAAO,KAAK,MAAM,IAAI,CAAC,EAAE,KAAK,OAAO,QAAQ,SAAS,KAAK,OAAO;AAAA,UAChE;AAAA,UACA;AAAA,UACA;AAAA,UACA,GAAI,KAAK,WACL;AAAA,YACE,UAAU;AAAA,cACR,MAAM,KAAK,SAAS;AAAA,cACpB,MAAM,KAAK,SAAS;AAAA,cACpB,cAAc,KAAK,SAAS;AAAA,cAC5B,GAAI,KAAK,SAAS,aACd,EAAE,YAAY,KAAK,SAAS,WAAW,IACvC,CAAC;AAAA,cACL,GAAI,KAAK,SAAS,YAAY,OAAO,CAAC,IAAI,EAAE,UAAU,KAAK,SAAS,SAAS;AAAA,YAC/E;AAAA,UACF,IACA,CAAC;AAAA,UACL,GAAI,UAAU,EAAE,SAAS,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,EAAE,IAAI,CAAC;AAAA,QACjF,EAAE;AAAA,MACJ,GAAG,MAAM,CAAC,CAAC;AAAA,IACb,OAAO;AACL,gBAAU,IAAI;AAAA,IAChB;AACA,QACE,KAAK,SAAS,KAAK,MAAM;AAAA,MACvB,CAAC,SAAS,KAAK,UAAU,QAAS,KAAK,WAAW,KAAK,QAAQ,UAAU;AAAA,IAC3E,EACA,SAAQ,WAAW;AACrB;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,UAAU;AAG7B,QAAI,WAAW;AACf,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,KAAK,UAAU,QAAS;AAC5B,YAAM,QAAQ,KAAK,QAAQ,KAAK,GAAG;AAGnC,UAAI,CAAC,SAAS,MAAM,aAAa,KAAK,KAAK,YAAY,MAAM,QAAQ,WAAW,EAAG;AACnF,UAAI,SAAS;AACb,iBAAW,UAAU,MAAM,SAAS;AAClC,cAAM,OAAO,kBAAkB,OAAO,MAAM,KAAK,KAAK,IAAI;AAC1D,YAAI,CAACP,aAAW,IAAI,KAAM,MAAM,WAAW,IAAI,MAAO,OAAO,QAAQ;AACnE,mBAAS;AACT;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,OAAQ;AACb,aAAW,MAAM,KAAK,KAAK,EAAE,UAAU,KAAK,KAAK,SAAS,CAAC;AAC3D;AAAA,IACF;AACA,UAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,QAAI,cAAc,QAAQ,kDAAkD;AAC5E,QAAI,mEAAmE;AACvE;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,SAAS;AAU5B,QAAI,KAAK,OAAO,UAAU,KAAK,OAAO,QAAQ;AAC5C,YAAM,IAAI;AAAA,QACR;AAAA,MAEF;AAAA,IACF;AACA,UAAM,WAAW,IAAI,KAAK,MAAM,aAAa,MAAM,GAAG,IAAI,CAAC,MAAM,QAAQ,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;AAC/F,UAAM,UAAU,OAAO,KAAK,KAAK,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,SAAS,IAAI,GAAG,CAAC,EAAE,KAAK;AACnF,QAAI,CAAC,QAAQ,QAAQ;AACnB,UAAI,wEAAmE;AACvE;AAAA,IACF;AAEA,QAAI;AAAA,IACJ,QAAQ,MAAM,kDAAkD;AAChE,eAAW,OAAO,QAAQ,MAAM,GAAG,EAAE,GAAG;AACtC,YAAM,UAAU,KAAK,QAAQ,GAAG,GAAG,WAAW,CAAC;AAC/C,YAAM,QAAQ,QAAQ,CAAC,GAAG,QAAQ;AAClC,UAAI,OAAO,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,EAAE;AAAA,IACtC;AACA,QAAI,QAAQ,SAAS,GAAI,KAAI,kBAAa,QAAQ,SAAS,EAAE,OAAO;AAEpE,QAAI,KAAK,QAAQ;AACf,UAAI;AAAA,8BACoB;AACxB;AAAA,IACF;AACA,QAAI;AAAA,oEAC4D;AAChE,QAAI,2EAAsE;AAC1E,QAAI,yEAAyE;AAC7E,QAAI,yEAAyE;AAC7E,QAAI,CAAE,MAAM,QAAQ,YAAY,QAAQ,MAAM,oBAAoB,KAAK,GAAG,GAAI;AAC5E,UAAI,WAAW;AACf;AAAA,IACF;AAEA,QAAI,UAAU;AACd,eAAW,OAAO,QAAS,KAAI,OAAW,MAAM,GAAG,EAAG;AACtD,UAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,QAAI,aAAa,OAAO,oBAAoB,OAAO,KAAK,KAAK,OAAO,EAAE,MAAM,SAAS;AACrF;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,QAAQ;AAG3B,QAAI,KAAK,eAAe,KAAK,YAAY,QAAQ;AAC/C,YAAM,IAAI,MAAM,+DAA+D;AAAA,IACjF;AACA,UAAMQ,eAAcT,OAAK,QAAQA,OAAK,QAAQ,KAAK,QAAQ,CAAC;AAC5D,UAAM,WAAW,KAAK,OAAO,SAAS,KAAK,SAAS,OAAO,KAAK,OAAO,SAAS,MAAM;AAEtF,eAAW,WAAW,UAAU;AAC9B,YAAM,iBAAiB,MAAM,aAAa,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;AACvE,YAAM,iBAAiB,MAAM,8BAA8B,gBAAgB,IAAI;AAC/E,YAAM,EAAE,KAAK,OAAO,SAAS,QAAQ,IAAI,UAAU,MAAM,SAASS,cAAa;AAAA,QAC7E,SAAS,KAAK;AAAA,QACd,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK;AAAA,QAClB,iBAAiB;AAAA,MACnB,CAAC;AAID,YAAM,QAAQ,OAAO,SAAS,OAAO,OAAO;AAC5C,YAAM,OAAO,KAAK,MACdT,OAAK,QAAQ,KAAK,IAAI,QAAQ,UAAU,EAAE,CAAC,IAC3CA,OAAK,QAAQS,cAAa,MAAO,QAAQ,GAAG,OAAO,QAAQ;AAE/D,YAAM,UAA0B;AAAA,QAC9B,EAAE,MAAM,GAAG,IAAI,QAAQ,MAAM,IAAI;AAAA,QACjC,EAAE,MAAM,GAAG,IAAI,SAAS,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC,IAAI,KAAK;AAAA,MACtE;AACA,YAAM,iBAAiB,iBACnB,MAAM,QAAQ;AAAA,QACZ,eAAe,OAAO,CAAC,SAAS,KAAK,OAAO,EAAE,IAAI,CAAC,SACjD;AAAA,UACE,YAAY,KAAK,OAAO;AAAA,UACxB,kBAAkB,KAAK,QAAS,OAAO;AAAA,QACzC,CAAC;AAAA,MACL,IACA,CAAC;AACL,YAAM,2BAA2B,GAAG,IAAI,mBAAmB,SAAS;AAAA,QAClE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM,eAAe,aAAa,KAAK,QAAQ;AAAA,UAC/C,MAAM,eAAe,SAAS,KAAK,IAAI;AAAA,UACvC,GAAG;AAAA,UACH,GAAG;AAAA,QACL;AAAA,QACA,SAAS;AAAA,UACP,SAAS,KAAK,WAAW;AAAA,UACzB,OAAO;AAAA,UACP,aAAa,CAAC,GAAG,KAAK,WAAW,EAAE,KAAK;AAAA,UACxC,aAAa,KAAK;AAAA,UAClB,OAAO;AAAA,QACT;AAAA,MACF,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;AAExB;AAAA,QACE,KAAK,OAAO,WAAM,MAAM,OAAO,MAAM,eAChC,MAAM,MAAM,KAAK,IAAI,MAAM,MAAM,MAAM,OAAO,MAAM,OAAO;AAAA,MAClE;AACA,UAAI,OAAOT,OAAK,SAAS,QAAQ,IAAI,GAAG,IAAI,CAAC,gCAAgC;AAC7E,iBAAW,KAAK,QAAS,KAAI,eAAe,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;AAAA,IACjE;AACA;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,SAAS;AAC5B,UAAMS,eAAcT,OAAK,QAAQA,OAAK,QAAQ,KAAK,QAAQ,CAAC;AAC5D,UAAM,WAAW,KAAK,OAAO,SAAS,KAAK,SAAS,OAAO,KAAK,OAAO,SAAS,MAAM;AAEtF,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,OAAO,SAAS,OAAO,OAAO;AAC5C,UAAI,CAAC,OAAO,OAAO;AAGjB,YAAI,KAAK,OAAO,QAAQ;AACtB,gBAAM,IAAI;AAAA,YACR,UAAU,OAAO;AAAA,UAEnB;AAAA,QACF;AACA;AAAA,MACF;AAEA,YAAM,QAA0C,CAAC;AACjD,YAAM,UAAkC,CAAC;AACzC,YAAM,cAAsC,CAAC;AAC7C,iBAAW,CAAC,SAAS,KAAK,KAAK,OAAO,QAAQ,OAAO,SAAS,MAAM,GAAG;AACrE,YAAI,CAAC,MAAM,KAAM;AACjB,cAAM,OAAO,IAAI,MAAM;AACvB,YAAI,MAAM,OAAQ,SAAQ,OAAO,IAAI,MAAM;AAC3C,YAAI,MAAM,WAAY,aAAY,OAAO,IAAI,MAAM;AAAA,MACrD;AACA,YAAM,iBAAiB,MAAM,aAAa,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;AACvE,YAAM,iBAAiB,MAAM;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,IAAI,IAAI,OAAO,KAAK,KAAK,CAAC;AAAA,QAC1B;AAAA,MACF;AACA,UAAI,eAAgB,QAAO,OAAO,SAAS,cAAc;AAEzD,YAAM,EAAE,KAAK,OAAO,SAAS,UAAU,SAAS,gBAAgB,IAAI;AAAA,QAClE;AAAA,QACA;AAAA,QACAS;AAAA,QACA,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,MAAMT,OAAK,QAAQS,cAAa,MAAM,MAAM,GAAG;AACrD,YAAM,WAAW,IAAI,QAAQ,UAAU,EAAE,IAAI;AAC7C,YAAM,YAAY,IAAI,QAAQ,UAAU,EAAE,IAAI;AAC9C,YAAM,UAA0B;AAAA,QAC9B,EAAE,MAAM,KAAK,MAAM,IAAI;AAAA,QACvB,EAAE,MAAM,UAAU,MAAM,KAAK,UAAU,OAAO,MAAM,CAAC,IAAI,KAAK;AAAA,MAChE;AACA,YAAM,iBAAiB,iBACnB,MAAM,QAAQ;AAAA,QACZ,eACG,OAAO,CAAC,SAAS,KAAK,WAAW,OAAO,OAAO,OAAO,KAAK,OAAO,CAAC,EACnE,IAAI,CAAC,SACJ;AAAA,UACE,YAAY,KAAK,OAAO;AAAA,UACxB,kBAAkB,KAAK,QAAS,OAAO;AAAA,QACzC,CAAC;AAAA,MACP,IACA,CAAC;AACL,YAAM,2BAA2B,WAAW,SAAS;AAAA,QACnD,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM,eAAe,aAAa,KAAK,QAAQ;AAAA,UAC/C,MAAM,eAAe,SAAS,KAAK,IAAI;AAAA,UACvC,GAAG;AAAA,UACH,GAAG,gBAAgB;AAAA,YACjB,CAAC,WAAW,OAAO,OAAO,WAAWT,OAAK,QAAQ,OAAO,IAAI,MAAM;AAAA,UACrE;AAAA,QACF;AAAA,QACA,SAAS;AAAA,UACP,YAAY,MAAM,MAAM;AAAA,UACxB,WAAW,MAAM,MAAM;AAAA,UACvB,OAAO,OAAO,QAAQ,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAAA,UAClE,OAAO;AAAA,QACT;AAAA,MACF,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;AAExB;AAAA,QACE,KAAK,OAAO,WAAM,MAAM,OAAO,MAAM,iBAChC,MAAM,MAAM,KAAK,IAAI,MAAM,MAAM,MAAM,MACzC,WAAW,SAAS,MAAM,MAAM,IAAI,KAAK;AAAA,MAC9C;AACA,UAAI,OAAOA,OAAK,SAAS,QAAQ,IAAI,GAAG,GAAG,CAAC,0BAA0B;AACtE,iBAAW,KAAK,QAAS,KAAI,eAAe,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE;AAAA,IACjE;AACA;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,SAAS;AAC5B,UAAM,WAAW,KAAK,OAAO,SAAS,KAAK,SAAS,OAAO,KAAK,OAAO,SAAS,MAAM;AACtF,UAAM,UAGD,CAAC;AACN,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,MAAM,WAAW,QAAQ,OAAO,SAAS,IAAI;AAC3D,YAAM,aAAa,cAAc,OAAO;AAAA,QACtC,aAAa,KAAK;AAAA,QAClB,iBAAiB,KAAK;AAAA,QACtB,WAAW,KAAK;AAAA,QAChB,OAAO,KAAK;AAAA,MACd,CAAC;AACD,cAAQ,KAAK,EAAE,OAAO,WAAW,CAAC;AAClC,UAAI,KAAK,KAAM;AACf,UAAI;AAAA,IAAO,OAAO,WAAM,MAAM,OAAO,MAAM,oBAAoB;AAC/D;AAAA,QACE,wBAAwB,MAAM,2BAA2B,iBAAiB,uBAAuB,KAC1F,MAAM,UAAU,MAAM,GAAG,CAAC,EAAE,IAAI,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,MACvD;AACA,UAAI,CAAC,MAAM,0BAA0B;AACnC,YAAI,6FAAwF;AAAA,MAC9F;AAEA,YAAM,SAAS,IAAI,IAAI,WAAW,QAAQ;AAC1C,UAAI;AAAA,wBAA2B;AAC/B,iBAAW,SAAS,MAAM,OAAO,MAAM,GAAG,EAAE,GAAG;AAC7C,cAAM,OAAO,OAAO,IAAI,MAAM,EAAE,IAAI,oBAAe;AACnD;AAAA,UACE,OAAO,MAAM,GAAG,OAAO,EAAE,CAAC,SAAS,MAAM,gBAAgB,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,aAChE,OAAO,MAAM,UAAU,EAAE,SAAS,CAAC,CAAC,kBAC/B,MAAM,eAAe,KAAK,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC,MAC7D,MAAM,QAAQ,MAAM,GAAG,CAAC,EAAE,IAAI,GAAG,EAAE,KAAK,GAAG,CAAC,GAAG,IAAI;AAAA,QAC5D;AAAA,MACF;AACA,UAAI,MAAM,OAAO,SAAS,GAAI,KAAI,kBAAa,MAAM,OAAO,SAAS,EAAE,OAAO;AAC9E,UAAI;AAAA,IAAO,WAAW,SAAS,MAAM,sBAAsB,WAAW,WAAW,KAAK,KAAK;AAC3F,UAAI,MAAM,QAAQ,OAAQ,KAAI,KAAK,MAAM,QAAQ,MAAM,uBAAuB;AAC9E,iBAAW,KAAK,MAAM,WAAY,KAAI,gBAAgB,CAAC,EAAE;AACzD,iBAAW,aAAa,WAAW,YAAY;AAC7C,YAAI,WAAW,UAAU,EAAE,KAAK,UAAU,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,MAChE;AAAA,IACF;AACA,QAAI,KAAK,MAAM;AACb,UAAI,KAAK,UAAU;AAAA,QACjB,SAAS;AAAA,QACT,MAAM,QAAQ,MAAM,CAAC,WAAW,OAAO,WAAW,IAAI;AAAA,QACtD,QAAQ,QAAQ,IAAI,CAAC,EAAE,OAAO,WAAW,OAAO,EAAE,GAAG,OAAO,WAAW,EAAE;AAAA,MAC3E,GAAG,MAAM,CAAC,CAAC;AAAA,IACb;AACA,QAAI,KAAK,SAAS,QAAQ,KAAK,CAAC,WAAW,CAAC,OAAO,WAAW,IAAI,EAAG,SAAQ,WAAW;AACxF;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,UAAU;AAC7B,UAAM,SAAS,KAAK,UAAU;AAC9B,UAAMS,eAAcT,OAAK,QAAQA,OAAK,QAAQ,KAAK,QAAQ,CAAC;AAC5D,UAAM,WAAW,MAAM,OAAO,CAAC,SAAS;AACtC,UAAI,KAAK,cAAc,QAAS,QAAO;AACvC,UAAI,KAAK,OAAO,UAAU,CAAC,KAAK,OAAO,SAAS,KAAK,OAAO,EAAG,QAAO;AACtE,UAAI,KAAK,OAAO,UAAU,CAAC,KAAK,OAAO,SAAS,KAAK,OAAO,EAAG,QAAO;AACtE,aAAO,QAAQ,KAAK,QAAQ,QAAQ,KAAK,SAAS,KAAK,OAAO,CAAC,CAAC;AAAA,IAClE,CAAC;AACD,QAAI,CAAC,SAAS,QAAQ;AACpB,YAAM,IAAI,MAAM,yEAAyE;AAAA,IAC3F;AACA,QAAI,KAAK,OAAO,SAAS,SAAS,GAAG;AACnC,YAAM,IAAI,MAAM,0EAA0E;AAAA,IAC5F;AAEA,eAAW,QAAQ,UAAU;AAC3B,YAAM,QAAQ,KAAK,QAAQ,QAAQ,KAAK,SAAS,KAAK,OAAO,CAAC;AAC9D,YAAM,QAAQ,OAAO,SAAS,OAAO,KAAK,OAAO;AACjD,YAAM,cAAcA,OAAK,QAAQS,cAAa,MAAM,QAAQ,GAAG,KAAK,OAAO,UAAU;AACrF,YAAM,OAAO,KAAK,MACdT,OAAK,QAAQ,KAAK,IAAI,QAAQ,6BAA6B,EAAE,CAAC,IAC9D;AACJ,YAAM,SAAS,cAAc,OAAO,MAAM;AAAA,QACxC;AAAA,QACA,aAAAS;AAAA,QACA,WAAWT,OAAK,SAAS,GAAG,IAAI,MAAM;AAAA,QACtC,SAAS,KAAK;AAAA,MAChB,CAAC;AACD,YAAM,UAA0B;AAAA,QAC9B,EAAE,MAAM,GAAG,IAAI,QAAQ,MAAM,OAAO,IAAI;AAAA,QACxC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,SAAS,IAAI,MAAM,OAAO,SAAS;AAAA,MAC9D;AACA,YAAM,2BAA2B,GAAG,IAAI,mBAAmB,SAAS;AAAA,QAClE,MAAM;AAAA,QACN,SAAS;AAAA,UACP,MAAM,eAAe,aAAa,KAAK,QAAQ;AAAA,UAC/C,MAAM,eAAe,SAAS,KAAK,IAAI;AAAA,UACvC,GAAG,OAAO;AAAA,QACZ;AAAA,QACA,SAAS;AAAA,UACP,OAAO,KAAK;AAAA,UACZ,SAAS,KAAK,WAAW;AAAA,UACzB;AAAA,UACA,OAAOA,OAAK,SAAS,GAAG,IAAI,MAAM;AAAA,UAClC,eAAe,OAAO,QAAQ;AAAA,UAC9B,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK,YAAY;AAAA,QAC7B;AAAA,MACF,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;AACxB;AAAA,QACE,KAAK,KAAK,OAAO,IAAI,KAAK,OAAO,WAAM,OAAO,QAAQ,MAAM,MAAM,aAC7D,OAAO,QAAQ,MAAM,KAAK,IAAI,OAAO,QAAQ,MAAM,MAAM,KAAK,MAAM;AAAA,MAC3E;AACA;AAAA,QACE,OAAOA,OAAK,SAAS,QAAQ,IAAI,GAAG,IAAI,CAAC,UACpCA,OAAK,SAAS,IAAI,CAAC,GAAG,OAAO,SAAS;AAAA,MAC7C;AAAA,IACF;AACA;AAAA,EACF;AAEA,QAAM,eACJ,KAAK,YAAY,aAAc,KAAK,YAAY,WAAW,CAAC,KAAK,MAC7D,cACA;AACN,QAAM,YAAY,oBAAI,IAAsB;AAC5C,QAAM,cAAc,CAAC,OAAe;AAClC,QAAI,WAAW,UAAU,IAAI,EAAE;AAC/B,QAAI,CAAC,UAAU;AACb,iBAAW,eAAe,IAAI,YAAY;AAC1C,gBAAU,IAAI,IAAI,QAAQ;AAAA,IAC5B;AACA,WAAO;AAAA,EACT;AACA,MAAI,KAAK,YAAY,SAAS;AAC5B,UAAM,WAAW,YAAY,uBAAwB;AACrD,QAAI;AAAA,kEAAgE;AACpE,UAAM,MAAM,MAAM,MAAM,UAAU,OAAO,MAAM,KAAK,MAAM,EAAE,YAAY,IAAI,CAAC;AAC7E,QAAI;AAAA,YAAe,IAAI,OAAO,8BAA8B,IAAI,OAAO,EAAE;AACzE,QAAI,IAAI,UAAU,QAAQ;AACxB,UAAI;AAAA,eAAkB,IAAI,UAAU,MAAM,IAAI;AAC9C,iBAAW,KAAK,IAAI,UAAU,MAAM,GAAG,EAAE,EAAG,KAAI,OAAO,CAAC,EAAE;AAAA,IAC5D;AACA,QAAI,IAAI,eAAe,QAAQ;AAC7B,UAAI;AAAA,gDAAmD,IAAI,eAAe,MAAM,IAAI;AACpF,iBAAW,KAAK,IAAI,eAAe,MAAM,GAAG,EAAE,EAAG,KAAI,OAAO,CAAC,EAAE;AAAA,IACjE;AACA,QAAI,IAAI,gBAAgB,QAAQ;AAC9B,UAAI;AAAA,iDAAoD,IAAI,gBAAgB,MAAM,IAAI;AACtF,UAAI,sBAAsB,IAAI,eAAe,CAAC;AAC9C;AAAA,QACE;AAAA;AAAA;AAAA;AAAA;AAAA,MAIF;AAAA,IACF;AACA,QAAI,KAAK,KAAK;AACZ,YAAM,IAAI,MAAM,WAAW,UAAU,OAAO,MAAM,EAAE,YAAY,IAAI,CAAC;AACrE,UAAI;AAAA,WAAc,CAAC,qBAAqB;AAAA,IAC1C;AACA,QAAI,KAAK,cAAc;AACrB,YAAM,EAAE,QAAQ,WAAW,IAAI,MAAM,iBAAiBA,OAAK,QAAQ,KAAK,QAAQ,GAAG,MAAM;AAAA,QACvF,YAAY;AAAA,QACZ,UAAU,SAAS;AAAA,QACnB,UAAU,MAAM,IAAI,CAAC,SAAS,KAAK,OAAO;AAAA,MAC5C,CAAC;AACD,UAAI,eAAe,MAAM,mBAAmBA,OAAK,SAAS,QAAQ,IAAI,GAAG,KAAK,QAAQ,CAAC,EAAE;AAKzF,YAAM,WAAW,MAAM,aAAa,KAAK,QAAQ;AACjD,YAAM,WAAW,MAAM,aAAa,UAAU;AAAA,QAC5C,QAAQ,KAAK;AAAA,QACb,QAAQ,KAAK;AAAA,MACf,CAAC,GAAG,OAAO,CAAC,SAAS,KAAK,aAAa,SAAS,EAAE;AAClD,UAAI,IAAI;AACR,iBAAW,QAAQ,SAAS;AAC1B,cAAM,MAAM,QAAQ,KAAK,SAAS,KAAK,OAAO;AAC9C,YAAI,KAAK,QAAQ,GAAG,GAAG,WAAW,aAAc;AAChD,eAAW,MAAM,KAAK,EAAE,UAAU,KAAK,SAAS,CAAC;AACjD;AAAA,MACF;AACA,YAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,UAAI,kBAAkB,CAAC,0CAA0C;AACjE,UAAI,WAAW,QAAQ;AACrB,YAAI,KAAK,WAAW,MAAM,wDAAwD;AAClF,mBAAW,MAAM,WAAW,MAAM,GAAG,EAAE,EAAG,KAAI,OAAO,EAAE,EAAE;AACzD,YAAI,WAAW,SAAS,GAAI,KAAI,kBAAa,WAAW,SAAS,EAAE,OAAO;AAAA,MAC5E;AAAA,IACF;AACA,QAAI;AAAA,sBAAyB,KAAK,IAAI,EAAE;AACxC;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,WAAW;AAC9B,UAAM,WAAW,YAAY,uBAAwB;AAMrD,UAAM,WAAW,KAAK,UAAU,KAAK;AACrC,UAAM,OAAO,WAAW,CAAC,MAAM,OAAO,QAAQ,MAAM,GAAG,IAAI;AAO3D,UAAM,UAAUA,OAAK,QAAQ,KAAK,IAAI;AACtC,QAAI,oBAAwC,CAAC;AAC7C,QAAI,eAAe;AACnB,QAAI,KAAK,WAAW;AAClB,YAAM,gBAAgBA,OAAK,QAAQ,KAAK,SAAS;AACjD,qBAAeA,OAAK,QAAQ,aAAa;AACzC,YAAM,WAAW,MAAM,+BAA+B,aAAa;AACnE,0BAAoB,SAAS,GAAG;AAChC,iBAAW,KAAK,SAAS,YAAa,MAAK,WAAW,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE;AAAA,IAC5E;AACA,UAAM,qBAAqB,kBAAkB,IAAI,CAAC,MAAM,eAAe,cAAc,CAAC,EAAE,QAAQ;AAChG,UAAM,YAAY;AAAA,MAChB,GAAG,oBAAI,IAAI;AAAA,QACT,GAAG;AAAA,QACH,GAAIC,aAAW,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC;AAAA,QACvC,GAAG,KAAK,OAAO,IAAI,CAAC,MAAMD,OAAK,QAAQ,CAAC,CAAC;AAAA,MAC3C,CAAC;AAAA,IACH;AACA,SAAK,gBAAgB,UAAU,MAAM,gBAAgB;AACrD,eAAW,KAAK,UAAW,MAAK,OAAOA,OAAK,SAAS,QAAQ,IAAI,GAAG,CAAC,CAAC,EAAE;AACxE,QAAI,CAAC,KAAK,OAAO,UAAU,CAAC,KAAK,WAAW;AAC1C;AAAA,QACE;AAAA;AAAA;AAAA;AAAA,MAGF;AAAA,IACF,WACE,KAAK,aACL,CAAC,kBAAkB,KAAK,CAAC,MAAM,eAAe,cAAc,CAAC,EAAE,iBAAiBA,OAAK,QAAQ,KAAK,QAAQ,CAAC,GAC3G;AACA;AAAA,QACE;AAAA;AAAA;AAAA,8BAEiC,KAAK,QAAQ;AAAA,MAChD;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,WAAW,WAAW,EAAE,UAAU,SAAS,GAAG,CAAC;AACrE,UAAM,EAAE,SAAS,MAAM,IAAI,MAAM,YAAY,UAAU,SAAS,EAAE,YAAY,KAAK,CAAC;AACpF,SAAK,KAAK,QAAQ,IAAI,iBAAc,QAAQ,MAAM,iBAAiB,KAAK,EAAE;AAC1E,QAAI,CAAC,QAAQ,QAAQ;AACnB,UAAI,SAAU,KAAI,IAAI;AAAA,UACjB,KAAI;AAAA,oBAAuB;AAChC;AAAA,IACF;AAMA,UAAM,WAAW,MAAM;AAAA,MACrB,KAAK;AAAA,MACL,kBAAkB,IAAI,CAAC,MAAM,eAAe,cAAc,CAAC,EAAE,YAAY;AAAA,MACzE,KAAK;AAAA,IACP;AAKA,UAAM,EAAE,SAAS,WAAW,UAAU,IAAI,oBAAoB,SAAS,iBAAiB,QAAQ;AAChG,UAAM,aAAa,OAAO,KAAK,gBAAgB,MAAM,EAAE,SAAS;AAChE,QAAI,YAAY;AACd,WAAK;AAAA,gEAAmE;AACxE,iBAAW,CAAC,IAAI,IAAI,KAAK,QAAS,MAAK,OAAO,GAAG,OAAO,EAAE,CAAC,IAAI,KAAK,MAAM,EAAE;AAC5E,UAAI,UAAU,OAAQ,MAAK,OAAO,mBAAmB,OAAO,EAAE,CAAC,IAAI,UAAU,MAAM,EAAE;AAAA,IACvF;AACA,QAAI,UAAU,MAAM;AAClB,WAAK;AAAA,6DAAgE;AACrE,iBAAW,CAAC,OAAO,IAAI,KAAK,UAAW,MAAK,OAAO,MAAM,OAAO,EAAE,CAAC,IAAI,KAAK,MAAM,EAAE;AACpF,WAAK,oEAA+D;AAAA,IACtE;AACA,QAAI,UAAU,QAAQ;AACpB;AAAA,QACE;AAAA,IAAO,UAAU,MAAM;AAAA;AAAA;AAAA;AAAA,MAIzB;AAAA,IACF;AAEA,QAAI,KAAK,QAAQ;AACf,UAAI,KAAK,MAAM;AACb,YAAI,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,MACtC,OAAO;AACL,cAAM,QAAQ,KAAK,MAAM,UAAU,QAAQ,MAAM,GAAG,EAAE;AACtD,mBAAW,KAAK,OAAO;AACrB,cAAI,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,IAAI,EAAE,MAAM,KAAK,EAAE,UAAU,MAAM,GAAG,EAAE,CAAC,KAAK,EAAE,OAAO,MAAM,GAAG,EAAE,CAAC,EAAE;AAAA,QAClG;AACA,YAAI,CAAC,KAAK,OAAO,QAAQ,SAAS,IAAI;AACpC,cAAI,kBAAa,QAAQ,SAAS,EAAE,8DAA8D;AAAA,QACpG;AAAA,MACF;AACA,WAAK;AAAA,8BAAiC;AACtC;AAAA,IACF;AAEA,UAAM,aAAa,YAAY;AAK7B,YAAM,WAAW,MAAM,aAAa,KAAK,QAAQ;AACjD,YAAM,WAAW,MAAM,aAAa,QAAQ,GAAG,OAAO,CAAC,SAAS,KAAK,aAAa,SAAS,EAAE;AAC7F,UAAI,IAAI;AACR,iBAAW,QAAQ,SAAS;AAC1B,cAAM,MAAM,QAAQ,KAAK,SAAS,KAAK,OAAO;AAC9C,cAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,YAAI,OAAO,WAAW,gBAAgB,MAAM,aAAa,mBAAoB;AAC7E,eAAW,MAAM,KAAK,EAAE,UAAU,KAAK,SAAS,CAAC;AACjD;AAAA,MACF;AACA,YAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,UAAI,EAAG,KAAI,eAAe,CAAC,yCAAyC;AAAA,IACtE;AAEA,UAAM,SAAS,OAAO,SAAiB,SAAyB;AAC9D,YAAM,QAAQ,gBAAgB,OAAO,OAAO;AAC5C,YAAM,MAAM,MAAM;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,UACE,cAAc,OAAO;AAAA,UACrB,UAAU;AAAA,UACV;AAAA,UACA,WAAWA,OAAK,QAAQ,OAAO,MAAM,MAAM,MAAM;AAAA,UACjD;AAAA,UACA,UAAU,KAAK;AAAA,QACjB;AAAA,QACA,EAAE,MAAM,KAAK,MAAM,MAAM,CAAC,KAAK,QAAQ,YAAY,IAAI;AAAA,MACzD;AACA;AAAA,QACE,cAAc,IAAI,QAAQ,cAAW,IAAI,IAAI,wBAAqB,IAAI,SAAS,MAC5E,IAAI,SAAS,gBAAa,IAAI,MAAM,KAAK;AAAA,MAC9C;AACA,UAAI,IAAI,WAAW,EAAG,OAAM,WAAW;AACvC,aAAO;AAAA,IACT;AAMA,QAAI,KAAK,OAAO,QAAQ;AACtB,YAAM,MAAM,MAAM,OAAO,KAAK,OAAO,CAAC,GAAI,OAAO;AACjD,UAAI,IAAI,WAAW;AACjB,YAAI;AAAA,iEAAoE;AACxE,YAAI;AAAA,CAAuB;AAAA,MAC7B;AACA;AAAA,IACF;AAEA,QAAI,CAAC,QAAQ,MAAM;AACjB,UAAI;AAAA,yDAAuD;AAC3D;AAAA,IACF;AAEA,QAAI;AAAA,IAAO,QAAQ,IAAI,mCAAmC;AAC1D,QAAI,iBAAiB;AACrB,eAAW,CAAC,SAAS,IAAI,KAAK,SAAS;AACrC,UAAI;AAAA,WAAS,OAAO,KAAK,KAAK,MAAM,UAAK;AACzC,YAAM,MAAM,MAAM,OAAO,SAAS,IAAI;AACtC,wBAAkB,IAAI;AAAA,IACxB;AACA,QAAI,gBAAgB;AAClB,UAAI;AAAA,iEAAoE;AACxE,UAAI;AAAA,CAAuB;AAAA,IAC7B;AACA;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,SAAS;AAC5B,UAAM,WAAW,YAAY,uBAAwB;AACrD,UAAM,SAA2C,CAAC;AAClD,qBAAiB,OAAO,YAAY,QAAQ,EAAE,GAAG;AAC/C,UAAI,IAAI,KAAK,SAAS,mBAAmB,GAAG;AAC1C,eAAO,KAAK,EAAE,IAAI,IAAI,IAAI,QAAQ,IAAI,OAAO,CAAC;AAAA,MAChD;AAAA,IACF;AACA,QAAI,CAAC,OAAO,QAAQ;AAClB,UAAI,2EAAsE;AAC1E;AAAA,IACF;AACA,QAAI;AAAA,IAAO,OAAO,MAAM,gCAAgC;AACxD,eAAW,KAAK,OAAO,MAAM,GAAG,EAAE,EAAG,KAAI,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,MAAM,GAAG,EAAE,CAAC,EAAE;AAChF,QAAI,OAAO,SAAS,GAAI,KAAI,kBAAa,OAAO,SAAS,EAAE,OAAO;AAElE,QAAI,KAAK,QAAQ;AACf,UAAI;AAAA,8BAAiC;AACrC;AAAA,IACF;AACA,QAAI;AAAA,4CAA+C,SAAS,EAAE,WAAW;AACzE,QAAI,qEAAqE;AACzE,QAAI,wDAAwD;AAC5D,QAAI,CAAE,MAAM,QAAQ,YAAY,OAAO,MAAM,eAAe,KAAK,GAAG,GAAI;AACtE,UAAI,WAAW;AACf;AAAA,IACF;AAEA,QAAI,UAAU;AACd,QAAI,SAAS;AACb,eAAW,KAAK,QAAQ;AACtB,UAAI;AACF,cAAM,cAAc,QAAQ,EAAE,EAAE,EAAE;AAClC;AAAA,MACF,SAAS,KAAK;AACZ;AACA,YAAI,mBAAmB,EAAE,EAAE,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,MACpF;AAAA,IACF;AACA,QAAI;AAAA,YAAe,OAAO,GAAG,SAAS,YAAY,MAAM,KAAK,EAAE,EAAE;AACjE;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,OAAO;AAC1B,QAAI,SAAS;AACb,eAAW,CAAC,YAAY,mBAAmB,KAAK,wBAAwB,OAAO,IAAI,GAAG;AACpF,gBAAU,MAAM,SAAS,YAAY,UAAU,GAAG,qBAAqB,MAAM;AAAA,QAC3E,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AACA,QAAI,YAAY,MAAM,YAAY;AAClC;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,YAAY,KAAK,YAAY,OAAO;AACvD,cAAU,IAAI;AACd,QAAI,KAAK,QAAQ;AACf,UAAI;AAAA,wCAA2C;AAC/C;AAAA,IACF;AACA,QAAI,KAAK,WAAW,QAAQ;AAC1B,YAAM,UAAU,eAAe,MAAM,IAAI;AACzC,YAAM,WAAW,oBAAI,IAAgC;AAIrD,iBAAW,SAAS,KAAK,QAAQ;AAC/B,cAAM,gBAAgB,YAAY,MAAM,QAAQ;AAChD,cAAM,UAAU,cAAc,UAAU,MAAM,cAAc,QAAQ,IAAI;AACxE,iBAAS,IAAI,MAAM,UAAU,OAAO;AACpC,YAAI,SAAS;AACX;AAAA,YACE;AAAA,aAAgB,WAAW,QAAQ,MAAM,QAAQ,SAAS,CAAC,eACrD,MAAM,QAAQ;AAAA,UACtB;AACA,cAAI,QAAQ,SAAS,MAAM,UAAU;AACnC,kBAAM,IAAI;AAAA,cACR,YAAY,MAAM,QAAQ,kBAAkB,MAAM,QAAQ,gCACxC,QAAQ,IAAI;AAAA,YAChC;AAAA,UACF;AACA,cAAI,QAAQ,SAAS,UAAU,MAAM,OAAO,QAAQ,WAAW;AAC7D,kBAAM,IAAI;AAAA,cACR,GAAG,MAAM,QAAQ,UAAU,WAAW,QAAQ,MAAM,MAAM,IAAI,CAAC,aAC1D,WAAW,QAAQ,MAAM,QAAQ,SAAS,CAAC;AAAA,YAClD;AAAA,UACF;AAAA,QACF,OAAO;AACL;AAAA,YACE;AAAA,IAAO,MAAM,QAAQ;AAAA,UAEvB;AAAA,QACF;AACA,cAAM,UAAU,QAAQ,IAAI,MAAM,QAAQ;AAC1C,YAAI,YAAY,UAAa,MAAM,OAAO,SAAS;AACjD,gBAAM,IAAI;AAAA,YACR,GAAG,MAAM,QAAQ,gBAAgB,WAAW,MAAM,UAAU,MAAM,IAAI,CAAC,sBACxD,WAAW,MAAM,UAAU,OAAO,CAAC;AAAA,UACpD;AAAA,QACF;AAAA,MACF;AACA,YAAM,eAAe,KAAK,OACvB,IAAI,CAAC,UAAU,GAAG,MAAM,QAAQ,IAAI,WAAW,MAAM,UAAU,MAAM,IAAI,CAAC,EAAE,EAC5E,KAAK,IAAI;AACZ,YAAM,KAAK,MAAM;AAAA,QACf,WAAW,YAAY,OAAO,KAAK,WAAW,MAAM;AAAA,QACpD,KAAK;AAAA,MACP;AACA,UAAI,CAAC,IAAI;AACP,YAAI,WAAW;AACf;AAAA,MACF;AACA,UAAI;AAAA,mBAAiB;AACrB,iBAAW,SAAS,KAAK,QAAQ;AAC/B,cAAM,gBAAgB,YAAY,MAAM,QAAQ;AAChD,cAAM,MAAM,MAAM,OAAO,eAAe,QAAQ,MAAM,YAAY,MAAM,KAAK,MAAM;AAAA,UACjF,QAAQ,QAAQ,IAAI,MAAM,QAAQ;AAAA,UAClC,YAAY;AAAA,QACd,CAAC;AACD;AAAA,UACE;AAAA,IAAO,MAAM,QAAQ,eAAe,IAAI,SAAS,YAAY,IAAI,MAAM,eACxD,WAAW,IAAI,MAAM,IAAI,KAAK,CAAC;AAAA,QAChD;AACA,YAAI;AACF,gBAAM,SAAS,SAAS,IAAI,MAAM,QAAQ;AAC1C,gBAAM,QAAQ,UAAU,cAAc,UAAU,MAAM,cAAc,QAAQ,IAAI;AAChF,cAAI,CAAC,UAAU,CAAC,MAAO,OAAM,IAAI,MAAM,kCAAkC;AACzE,gBAAM,WAAW,qBAAqB,QAAQ,KAAK;AACnD,cAAI,UAAU;AACZ,kBAAM,WAAW,SAAS,WACtB,GAAG,WAAW,SAAS,MAAM,SAAS,QAAQ,CAAC,cAC/C,GAAG,WAAW,SAAS,MAAM,SAAS,KAAK,CAAC;AAChD,gBAAI,KAAK,MAAM,QAAQ,oBAAoB,QAAQ,EAAE;AAAA,UACvD,OAAO;AACL,gBAAI,KAAK,MAAM,QAAQ,2CAA2C;AAAA,UACpE;AAAA,QACF,SAAS,KAAK;AACZ;AAAA,YACE,KAAK,MAAM,QAAQ,iCACd,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UACvD;AAAA,QACF;AACA,YAAI,IAAI,OAAQ,SAAQ,WAAW;AAAA,MACrC;AAAA,IACF;AACA,QAAI,KAAK,YAAY,SAAU;AAAA,EACjC;AAEA,MAAI,KAAK,YAAY,UAAU,KAAK,YAAY,OAAO;AACrD,QAAI;AAAA,gBAAc;AAClB,UAAM,QAAQ,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,cAAc,EAAE;AACpE,eAAW,CAAC,YAAY,mBAAmB,KAAK,wBAAwB,OAAO,IAAI,GAAG;AACpF,YAAM,MAAM,MAAM,KAAK,YAAY,UAAU,GAAG,MAAM,KAAK,MAAM;AAAA,QAC/D,YAAY;AAAA,QACZ,OAAO;AAAA,MACT,CAAC;AACD,YAAM,aAAa,IAAI;AACvB,YAAM,UAAU,IAAI;AACpB,YAAM,UAAU,IAAI;AACpB,YAAM,gBAAgB,IAAI;AAAA,IAC5B;AACA;AAAA,MACE;AAAA,IAAO,MAAM,SAAS,eAAY,MAAM,MAAM,4BACzC,MAAM,MAAM;AAAA,IACnB;AACA,QAAI,MAAM,UAAU,MAAM,aAAc,SAAQ,WAAW;AAC3D,QAAI,KAAK,YAAY,QAAQ;AAC3B,yBAAmB,OAAO,IAAI;AAC9B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,UAAU,KAAK,YAAY,OAAO;AACrD,UAAM,QAAQ,EAAE,UAAU,GAAG,SAAS,EAAE;AACxC,eAAW,CAAC,YAAY,mBAAmB,KAAK,wBAAwB,OAAO,IAAI,GAAG;AACpF,YAAM,MAAM,MAAM,UAAU,YAAY,UAAU,GAAG,MAAM,KAAK,MAAM;AAAA,QACpE,MAAM,KAAK;AAAA,QACX,MAAM,CAAC,KAAK;AAAA,QACZ,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,MAAM,oBAAoB,IAAI,CAAC,SAAS,QAAQ,KAAK,SAAS,KAAK,OAAO,CAAC;AAAA,QAC3E,OAAO;AAAA,MACT,CAAC;AACD,YAAM,YAAY,IAAI;AACtB,YAAM,WAAW,IAAI;AAAA,IACvB;AACA,QAAI,MAAM,aAAa,KAAK,MAAM,YAAY,GAAG;AAC/C,UAAI,8BAA8B;AAAA,IACpC,OAAO;AACL,UAAI;AAAA,aAAgB,MAAM,QAAQ,oBAAoB,MAAM,OAAO,EAAE;AAAA,IACvE;AACA,QAAI,KAAK,YAAY,SAAS,MAAM,QAAS,SAAQ,WAAW;AAChE,QAAI,KAAK,YAAY,QAAQ;AAC3B,yBAAmB,OAAO,IAAI;AAC9B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,KAAK,YAAY,WAAW,KAAK,YAAY,aAAa,KAAK,YAAY,OAAO;AACpF,QAAI;AAAA,oBAAkB;AACtB,UAAM,QAAQ,EAAE,YAAY,GAAG,SAAS,GAAG,QAAQ,GAAG,QAAQ,EAAE;AAChE,eAAW,CAAC,YAAY,mBAAmB,KAAK,wBAAwB,OAAO,IAAI,GAAG;AACpF,YAAM,gBAAgB,YAAY,UAAU;AAC5C,YAAM,MAAM,MAAM,YAAY,eAAe,qBAAqB,MAAM,KAAK,MAAM;AAAA,QACjF,YAAY;AAAA,QACZ,QAAQ,KAAK,YAAY;AAAA,QACzB,OAAO,KAAK;AAAA,MACd,CAAC;AACD,YAAM,cAAc,IAAI;AACxB,YAAM,WAAW,IAAI;AACrB,YAAM,UAAU,IAAI;AACpB,UAAI,KAAK,KAAK;AACZ,cAAM,UAAU,MAAM,SAAS,eAAe,qBAAqB,MAAM;AAAA,UACvE,YAAY;AAAA,QACd,CAAC;AAAA,MACH;AAAA,IACF;AACA;AAAA,MACE;AAAA,eAAkB,MAAM,UAAU,aAAa,MAAM,OAAO,YAAY,MAAM,MAAM;AAAA,IACtF;AACA,QAAI,MAAM,OAAQ,SAAQ,WAAW;AACrC,QAAI,KAAK,IAAK,KAAI,YAAY,MAAM,MAAM,qBAAqB;AAC/D,UAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,QAAI,uBAAuB,KAAK,IAAI,EAAE;AACtC,UAAM,oBAAoB,mBAAmB,OAAO,IAAI;AACxD,QAAI,KAAK,YAAY,SAAS,MAAM,KAAK,CAAC,SAAS,KAAK,OAAO,KAAK,CAAC,MAAM,QAAQ;AACjF,YAAM,WAAW,MAAM,QAAQ;AAAA,QAC7B,MAAM,OAAO,CAAC,SAAS,KAAK,OAAO,EAAE,IAAI,CAAC,SAAS,sBAAsB,MAAM,IAAI,CAAC;AAAA,MACtF,GAAG,OAAO,CAAC,SAAS,SAAS,IAAI;AACjC,YAAM,UAAU,QAAQ,OAAO,CAAC,SAAS,KAAK,UAAU,SAAS;AACjE,UAAI,QAAQ,QAAQ;AAClB;AAAA,UACE;AAAA,IAAO,QAAQ,MAAM,kBAAkB,QAAQ,WAAW,IAAI,QAAQ,OAAO,kBAC1E,oBACG,mDACA;AAAA,QACR;AAAA,MACF,OAAO;AACL,YAAI;AAAA,iGAAoG;AACxG,YAAI,gFAAgF;AAAA,MACtF;AAAA,IACF;AACA;AAAA,EACF;AAEA,MAAI,IAAI;AACV;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,UAAQ,MAAM;AAAA,WAAc,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,CAAI;AAChF,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["path","existsSync","readFile","path","path","chunk","hex","sha256","path","workflow","images","promptId","history","entry","status","message","existsSync","readFileSync","randomUUID","path","message","path","z","path","randomUUID","res","existsSync","readFileSync","DEFAULT_BASE_URL","path","sourceRef","message","DEFAULT_BASE_URL","SOURCE_PROTOCOL","value","asset","message","mode","mode","readFile","existsSync","path","path","readFile","existsSync","path","existsSync","readFile","path","path","path","path","existsSync","readFile","readFileSync","path","path","readFileSync","inputs","packed","existsSync","path","existsSync","path","path","readFile","rm","path","createHash","randomUUID","mkdir","readFile","rename","rm","writeFile","canonical","remove","cleanupErrors","readFile","existsSync","path","existsSync","readFile","path","message","hex","path","readFile","rm","source","output","path","existsSync","existsSync","path","existsSync","path","existsSync","path","sleep","log","message","sleep","log","existsSync","mkdir","readFile","rename","rm","writeFile","path","log","path","existsSync","readFile","mkdir","writeFile","rename","message","rm","existsSync","stat","path","message","path","existsSync","stat","existsSync","readFile","writeFile","path","mkdir","readFile","rename","rm","writeFile","existsSync","z","path","log","existsSync","readFile","writeFile","readFile","log","chunk","message","log","readFile","writeFile","existsSync","path","readFile","existsSync","path","existsSync","readFile","log","path","existsSync","log","mkdir","readFile","rename","rm","writeFile","existsSync","path","z","existsSync","readFile","readdir","rm","path","existsSync","path","rm","readFile","readdir","isRecord","mkdir","writeFile","readFile","path","escapeHtml","PNG_SIGNATURE","log","path","mkdir","writeFile","readFile","path","existsSync","readdir","readFile","z","z","path","canonical","message","readFile","existsSync","readdir","path","existsSync","readFile","z","SHA256_RE","z","path","message","digest","readFile","portableRelative","existsSync","path","existsSync","amount","item","readFile","result","loaded","lock","providers","manifestDir"]}
1
+ {"version":3,"sources":["../src/cli.ts","../src/env.ts","../src/provider.ts","../src/providers/comfyui.ts","../src/hash.ts","../src/png.ts","../src/media.ts","../src/providers/pixellab.ts","../src/client.ts","../src/types.ts","../src/providers/retrodiffusion.ts","../src/providers/scenario.ts","../src/providers/registry.ts","../src/manifest.ts","../src/outputs.ts","../src/lock.ts","../src/pipeline/pack.ts","../src/pipeline/plan.ts","../src/pipeline/quality-profile.ts","../src/pipeline/refine.ts","../src/artifacts.ts","../src/pipeline/audit.ts","../src/pipeline/revision.ts","../src/pipeline/submit.ts","../src/pipeline/poll.ts","../src/pipeline/fetch.ts","../src/source-url.ts","../src/pipeline/doctor.ts","../src/pipeline/adopt.ts","../src/cache.ts","../src/pick/sheet.ts","../src/pick/review-server.ts","../src/pick/server.ts","../src/pipeline/init.ts","../src/pipeline/salvage.ts","../src/workspace.ts","../src/pipeline/workspace.ts","../src/pipeline/cache-health.ts","../src/pipeline/tileset-export.ts","../src/pick/salvage-server.ts","../src/pick/salvage-sheet.ts","../src/recipes.ts","../src/pipeline/quality-regression.ts"],"sourcesContent":["#!/usr/bin/env node\nimport path from \"node:path\"\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { loadEnvFiles } from \"./env.ts\"\nimport {\n formatCost,\n measureBalanceChange,\n requireBalance,\n requireDelete,\n requireList,\n} from \"./provider.ts\"\nimport {\n createProvider,\n providerCredentialEnvs,\n providerFactory,\n type ProviderMode,\n} from \"./providers/registry.ts\"\nimport { loadManifest, resolveSpecs } from \"./manifest.ts\"\nimport { mountStyle, packSprites, packStyle, resolvePackInputs } from \"./pipeline/pack.ts\"\nimport { loadLock, remove as removeLock, saveLock, spendByUnit, upsert as upsertLock } from \"./lock.ts\"\nimport { sha256File } from \"./hash.ts\"\nimport {\n lockKey,\n type GridConfidence,\n type Lock,\n type Manifest,\n type ResolvedSpec,\n} from \"./types.ts\"\nimport { normalizeLockOutputPaths, resolveOutputPath } from \"./outputs.ts\"\nimport { buildPlan, resumeActions, summarize, type Plan } from \"./pipeline/plan.ts\"\nimport { submit } from \"./pipeline/submit.ts\"\nimport { poll } from \"./pipeline/poll.ts\"\nimport { fetchAssets, pushTags } from \"./pipeline/fetch.ts\"\nimport { doctor } from \"./pipeline/doctor.ts\"\nimport { adopt, formatUnmatchedRemote, tagAdopted, writePromptsBack } from \"./pipeline/adopt.ts\"\nimport { runPicker, type ReviewReadyInfo } from \"./pick/server.ts\"\nimport { scanAssets, buildManifest, writeManifestFile } from \"./pipeline/init.ts\"\nimport {\n loadClaims,\n findOrphans,\n groupOrphansByStyle,\n loadSiblingManifests,\n SALVAGED_SPEC_HASH,\n} from \"./pipeline/salvage.ts\"\nimport {\n loadWorkspace,\n saveWorkspace,\n toPortablePath,\n resolveProject,\n validateWorkspace,\n type WorkspaceProject,\n} from \"./workspace.ts\"\nimport { workspaceClaims, workspaceStatus } from \"./pipeline/workspace.ts\"\nimport { auditStyle, evaluateAudit, hex } from \"./pipeline/audit.ts\"\nimport { inspectCaches } from \"./pipeline/cache-health.ts\"\nimport {\n approveQualityRecord,\n checkQualityRecord,\n qualityRecordPath,\n refineAsset,\n} from \"./pipeline/refine.ts\"\nimport {\n inspectQualityProfile,\n refineQualityProfiles,\n requireApprovedQualitySources,\n} from \"./pipeline/quality-profile.ts\"\nimport { exportTileset, type TilesetFormat } from \"./pipeline/tileset-export.ts\"\nimport { runSalvage } from \"./pick/salvage-server.ts\"\nimport type { BalanceInfo, Provider } from \"./provider.ts\"\nimport {\n writeManagedArtifactBundle,\n type ArtifactFile,\n type ArtifactSource,\n} from \"./artifacts.ts\"\nimport {\n installRecipe,\n listBundledRecipes,\n resolveRecipe,\n verifyRecipe,\n} from \"./recipes.ts\"\nimport {\n checkQualityBaseline,\n resolveQualityInputs,\n snapshotQualityBaseline,\n} from \"./pipeline/quality-regression.ts\"\n\nconst log = (msg = \"\") => console.log(msg)\n\ninterface CliWritable {\n isTTY?: boolean\n write(chunk: string): unknown\n}\n\n/**\n * Interactive readiness is progress, not command output. Keep it on stdout in\n * a terminal, but use stderr when stdout is piped so consumers such as `tail`\n * cannot hold the only copy of the live URL until the server exits.\n */\nexport function announceReviewReady(\n info: ReviewReadyInfo,\n stdout: CliWritable = process.stdout,\n stderr: CliWritable = process.stderr,\n): void {\n const stream = stdout.isTTY ? stdout : stderr\n const count = info.keys.length\n stream.write(\n `\\n ${count} asset${count === 1 ? \"\" : \"s\"} awaiting selection: ${info.url}\\n` +\n \" (leave this running; it exits once you apply)\\n\\n\",\n )\n}\n\nasync function provenanceFile(id: string, file: string): Promise<ArtifactSource> {\n const absolute = path.resolve(file)\n return {\n id,\n path: absolute,\n sha256: existsSync(absolute) ? await sha256File(absolute) : null,\n included: true,\n }\n}\n\ninterface Args {\n command: string\n manifest: string\n lock: string\n styles: string[]\n assets: string[]\n force: boolean\n yes: boolean\n budget?: number\n /** Repeatable provider-keyed budgets used by a mixed-provider run. */\n providerBudgets: Record<string, number>\n dryRun: boolean\n all: boolean\n json: boolean\n check: boolean\n noOpen: boolean\n tag: boolean\n from?: string\n out?: string\n generator?: string\n exclude: string[]\n name?: string\n writePrompts: boolean\n columns?: number\n port?: number\n inputs?: string\n claims: string[]\n format?: TilesetFormat\n outputRoles: string[]\n primaryOnly: boolean\n prune: boolean\n maxDistance?: number\n minTransparency?: number\n maxColors?: number\n sigma?: number\n palette: string[]\n fixerPython?: string\n fixerRevision?: string\n minGridConfidence?: GridConfidence\n reviewer?: string\n note?: string\n /** ComfyUI `models` directory used for offline recipe model verification. */\n modelRoot?: string\n /** Subcommand for `quality`, `recipe`, `refine`, or `workspace`. */\n subcommand?: string\n /** Path to a workspace catalog. Defaults to `pixelkiln.workspace.json` in cwd. */\n workspace?: string\n /** Positional target for recipe and workspace subcommands. */\n target?: string\n /** Account provider selector; also the `workspace add` catalog provider hint. */\n provider?: string\n /** `workspace add`: free-form account label, e.g. distinguishing sandboxes. */\n account?: string\n /**\n * Raw `--lock` value with no manifest-relative default applied. `workspace\n * add` needs to know whether the user actually passed `--lock`, since the\n * ambient default (beside `--manifest`, which usually names an unrelated\n * project) is meaningless for the manifest being registered.\n */\n explicitLock?: string\n}\n\nconst VALUE_FLAGS = [\n \"--manifest\", \"--lock\", \"--style\", \"--only\", \"--budget\", \"--port\",\n \"--from\", \"--out\", \"--generator\", \"--exclude\", \"--name\", \"--claims\", \"--columns\", \"--inputs\", \"--format\",\n \"--output-role\", \"--max-distance\", \"--min-transparency\", \"--max-colors\", \"--sigma\", \"--workspace\",\n \"--provider\", \"--account\", \"--palette\", \"--fixer-python\", \"--fixer-revision\", \"--min-grid-confidence\",\n \"--reviewer\", \"--note\",\n \"--model-root\",\n] as const\nconst BOOL_FLAGS = [\n \"--force\", \"--yes\", \"-y\", \"--dry-run\", \"--all\", \"--json\", \"--check\", \"--no-open\", \"--tag\", \"--write-prompts\", \"--primary-only\", \"--prune\",\n] as const\n\nexport const COMMANDS = [\n \"init\", \"plan\", \"doctor\", \"gen\", \"submit\", \"poll\", \"pick\", \"fetch\", \"restore\", \"adopt\", \"accept\",\n \"salvage\", \"purge\", \"prune\", \"audit\", \"cache\", \"pack\", \"mount\", \"export\", \"tag\", \"balance\", \"status\",\n \"quality\", \"refine\", \"recipe\", \"workspace\", \"help\", \"--help\", \"-h\", \"--version\", \"-v\",\n] as const\n\nconst WORKSPACE_SUBCOMMANDS = [\"add\", \"remove\", \"list\", \"status\", \"claims\"] as const\nconst REFINE_SUBCOMMANDS = [\"run\", \"approve\", \"check\"] as const\nconst RECIPE_SUBCOMMANDS = [\"list\", \"inspect\", \"install\", \"verify\"] as const\nconst QUALITY_SUBCOMMANDS = [\"snapshot\", \"check\"] as const\n\n/**\n * Strict parsing. Unknown flags are a hard error rather than being ignored,\n * because a silently-dropped filter is expensive here: `--styles neon` (plural,\n * a typo) would otherwise fall through to \"no filter\" and generate the entire\n * manifest instead of one style.\n */\nexport function parseArgs(argv: string[]): Args {\n const [command = \"help\"] = argv\n if (!(COMMANDS as readonly string[]).includes(command)) {\n throw new Error(`Unknown command \"${command}\". Run \\`pixelkiln help\\` for the list.`)\n }\n\n let rest = argv.slice(1)\n let subcommand: string | undefined\n let target: string | undefined\n if (command === \"quality\") {\n subcommand = rest[0]\n if (subcommand === undefined || subcommand.startsWith(\"-\")) {\n throw new Error(`quality needs a subcommand: ${QUALITY_SUBCOMMANDS.join(\", \")}`)\n }\n if (!(QUALITY_SUBCOMMANDS as readonly string[]).includes(subcommand)) {\n throw new Error(\n `Unknown quality subcommand \"${subcommand}\". Known: ${QUALITY_SUBCOMMANDS.join(\", \")}`,\n )\n }\n rest = rest.slice(1)\n } else if (command === \"recipe\") {\n subcommand = rest[0]\n if (subcommand === undefined || subcommand.startsWith(\"-\")) {\n throw new Error(`recipe needs a subcommand: ${RECIPE_SUBCOMMANDS.join(\", \")}`)\n }\n if (!(RECIPE_SUBCOMMANDS as readonly string[]).includes(subcommand)) {\n throw new Error(\n `Unknown recipe subcommand \"${subcommand}\". Known: ${RECIPE_SUBCOMMANDS.join(\", \")}`,\n )\n }\n rest = rest.slice(1)\n if (subcommand !== \"list\") {\n target = rest[0]\n if (target === undefined || target.startsWith(\"-\")) {\n throw new Error(`recipe ${subcommand} needs a recipe id, selector, or path.`)\n }\n rest = rest.slice(1)\n }\n } else if (command === \"workspace\") {\n subcommand = rest[0]\n if (subcommand === undefined || subcommand.startsWith(\"-\")) {\n throw new Error(`workspace needs a subcommand: ${WORKSPACE_SUBCOMMANDS.join(\", \")}`)\n }\n if (!(WORKSPACE_SUBCOMMANDS as readonly string[]).includes(subcommand)) {\n throw new Error(\n `Unknown workspace subcommand \"${subcommand}\". Known: ${WORKSPACE_SUBCOMMANDS.join(\", \")}`,\n )\n }\n rest = rest.slice(1)\n if (subcommand === \"add\" || subcommand === \"remove\") {\n target = rest[0]\n if (target === undefined || target.startsWith(\"-\")) {\n throw new Error(\n subcommand === \"add\"\n ? \"workspace add needs a manifest path.\"\n : \"workspace remove needs a project id or manifest path.\",\n )\n }\n rest = rest.slice(1)\n }\n } else if (command === \"refine\") {\n subcommand = rest[0]?.startsWith(\"-\") || rest[0] === undefined ? \"run\" : rest[0]\n if (!(REFINE_SUBCOMMANDS as readonly string[]).includes(subcommand)) {\n throw new Error(\n `Unknown refine subcommand \"${subcommand}\". Known: ${REFINE_SUBCOMMANDS.join(\", \")}`,\n )\n }\n if (rest[0] === subcommand) rest = rest.slice(1)\n }\n\n for (let i = 0; i < rest.length; i++) {\n const token = rest[i]!\n if (!token.startsWith(\"-\")) {\n throw new Error(`Unexpected argument \"${token}\". Options must be passed with a named flag.`)\n }\n if ((BOOL_FLAGS as readonly string[]).includes(token)) continue\n if ((VALUE_FLAGS as readonly string[]).includes(token)) {\n const value = rest[i + 1]\n // A numeric token is a value even though it starts with \"-\", so\n // `--budget -5` reaches the range check and reports the real problem.\n const looksLikeFlag = value !== undefined && value.startsWith(\"-\") && !Number.isFinite(Number(value))\n if (value === undefined || looksLikeFlag) {\n throw new Error(`${token} needs a value.`)\n }\n i++\n continue\n }\n throw new Error(\n `Unknown flag \"${token}\". Known flags: ${[...VALUE_FLAGS, ...BOOL_FLAGS].join(\", \")}`,\n )\n }\n\n const get = (flag: string) => {\n const i = rest.indexOf(flag)\n return i >= 0 ? rest[i + 1] : undefined\n }\n /**\n * Collects every occurrence of a list flag, not just the first.\n *\n * `--style a --style b` is the natural way to write this and previously kept\n * only `a`, silently discarding `b` — so a run that looked like it covered\n * two styles covered one, and `plan` quoted a cost for work it would not do.\n * Repeated flags now accumulate; commas still work within each occurrence.\n */\n const list = (flag: string) => {\n const out: string[] = []\n for (let i = 0; i < rest.length; i++) {\n if (rest[i] !== flag) continue\n for (const part of (rest[i + 1] ?? \"\").split(\",\")) {\n const v = part.trim()\n if (v) out.push(v)\n }\n }\n return [...new Set(out)]\n }\n\n const rawColumns = get(\"--columns\")\n let columns: number | undefined\n if (rawColumns !== undefined) {\n columns = Number(rawColumns)\n // Same guard as --budget: NaN would silently fall through to the default\n // and quietly produce a differently-shaped sheet than asked for.\n if (!Number.isInteger(columns) || columns < 1 || columns > 1024) {\n throw new Error(`--columns must be a whole number between 1 and 1024, got \"${rawColumns}\"`)\n }\n }\n\n const rawPort = get(\"--port\")\n let port: number | undefined\n if (rawPort !== undefined) {\n port = Number(rawPort)\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(`--port must be a whole number between 1 and 65535, got \"${rawPort}\"`)\n }\n }\n\n let budget: number | undefined\n // A registry id is intentionally only constrained to non-empty text. Use a\n // null-prototype dictionary so ids such as \"constructor\" cannot interact\n // with Object.prototype while budgets are parsed.\n const providerBudgets: Record<string, number> = Object.create(null)\n const rawBudgets = rest.flatMap((token, index) => token === \"--budget\" ? [rest[index + 1]!] : [])\n for (const rawBudget of rawBudgets) {\n const separator = rawBudget.indexOf(\"=\")\n if (separator >= 0) {\n const providerId = rawBudget.slice(0, separator).trim()\n const rawAmount = rawBudget.slice(separator + 1).trim()\n const amount = Number(rawAmount)\n if (!providerId || /[=\\s]/.test(providerId) || !Number.isFinite(amount) || amount < 0) {\n throw new Error(\n `--budget must be a non-negative number or provider=number, got \"${rawBudget}\".`,\n )\n }\n if (Object.hasOwn(providerBudgets, providerId)) {\n throw new Error(`--budget repeats provider \"${providerId}\".`)\n }\n providerBudgets[providerId] = amount\n continue\n }\n const amount = Number(rawBudget)\n if (!Number.isFinite(amount) || amount < 0) {\n throw new Error(`--budget must be a non-negative number, got \"${rawBudget}\".`)\n }\n if (budget !== undefined) throw new Error(\"Only one unkeyed --budget may be passed.\")\n budget = amount\n }\n if (budget !== undefined && Object.keys(providerBudgets).length) {\n throw new Error(\"Do not mix an unkeyed --budget with provider-keyed budgets.\")\n }\n\n const manifest = get(\"--manifest\") ?? \"pixelkiln.manifest.json\"\n const rawFormat = get(\"--format\")\n if (rawFormat && rawFormat !== \"generic\" && rawFormat !== \"tiled\" && rawFormat !== \"godot\") {\n throw new Error(`--format must be generic, tiled, or godot, got \"${rawFormat}\"`)\n }\n const numberOption = (\n flag: string,\n opts: { min: number; max?: number; integer?: boolean },\n ): number | undefined => {\n const raw = get(flag)\n if (raw === undefined) return undefined\n const value = Number(raw)\n if (\n !Number.isFinite(value) ||\n value < opts.min ||\n (opts.max !== undefined && value > opts.max) ||\n (opts.integer && !Number.isInteger(value))\n ) {\n const range = opts.max === undefined ? `at least ${opts.min}` : `${opts.min} to ${opts.max}`\n throw new Error(`${flag} must be ${opts.integer ? \"a whole number \" : \"a number \"}${range}, got \"${raw}\"`)\n }\n return value\n }\n const rawGridConfidence = get(\"--min-grid-confidence\")\n if (\n rawGridConfidence !== undefined &&\n rawGridConfidence !== \"low\" && rawGridConfidence !== \"medium\" && rawGridConfidence !== \"high\"\n ) {\n throw new Error(\n `--min-grid-confidence must be low, medium, or high, got \"${rawGridConfidence}\"`,\n )\n }\n return {\n command,\n manifest,\n lock: get(\"--lock\") ?? path.join(path.dirname(path.resolve(manifest)), \"pixelkiln.lock.json\"),\n explicitLock: get(\"--lock\"),\n styles: list(\"--style\"),\n assets: list(\"--only\"),\n force: rest.includes(\"--force\"),\n yes: rest.includes(\"--yes\") || rest.includes(\"-y\"),\n budget,\n providerBudgets,\n dryRun: rest.includes(\"--dry-run\"),\n all: rest.includes(\"--all\"),\n json: rest.includes(\"--json\"),\n check: rest.includes(\"--check\"),\n noOpen: rest.includes(\"--no-open\"),\n tag: rest.includes(\"--tag\"),\n from: get(\"--from\"),\n out: get(\"--out\"),\n generator: get(\"--generator\"),\n exclude: list(\"--exclude\"),\n name: get(\"--name\"),\n writePrompts: rest.includes(\"--write-prompts\"),\n columns,\n port,\n inputs: get(\"--inputs\"),\n claims: list(\"--claims\"),\n format: rawFormat as TilesetFormat | undefined,\n outputRoles: list(\"--output-role\"),\n primaryOnly: rest.includes(\"--primary-only\"),\n prune: rest.includes(\"--prune\"),\n maxDistance: numberOption(\"--max-distance\", { min: 0 }),\n minTransparency: numberOption(\"--min-transparency\", { min: 0, max: 1 }),\n maxColors: numberOption(\"--max-colors\", { min: 1, integer: true }),\n sigma: numberOption(\"--sigma\", { min: Number.EPSILON }),\n palette: list(\"--palette\"),\n fixerPython: get(\"--fixer-python\"),\n fixerRevision: get(\"--fixer-revision\"),\n minGridConfidence: rawGridConfidence as GridConfidence | undefined,\n reviewer: get(\"--reviewer\"),\n note: get(\"--note\"),\n modelRoot: get(\"--model-root\"),\n subcommand,\n workspace: get(\"--workspace\"),\n target,\n provider: get(\"--provider\"),\n account: get(\"--account\"),\n }\n}\n\nconst HELP = `pixelkiln — manifest-driven pixel art generation\n\n pixelkiln <command> [options]\n\nCommands\n init Scaffold a manifest from an existing tree of PNGs.\n plan Diff manifest against lockfile and disk. Costs nothing. Start here.\n doctor Validate project state, recovery paths, and provider connectivity.\n gen Full run: submit → poll → pick → fetch. The everyday command.\n submit Queue generation jobs only.\n poll Advance in-flight jobs to their settled state.\n pick Open the contact sheet to choose among candidates.\n fetch Download selected objects to their manifest paths.\n restore Re-download missing generated files without generating new art.\n adopt Match existing account objects to files already in the repo.\n accept Keep existing art after a style reword — re-baseline, do not regenerate.\n salvage Triage account objects no lockfile claims. Recovers usable art.\n One session per matching style unless --style forces a single one.\n audit Measure how consistently a style's assets hold together. Offline.\n refine Build/check manifest quality profiles, or refine one --from PNG.\n Native grid, fixed palette, audit, and human approval. Offline.\n recipe List, inspect, install, or verify versioned workflow packs. Offline.\n quality Snapshot or check measurable image regressions. Offline.\n cache Inspect local recovery/object-hash caches; optionally verify or prune.\n pack Composite sprites into a PNG/atlas/provenance bundle. Offline.\n mount Write a style's sprites into their declared cells of an existing\n sheet, leaving every other pixel untouched. Offline.\n export Build a tile atlas, engine metadata, and offline provenance record.\n purge Delete objects previously tagged discard. Irreversible; asks first.\n prune Drop lock entries the manifest no longer declares. Offline; asks\n first. Local art is untouched.\n tag Push manifest tags to the objects upstream (free).\n balance Show the provider's remaining balance.\n status Summarise the lockfile.\n workspace Register sibling projects and derive account-wide claims/status.\n add/remove/list/status/claims. Offline.\n\nOptions\n --columns <n> pack/export: sprites or tiles per row (default: near-square)\n --port <n> Local review-server port (default: choose a free port)\n --inputs <path> pack/quality snapshot: JSON input list; needs --out\n --format <format> export: generic (default), tiled, or godot\n --output-role <r> pack: include only this output role (repeatable)\n --primary-only pack: include only unambiguous primary/single outputs\n --max-distance <n> audit: maximum palette distance\n --min-transparency <0..1> audit: minimum transparent canvas share\n --max-colors <n> audit: maximum distinct opaque colors\n --sigma <n> audit: relative outlier cutoff (default: 1.5)\n --palette <hexes> refine: final comma-separated #rrggbb colors (repeatable)\n --fixer-python <path> refine: override Python with Pixel Art Fixer installed\n --fixer-revision <sha> refine: Pixel Art Fixer revision to record\n --min-grid-confidence <level> refine: high (default), medium, or low\n --reviewer <name> refine approve: human reviewer recorded in provenance\n --note <text> refine approve: optional review note\n --model-root <dir> recipe verify: also hash required local model files\n --prune cache: remove invalid/unreferenced local cache data\n --manifest <path> Default: pixelkiln.manifest.json\n --lock <path> Default: pixelkiln.lock.json beside the manifest\n --style a,b Restrict to these styles\n --only id1,id2 Restrict to these asset ids\n --budget <n|provider=n> Refuse to exceed one provider ceiling; repeat keyed budgets\n for a mixed-provider run\n --provider <id> Choose the account for balance/adopt/salvage/purge in a mixed manifest\n --force Regenerate, replace a fetch destination, or rebuild managed output\n --dry-run Never spend; doctor also skips provider connectivity\n --all salvage --dry-run: list every unclaimed object, not just the first 30\n --json Machine-readable output where supported, including quality checks\n --check plan/audit/cache: exit nonzero when the selected state is unsafe\n --yes, -y Skip the confirmation prompt\n --no-open Do not auto-open the browser during pick\n --tag Also push tags upstream after fetch\n --claims a.json,b Other projects' lockfiles (salvage; required if account is shared)\n --workspace <path> Workspace catalog (default: pixelkiln.workspace.json). Also\n derives salvage's claim set instead of repeated --claims.\n --from <path> Source for init/path-mode refine, or baseline for quality check\n --write-prompts adopt: recover prompts into the manifest\n\nExamples\n pixelkiln plan\n pixelkiln gen --style heybud-premium --budget 400\n pixelkiln gen --only first_review --force\n pixelkiln adopt --tag\n pixelkiln pack --style heybud-premium\n pixelkiln pack --inputs sprites.json --out dist/sheet # no manifest needed\n pixelkiln mount --style ground\n pixelkiln export --style ground --only terrain --format tiled\n pixelkiln refine --style environment\n pixelkiln refine check --style environment\n pixelkiln refine --from source.png --out final.png --palette \"#101820,#f2aa4c\"\n pixelkiln refine approve --from final.pixelkiln.json --reviewer \"Your Name\"\n pixelkiln refine check --from final.pixelkiln.json\n pixelkiln recipe list\n pixelkiln recipe install comfyui/pixel-art-xl-environment\n pixelkiln recipe verify pixelkiln-recipes/comfyui/pixel-art-xl-environment/1.0.0 --model-root /path/to/ComfyUI/models\n pixelkiln quality snapshot --inputs quality-inputs.json --out pixelkiln.quality.json\n pixelkiln quality check --from pixelkiln.quality.json\n pixelkiln workspace add ../other-game/pixelkiln.manifest.json\n pixelkiln workspace status --json\n pixelkiln salvage --workspace pixelkiln.workspace.json\n`\n\nfunction printPlan(plan: Plan): void {\n const counts = summarize(plan)\n const order = [\n \"blocked\", \"missing\", \"untracked\", \"stale\", \"failed\", \"recoverable\", \"in-flight\", \"orphaned\", \"ok\",\n ] as const\n for (const state of order) {\n const items = plan.items.filter((i) => i.state === state)\n if (!items.length) continue\n log(`\\n ${state} (${items.length})`)\n for (const item of items.slice(0, 40)) {\n log(` ${item.key.padEnd(42)} ${item.reason}`)\n }\n if (items.length > 40) log(` … and ${items.length - 40} more`)\n }\n log(\n `\\n totals: ${counts.ok} ok · ${counts.blocked} blocked · ${counts.missing} missing · ${counts.untracked} untracked · ` +\n `${counts.stale} stale · ${counts[\"in-flight\"]} in-flight · ${counts.orphaned} orphaned · ` +\n `${counts.recoverable} recoverable · ${counts.failed} failed`,\n )\n if (plan.actionable.length) {\n for (const group of plan.groups) {\n log(\n ` ${group.provider}: ${group.actionable.length} asset(s) — ` +\n `${formatCost(group.costUnit, group.cost)}, ` +\n `${group.candidates} candidate/output image(s)`,\n )\n }\n } else {\n log(` nothing to generate`)\n }\n const qualityItems = plan.items.flatMap((item) => item.quality ? [item.quality] : [])\n if (qualityItems.length) {\n const approved = qualityItems.filter((item) => item.state === \"approved\").length\n log(`\\n quality: ${approved}/${qualityItems.length} approved`)\n for (const item of qualityItems.filter((item) => item.state !== \"approved\").slice(0, 40)) {\n log(` ${item.state.padEnd(16)} ${item.key} ${item.reason}`)\n }\n }\n}\n\nfunction printResumeActions(specs: ResolvedSpec[], lock: Lock): number {\n const actions = resumeActions(specs, lock)\n for (const action of actions) {\n const shown = action.keys.slice(0, 3).join(\", \")\n const more = action.keys.length > 3 ? `, +${action.keys.length - 3} more` : \"\"\n log(\n ` next: pixelkiln ${action.command} — ${action.keys.length} asset` +\n `${action.keys.length === 1 ? \"\" : \"s\"} (${shown}${more})`,\n )\n }\n return actions.length\n}\n\nfunction manifestProviderIds(manifest: Manifest): string[] {\n return [...new Set(\n Object.values(manifest.styles).map((style) => style.provider ?? manifest.provider),\n )].sort()\n}\n\nfunction specsByRecordedProvider(specs: ResolvedSpec[], lock: Lock): Map<string, ResolvedSpec[]> {\n const grouped = new Map<string, ResolvedSpec[]>()\n for (const spec of specs) {\n const key = lockKey(spec.styleId, spec.assetId)\n const provider = lock.entries[key]?.provider ?? spec.provider\n grouped.set(provider, [...(grouped.get(provider) ?? []), spec])\n }\n return grouped\n}\n\nfunction accountProviderId(manifest: Manifest, requested: string | undefined, command: string): string {\n const providers = manifestProviderIds(manifest)\n if (requested) {\n if (!providers.includes(requested)) {\n throw new Error(\n `Provider \"${requested}\" is not used by this manifest. Used: ${providers.join(\", \")}.`,\n )\n }\n return requested\n }\n if (providers.length > 1) {\n throw new Error(\n `${command} is account-scoped and this manifest uses ${providers.join(\", \")}. ` +\n `Pass --provider <id>.`,\n )\n }\n return providers[0] ?? manifest.provider\n}\n\nfunction budgetsForPlan(plan: Plan, args: Args): Map<string, number | undefined> {\n const providerIds = new Set(plan.groups.map((group) => group.provider))\n const keyed = Object.entries(args.providerBudgets)\n for (const [provider] of keyed) {\n if (!providerIds.has(provider)) {\n throw new Error(\n `Budget names provider \"${provider}\", but this run has work only for ` +\n `${[...providerIds].join(\", \") || \"no providers\"}.`,\n )\n }\n }\n if (plan.groups.length > 1 && args.budget !== undefined) {\n throw new Error(\n \"A mixed-provider run needs provider-keyed budgets, for example \" +\n \"--budget pixellab=40 --budget retrodiffusion=1.25.\",\n )\n }\n const out = new Map<string, number | undefined>()\n for (const group of plan.groups) {\n const ceiling = args.providerBudgets[group.provider]\n if (\n plan.groups.length > 1 &&\n group.costUnit !== \"free\" &&\n group.cost > 0 &&\n ceiling === undefined\n ) {\n throw new Error(\n `Mixed-provider run is missing --budget ${group.provider}=<amount> for ` +\n `${formatCost(group.costUnit, group.cost)} of planned work.`,\n )\n }\n out.set(group.provider, ceiling ?? (plan.groups.length === 1 ? args.budget : undefined))\n }\n return out\n}\n\nasync function confirm(question: string, auto: boolean): Promise<boolean> {\n if (auto) return true\n if (!process.stdin.isTTY) {\n log(` (non-interactive; pass --yes to proceed)`)\n return false\n }\n process.stdout.write(`${question} [y/N] `)\n const answer = await new Promise<string>((resolve) => {\n process.stdin.setEncoding(\"utf8\")\n process.stdin.once(\"data\", (d) => resolve(String(d).trim().toLowerCase()))\n })\n process.stdin.pause()\n return answer === \"y\" || answer === \"yes\"\n}\n\n/**\n * Loads a workspace catalog and derives its complete claim set, refusing when\n * the catalog itself is unsafe — missing entirely, or containing duplicate\n * ids/locks, or a registered manifest or lock that does not exist — rather\n * than silently deriving a partial (or empty) claim set. `loadWorkspace`\n * treats a missing file as an empty catalog because that's the right\n * behavior for `workspace add` (creating one for the first time); a claim\n * consumer needs the opposite default, the same way `--claims` treats a\n * missing lockfile path as a hard error (`loadClaims`,\n * `src/pipeline/salvage.ts`) rather than skipping it. `workspaceClaims`\n * separately guards against an unreadable lock that passed the existence\n * check.\n */\nasync function requireCompleteWorkspaceClaims(workspacePath: string) {\n if (!existsSync(workspacePath)) {\n throw new Error(`Workspace catalog not found: ${workspacePath}`)\n }\n const dir = path.dirname(path.resolve(workspacePath))\n const ws = await loadWorkspace(workspacePath)\n const diagnostics = validateWorkspace(ws, dir)\n const errors = diagnostics.filter((d) => d.level === \"error\")\n if (errors.length) {\n throw new Error(\n `Workspace catalog at ${workspacePath} is not safe to derive a claim set from:\\n` +\n errors.map((d) => ` ${d.id}: ${d.message}`).join(\"\\n\"),\n )\n }\n const claims = await workspaceClaims(ws, dir)\n return { ws, dir, diagnostics, claims }\n}\n\nasync function main() {\n const args = parseArgs(process.argv.slice(2))\n if (args.command === \"help\" || args.command === \"--help\" || args.command === \"-h\") {\n log(HELP)\n return\n }\n\n if (args.command === \"--version\" || args.command === \"-v\") {\n const pkg = JSON.parse(\n await readFile(new URL(\"../package.json\", import.meta.url), \"utf8\"),\n ) as { name: string; version: string }\n log(`${pkg.name} ${pkg.version}`)\n return\n }\n\n if (args.command === \"quality\") {\n if (args.subcommand === \"snapshot\") {\n if (!args.inputs) throw new Error(\"quality snapshot needs --inputs <quality-inputs.json>.\")\n if (!args.out) throw new Error(\"quality snapshot needs --out <pixelkiln.quality.json>.\")\n let raw: unknown\n try {\n raw = JSON.parse(await readFile(path.resolve(args.inputs), \"utf8\"))\n } catch (error) {\n throw new Error(\n `Could not read quality inputs ${path.resolve(args.inputs)}: ` +\n `${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n )\n }\n const inputs = resolveQualityInputs(raw, args.inputs)\n if (path.resolve(args.inputs) === path.resolve(args.out)) {\n throw new Error(\"quality snapshot --out must not overwrite its --inputs file.\")\n }\n const result = await snapshotQualityBaseline(inputs, args.out, { force: args.force })\n if (args.json) {\n log(JSON.stringify({\n version: 1,\n path: result.path,\n changed: result.changed,\n baseline: result.baseline,\n }, null, 2))\n } else {\n log(\n ` ${result.changed ? \"wrote\" : \"unchanged\"} ` +\n `${path.relative(process.cwd(), result.path)} (${result.baseline.cases.length} case(s))`,\n )\n log(` Review the tolerances, commit the baseline, then run quality check in CI.`)\n }\n return\n }\n\n if (!args.from) throw new Error(\"quality check needs --from <pixelkiln.quality.json>.\")\n const report = await checkQualityBaseline(args.from)\n if (args.json) {\n log(JSON.stringify(report, null, 2))\n } else {\n for (const entry of report.cases) {\n log(` ${entry.status === \"pass\" ? \"ok\" : \"ERROR\"} ${entry.id}`)\n for (const violation of entry.violations) log(` ${violation}`)\n for (const warning of entry.warnings) log(` WARN ${warning}`)\n }\n log(\n `\\n ${report.summary.passed}/${report.summary.total} passed` +\n (report.summary.changed ? ` · ${report.summary.changed} image hash(es) changed` : \"\"),\n )\n log(` Metrics catch structural regressions; they do not replace art review.`)\n }\n if (!report.safe) process.exitCode = 1\n return\n }\n\n if (args.command === \"recipe\") {\n if (args.subcommand === \"list\") {\n const recipes = await listBundledRecipes()\n if (args.json) {\n log(JSON.stringify({\n version: 1,\n recipes: recipes.map(({ recipe }) => ({\n id: recipe.id,\n version: recipe.version,\n provider: recipe.provider,\n summary: recipe.summary,\n selector: `${recipe.id}@${recipe.version}`,\n })),\n }, null, 2))\n } else {\n log(` ${recipes.length} bundled recipe(s):`)\n for (const { recipe } of recipes) {\n log(` ${(recipe.id + \"@\" + recipe.version).padEnd(52)} ${recipe.summary}`)\n }\n }\n return\n }\n\n const target = args.target!\n if (args.subcommand === \"inspect\") {\n const { recipe, path: recipePath, bundled } = await resolveRecipe(target)\n if (args.json) {\n log(JSON.stringify({ ...recipe, path: recipePath, bundled }, null, 2))\n } else {\n log(` ${recipe.id}@${recipe.version}`)\n log(` ${recipe.summary}`)\n log(` provider: ${recipe.provider} · style: ${recipe.styleId} · stage: ${recipe.quality.stage}`)\n log(\n ` native target: ${recipe.quality.recommendedNativeSize.min}–` +\n `${recipe.quality.recommendedNativeSize.max}px · palette: ` +\n `${recipe.quality.paletteColors.min}–${recipe.quality.paletteColors.max} colors`,\n )\n if (recipe.workflow) log(` workflow: ${recipe.workflow.path} · ${recipe.workflow.numImages} candidate(s)`)\n for (const model of recipe.models) log(` model: ${model.path} · ${model.license}`)\n log(` source: ${recipePath}${bundled ? \" (bundled)\" : \"\"}`)\n }\n return\n }\n\n if (args.subcommand === \"verify\") {\n const report = await verifyRecipe(target, { modelRoot: args.modelRoot })\n if (args.json) {\n log(JSON.stringify(report, null, 2))\n } else {\n log(` ${report.ok ? \"ok\" : \"ERROR\"} ${report.recipe.id}@${report.recipe.version}`)\n log(` ${report.integrity.status.padEnd(9)} recipe metadata`)\n for (const file of report.files) log(` ${file.status.padEnd(9)} ${file.path}`)\n for (const model of report.models) log(` ${model.status.padEnd(9)} ${model.path}`)\n if (!report.modelRoot && report.models.length) {\n log(` models were not checked; pass --model-root <ComfyUI/models> to verify this workstation`)\n }\n }\n if (!report.ok) process.exitCode = 1\n return\n }\n\n if (args.subcommand === \"install\") {\n const result = await installRecipe(target, { out: args.out, force: args.force })\n if (args.json) {\n log(JSON.stringify({\n version: 1,\n recipe: `${result.recipe.id}@${result.recipe.version}`,\n destination: result.destination,\n changed: result.changed,\n unchanged: result.unchanged,\n styleId: result.styleId,\n style: result.style,\n }, null, 2))\n } else {\n log(` installed ${result.recipe.id}@${result.recipe.version}`)\n log(` ${path.relative(process.cwd(), result.destination) || \".\"}`)\n log(`\\n Add this entry under your manifest's styles object:`)\n log(JSON.stringify({ [result.styleId]: result.style }, null, 2))\n if (result.recipe.models.length) {\n log(`\\n Models are not downloaded automatically. Verify them with:`)\n log(` pixelkiln recipe verify ${path.relative(process.cwd(), result.destination)} --model-root <ComfyUI/models>`)\n }\n }\n return\n }\n }\n\n // Path mode stays manifest-free. Without --from, `refine run/check` falls\n // through to the manifest quality-profile workflow below.\n if (args.command === \"refine\" && (args.from || args.subcommand === \"approve\")) {\n if (!args.from) {\n throw new Error(\n args.subcommand === \"run\"\n ? \"refine needs --from <source.png>.\"\n : `refine ${args.subcommand} needs --from <output.pixelkiln.json>.`,\n )\n }\n\n if (args.subcommand === \"run\") {\n if (!args.out) throw new Error(\"refine needs --out <final.png>.\")\n if (!args.palette.length) {\n throw new Error(\"refine needs an explicit final palette via --palette <#rrggbb,...>.\")\n }\n const result = await refineAsset({\n source: args.from,\n output: args.out,\n palette: args.palette,\n fixerPython: args.fixerPython,\n fixerRevision: args.fixerRevision,\n minGridConfidence: args.minGridConfidence,\n minTransparency: args.minTransparency,\n force: args.force,\n })\n if (args.json) {\n log(JSON.stringify(result, null, 2))\n } else {\n log(\n ` recovered ${result.detection.columns}x${result.detection.rows} native grid ` +\n `(${result.detection.confidence}: ${result.detection.consensus})`,\n )\n log(` enforced ${result.palette.length}-color palette without dithering`)\n log(` wrote ${path.relative(process.cwd(), result.output)}`)\n log(` quality record: ${path.relative(process.cwd(), result.record)}`)\n log(`\\n Automated checks passed. Human 1× review is still required:`)\n log(\n ` pixelkiln refine approve --from ${path.relative(process.cwd(), result.record)} ` +\n `--reviewer \"Your Name\"`,\n )\n }\n return\n }\n\n if (args.subcommand === \"approve\") {\n if (!args.reviewer?.trim()) {\n throw new Error(\"refine approve needs --reviewer <name>.\")\n }\n const pending = await checkQualityRecord(args.from)\n log(\n pending.options.frameSet\n ? ` Inspect all ${pending.options.frameSet.count} ordered frames at 1×, integer zoom, and playback speed.`\n : ` Inspect the final PNG at 1× and integer zoom.`,\n )\n log(` Confirm crisp edges, readable forms, palette separation, alpha, and seams.`)\n if (!(await confirm(\n pending.options.frameSet\n ? \" Record this complete frame set as human-approved?\"\n : \" Record this asset as human-approved?\",\n args.yes,\n ))) {\n log(\" approval not recorded\")\n return\n }\n const result = await approveQualityRecord(args.from, {\n reviewer: args.reviewer,\n note: args.note,\n })\n if (args.json) log(JSON.stringify(result, null, 2))\n else {\n log(\n result.options.frameSet\n ? ` approved ${result.outputs.length} frames in ${path.relative(process.cwd(), result.record)} by ${args.reviewer.trim()}`\n : ` approved ${path.relative(process.cwd(), result.output)} by ${args.reviewer.trim()}`,\n )\n }\n return\n }\n\n const result = await checkQualityRecord(args.from)\n if (args.json) {\n log(JSON.stringify(result, null, 2))\n } else {\n log(` ${result.safe ? \"release-ready\" : \"not release-ready\"}: ${path.relative(process.cwd(), result.output || result.record)}`)\n for (const reason of result.reasons) log(` ${reason}`)\n }\n if (!result.safe) process.exitCode = 1\n return\n }\n\n if (args.command === \"balance\") {\n loadEnvFiles(path.dirname(path.resolve(args.manifest)))\n loadEnvFiles(process.cwd())\n const loaded = await loadManifest(args.manifest)\n const selectedProvider = accountProviderId(loaded.manifest, args.provider, \"balance\")\n const p = createProvider(selectedProvider, \"online\")\n const b = await requireBalance(p)()\n log(` provider: ${p.id}`)\n log(` plan: ${b.plan ?? \"n/a\"}`)\n log(` remaining: ${formatCost(b.unit, b.remaining)}${b.total ? ` of ${b.total}` : \"\"}`)\n return\n }\n\n if (args.command === \"init\") {\n if (!args.from) throw new Error(\"init needs --from <dir> pointing at your existing PNGs.\")\n const root = path.resolve(args.from)\n if (!existsSync(root)) throw new Error(`No directory at ${root}`)\n\n const generator = (args.generator ?? \"map\") as \"1dir\" | \"map\"\n if (generator !== \"1dir\" && generator !== \"map\") {\n throw new Error(`--generator must be \"1dir\" or \"map\", got \"${args.generator}\".`)\n }\n\n const target = path.resolve(args.out ?? \"pixelkiln.manifest.json\")\n const { assets, skipped } = await scanAssets(root, { exclude: args.exclude })\n if (!assets.length) throw new Error(`No PNGs found under ${root}`)\n\n const manifest = buildManifest(\n args.name ?? path.basename(path.dirname(target)),\n args.styles[0] ?? \"base\",\n generator,\n path.relative(path.dirname(target), root) || \".\",\n assets,\n )\n await writeManifestFile(target, manifest)\n\n log(` scanned ${assets.length} PNG(s) under ${path.relative(process.cwd(), root)}`)\n if (skipped.length) log(` skipped ${skipped.length} unreadable file(s)`)\n log(` wrote ${path.relative(process.cwd(), target)}`)\n log(`\\n Prompts are intentionally empty. To recover the real ones from your`)\n log(` PixelLab account instead of inventing them:`)\n log(`\\n pixelkiln adopt --manifest ${path.relative(process.cwd(), target)} --write-prompts\\n`)\n return\n }\n\n if (args.command === \"cache\") {\n const lock = await loadLock(args.lock)\n const report = await inspectCaches(lock, args.lock, { prune: args.prune })\n if (args.json) {\n log(JSON.stringify(report, null, 2))\n } else {\n const size = report.content.bytes < 1024\n ? `${report.content.bytes} B`\n : `${(report.content.bytes / 1024).toFixed(1)} KB`\n log(` content cache: ${report.content.path}`)\n log(\n report.content.exists\n ? ` ${report.content.valid} valid PNG(s), ${report.content.referenced} referenced, ` +\n `${report.content.unreferenced.length} unreferenced — ${size}`\n : \" not created yet\",\n )\n if (report.content.missingReferenced.length) {\n log(` ${report.content.missingReferenced.length} lockfile hash(es) are not locally cached`)\n }\n for (const issue of report.content.invalid.slice(0, 10)) {\n log(` invalid ${issue.name}: ${issue.reason}`)\n }\n if (report.content.invalid.length > 10) {\n log(` … and ${report.content.invalid.length - 10} more invalid entr(ies)`)\n }\n\n log(` remote object-hash cache: ${report.remoteHashes.path}`)\n if (!report.remoteHashes.exists) log(\" not created yet\")\n else if (report.remoteHashes.error) {\n log(` invalid cache: ${report.remoteHashes.error.split(\"\\n\")[0]}`)\n } else {\n log(\n ` ${report.remoteHashes.valid} valid entr(ies), ` +\n `${report.remoteHashes.invalidIds.length} invalid`,\n )\n }\n if (args.prune) {\n log(\n ` pruned ${report.removed.contentFiles} content file(s), ` +\n `${report.removed.remoteHashEntries} invalid remote hash entr(ies)` +\n (report.removed.resetRemoteHashCache ? \"; rebuilt malformed remote cache\" : \"\"),\n )\n }\n log(` ${report.safe ? \"cache integrity is healthy\" : \"cache integrity needs attention\"}`)\n }\n if (args.check && !report.safe) process.exitCode = 1\n return\n }\n\n if (args.command === \"pack\" && args.inputs) {\n // Handled before the manifest-required check below, deliberately: the\n // whole point of `--inputs` is packing sprites that were never part of a\n // pixelkiln manifest at all. Requiring one anyway — as this did until a\n // manual smoke test caught it — defeated the feature for exactly the\n // no-manifest consumer it was built for; heybud-admin's sync script never\n // noticed because it happens to run from a directory that has its own\n // manifest for an unrelated reason.\n if (!args.out) throw new Error(\"--inputs requires --out\")\n if (args.primaryOnly || args.outputRoles.length) {\n throw new Error(\"--primary-only and --output-role require manifest-driven pack\")\n }\n\n const raw = JSON.parse(await readFile(path.resolve(args.inputs), \"utf8\")) as unknown\n const inputs = resolvePackInputs(raw, args.inputs)\n\n const { png, atlas, skipped, sources } = packSprites(inputs, { columns: args.columns })\n const base = path.resolve(args.out.replace(/\\.png$/, \"\"))\n const outputs: ArtifactFile[] = [\n { path: `${base}.png`, data: png },\n { path: `${base}.json`, data: JSON.stringify(atlas, null, 2) + \"\\n\" },\n ]\n await writeManagedArtifactBundle(`${base}.pixelkiln.json`, outputs, {\n kind: \"pack\",\n sources: [await provenanceFile(\"$inputs\", args.inputs), ...sources],\n options: { columns: args.columns ?? null, order: \"id\", style: null },\n }, { force: args.force })\n log(\n ` ${atlas.frames.length} sprite(s), ${atlas.sheet.width}x${atlas.sheet.height} ` +\n `in ${atlas.columns} column(s) — ${(png.length / 1024).toFixed(1)} KB`,\n )\n log(` ${path.relative(process.cwd(), base)}.png + .json + .pixelkiln.json`)\n for (const s of skipped) log(` skipped ${s.id}: ${s.reason}`)\n return\n }\n\n if (args.command === \"workspace\") {\n // No manifest is required in cwd for any of these — a catalog is meant to\n // be operated on from outside any one project.\n const workspacePath = path.resolve(args.workspace ?? \"pixelkiln.workspace.json\")\n const dir = path.dirname(workspacePath)\n\n if (args.subcommand === \"add\") {\n const manifestPath = path.resolve(args.target!)\n const loadedTarget = await loadManifest(manifestPath)\n const lockPath = args.explicitLock\n ? path.resolve(args.explicitLock)\n : path.join(path.dirname(manifestPath), \"pixelkiln.lock.json\")\n\n const ws = await loadWorkspace(workspacePath)\n const id = args.name ?? loadedTarget.manifest.name\n if (ws.projects.some((p) => p.id === id)) {\n throw new Error(\n `Project id \"${id}\" is already registered in ${workspacePath}. Pass --name for a different id.`,\n )\n }\n const lockOwner = ws.projects.find((p) => resolveProject(dir, p).lockPath === lockPath)\n if (lockOwner) {\n throw new Error(`Lockfile ${lockPath} is already registered under project id \"${lockOwner.id}\".`)\n }\n\n const project: WorkspaceProject = {\n id,\n manifest: toPortablePath(dir, manifestPath),\n lock: toPortablePath(dir, lockPath),\n provider: args.provider ?? loadedTarget.manifest.provider,\n ...(args.account ? { account: args.account } : {}),\n }\n await saveWorkspace(workspacePath, { version: 1, projects: [...ws.projects, project] })\n log(` registered \"${id}\" in ${path.relative(process.cwd(), workspacePath)}`)\n log(` manifest: ${project.manifest}`)\n log(` lock: ${project.lock}`)\n if (!existsSync(lockPath)) {\n log(\n ` warning: no lockfile there yet — this project contributes no claims until one is generated`,\n )\n }\n return\n }\n\n if (args.subcommand === \"remove\") {\n const ws = await loadWorkspace(workspacePath)\n const resolvedTarget = path.resolve(args.target!)\n const match = ws.projects.find(\n (p) => p.id === args.target || resolveProject(dir, p).manifestPath === resolvedTarget,\n )\n if (!match) {\n throw new Error(`No registered project matches \"${args.target}\" (checked id and manifest path).`)\n }\n await saveWorkspace(workspacePath, {\n version: 1,\n projects: ws.projects.filter((p) => p !== match),\n })\n log(` removed \"${match.id}\" from ${path.relative(process.cwd(), workspacePath)}`)\n return\n }\n\n if (args.subcommand === \"list\") {\n if (!existsSync(workspacePath)) {\n throw new Error(`Workspace catalog not found: ${workspacePath}`)\n }\n const ws = await loadWorkspace(workspacePath)\n const diagnostics = validateWorkspace(ws, dir)\n if (args.json) {\n log(JSON.stringify({ version: 1, workspace: workspacePath, projects: ws.projects, diagnostics }, null, 2))\n } else if (!ws.projects.length) {\n log(` no projects registered in ${path.relative(process.cwd(), workspacePath)}`)\n } else {\n log(` ${ws.projects.length} project(s) in ${path.relative(process.cwd(), workspacePath)}:`)\n for (const p of ws.projects) {\n log(` ${p.id.padEnd(24)} ${p.manifest.padEnd(40)} (${p.provider}${p.account ? `, ${p.account}` : \"\"})`)\n }\n for (const d of diagnostics) log(` ${d.level === \"error\" ? \"ERROR\" : \"WARN \"} ${d.id.padEnd(18)} ${d.message}`)\n }\n if (args.check && diagnostics.some((d) => d.level === \"error\")) process.exitCode = 1\n return\n }\n\n if (args.subcommand === \"status\") {\n if (!existsSync(workspacePath)) {\n throw new Error(`Workspace catalog not found: ${workspacePath}`)\n }\n const ws = await loadWorkspace(workspacePath)\n const report = await workspaceStatus(ws, dir)\n if (args.json) {\n log(JSON.stringify({ ...report, workspace: workspacePath }, null, 2))\n } else {\n log(` workspace: ${path.relative(process.cwd(), workspacePath)}`)\n for (const p of report.projects) {\n if (p.error) {\n log(`\\n ${p.id} — ERROR: ${p.error}`)\n continue\n }\n log(\n `\\n ${p.id} (${p.providers.join(\" + \")}` +\n `${p.account ? `, ${p.account}` : \"\"})`,\n )\n log(` ${p.entries} lock entries`)\n for (const [state, n] of Object.entries(p.byState)) if (n) log(` ${state.padEnd(12)} ${n}`)\n for (const [unit, amount] of Object.entries(p.spendByUnit).sort()) {\n if (amount) log(` spend: ${formatCost(unit, amount)}`)\n }\n }\n log(`\\n totals:`)\n for (const [state, n] of Object.entries(report.totals.byState)) if (n) log(` ${state.padEnd(12)} ${n}`)\n for (const [unit, amount] of Object.entries(report.totals.spendByUnit).sort()) {\n if (amount) log(` spend: ${formatCost(unit, amount)}`)\n }\n log(` claims: ${report.totals.claims}`)\n for (const d of report.diagnostics) log(` ${d.level === \"error\" ? \"ERROR\" : \"WARN \"} ${d.id.padEnd(18)} ${d.message}`)\n }\n if (args.check && !report.safe) process.exitCode = 1\n return\n }\n\n if (args.subcommand === \"claims\") {\n const { claims, diagnostics } = await requireCompleteWorkspaceClaims(workspacePath)\n if (args.json) {\n log(JSON.stringify({\n version: 1,\n claimed: [...claims.claimed].sort(),\n byProject: claims.byProject,\n lockPaths: claims.lockPaths,\n }, null, 2))\n } else {\n log(` ${claims.claimed.size} claimed id(s) across ${claims.lockPaths.length} lockfile(s):`)\n for (const [id, n] of Object.entries(claims.byProject).sort()) log(` ${id.padEnd(24)} ${n}`)\n for (const d of diagnostics) log(` WARN ${d.id.padEnd(18)} ${d.message}`)\n }\n return\n }\n }\n\n if (!existsSync(path.resolve(args.manifest))) {\n throw new Error(\n `No manifest at ${path.resolve(args.manifest)}. Pass --manifest, or run \\`pixelkiln init --from <dir>\\`.`,\n )\n }\n\n // Load env before any provider is constructed, from the manifest's directory\n // and the cwd — the key belongs with the project, not the tool.\n const manifestDir = path.dirname(path.resolve(args.manifest))\n const envFiles = [...loadEnvFiles(manifestDir)]\n if (path.resolve(process.cwd()) !== manifestDir) envFiles.push(...loadEnvFiles(process.cwd()))\n\n const loaded = await loadManifest(args.manifest)\n let specs = await resolveSpecs(loaded, {\n styles: args.styles,\n assets: args.assets,\n })\n const accountCommands = new Set([\"adopt\", \"salvage\", \"purge\"])\n const selectedAccountProvider = accountCommands.has(args.command)\n ? accountProviderId(loaded.manifest, args.provider, args.command)\n : undefined\n if (args.provider && !selectedAccountProvider) {\n throw new Error(\n \"--provider is only used by balance, adopt, salvage, purge, or workspace add.\",\n )\n }\n if (selectedAccountProvider) {\n specs = specs.filter((spec) => spec.provider === selectedAccountProvider)\n }\n const accountManifest: Manifest = selectedAccountProvider\n ? {\n ...loaded.manifest,\n provider: selectedAccountProvider,\n styles: Object.fromEntries(\n Object.entries(loaded.manifest.styles).filter(\n ([, style]) => (style.provider ?? loaded.manifest.provider) === selectedAccountProvider,\n ),\n ),\n }\n : loaded.manifest\n if (\n selectedAccountProvider &&\n args.styles.some((styleId) => !accountManifest.styles[styleId])\n ) {\n throw new Error(\n `Selected style is not assigned to provider \"${selectedAccountProvider}\".`,\n )\n }\n const lock = await loadLock(args.lock)\n normalizeLockOutputPaths(lock, specs)\n\n if (args.command === \"status\") {\n const byStatus: Record<string, number> = {}\n for (const e of Object.values(lock.entries)) byStatus[e.status] = (byStatus[e.status] ?? 0) + 1\n if (args.json) {\n log(JSON.stringify({ entries: Object.keys(lock.entries).length, byStatus, spendByUnit: spendByUnit(lock) }, null, 2))\n return\n }\n log(` ${Object.keys(lock.entries).length} lock entries`)\n for (const [s, n] of Object.entries(byStatus).sort()) log(` ${s.padEnd(12)} ${n}`)\n const spend = spendByUnit(lock)\n let reported = false\n for (const [unit, amount] of Object.entries(spend).sort()) {\n if (amount) {\n log(` recorded successful submissions: ${formatCost(unit, amount)}`)\n reported = true\n }\n }\n if (!reported) log(` no successful submission cost recorded`)\n return\n }\n\n const plan = await buildPlan(specs, lock, { force: args.force })\n\n if (args.command === \"refine\") {\n const pathOwnedFlags = [\n args.out ? \"--out\" : null,\n args.palette.length ? \"--palette\" : null,\n args.fixerRevision ? \"--fixer-revision\" : null,\n args.minGridConfidence ? \"--min-grid-confidence\" : null,\n args.minTransparency != null ? \"--min-transparency\" : null,\n ].filter(Boolean)\n if (pathOwnedFlags.length) {\n throw new Error(\n `${pathOwnedFlags.join(\", \")} require --from. Manifest mode reads output, palette, ` +\n \"revision, and thresholds from style.quality.\",\n )\n }\n\n if (args.subcommand === \"check\") {\n const inspections = (await Promise.all(\n specs.filter((spec) => spec.quality).map((spec) => inspectQualityProfile(spec, lock)),\n )).filter((item) => item !== null)\n if (!inspections.length) throw new Error(\"No selected style has a quality profile.\")\n const safe = inspections.every((item) => item.state === \"approved\")\n if (args.json) {\n log(JSON.stringify({ version: 1, safe, items: inspections }, null, 2))\n } else {\n for (const item of inspections) {\n log(` ${item.state.padEnd(16)} ${item.key} ${item.reason}`)\n }\n }\n if (!safe) process.exitCode = 1\n return\n }\n\n const result = await refineQualityProfiles(specs, lock, {\n fixerPython: args.fixerPython,\n force: args.force,\n })\n if (args.json) {\n log(JSON.stringify({ version: 1, ...result }, null, 2))\n } else {\n for (const item of result.items) {\n log(` ${item.state.padEnd(16)} ${item.key} ${item.reason}`)\n if (item.state === \"needs-approval\") {\n log(\n ` pixelkiln refine approve --from ${path.relative(process.cwd(), item.record)} ` +\n `--reviewer \"Your Name\"`,\n )\n }\n }\n log(`\\n ${result.processed} refined, ${result.skipped} unchanged, ${result.failed} failed`)\n }\n if (result.failed) process.exitCode = 1\n return\n }\n\n if (args.command === \"doctor\") {\n const selectedStyleIds = args.styles.length\n ? args.styles\n : Object.keys(loaded.manifest.styles)\n const providerIds = [...new Set(\n selectedStyleIds.map((styleId) =>\n loaded.manifest.styles[styleId]?.provider ?? loaded.manifest.provider),\n )].sort()\n const providers = providerIds.map((id) => {\n const factory = providerFactory(id)\n const credentialEnvs = providerCredentialEnvs(factory)\n const missingCredentialEnvs = credentialEnvs.filter((name) => !process.env[name])\n const apiKeyPresent = missingCredentialEnvs.length === 0\n return {\n id,\n apiKeyPresent,\n credentialEnv: factory.credentialEnv,\n missingCredentialEnvs,\n provider: !args.dryRun && apiKeyPresent ? createProvider(id, \"online\") : undefined,\n }\n })\n const report = await doctor(loaded, specs, lock, args.lock, {\n providers,\n offline: args.dryRun,\n })\n if (args.json) {\n log(JSON.stringify(report, null, 2))\n } else {\n for (const check of report.checks) {\n const icon = check.level === \"ok\" ? \"ok\" : check.level === \"warning\" ? \"WARN\" : \"ERROR\"\n log(` ${icon.padEnd(5)} ${check.id.padEnd(14)} ${check.message}`)\n }\n }\n if (!report.ok) process.exitCode = 1\n return\n }\n\n if (args.command === \"plan\") {\n if (args.json) {\n log(JSON.stringify({\n totals: summarize(plan),\n cost: plan.cost,\n costUnit: plan.costUnit,\n candidates: plan.candidates,\n groups: plan.groups.map((group) => ({\n provider: group.provider,\n cost: group.cost,\n costUnit: group.costUnit,\n candidates: group.candidates,\n actionable: group.actionable.map((item) => item.key),\n })),\n actionable: plan.actionable.map((i) => i.key),\n items: plan.items.map(({ key, state, reason, quality, spec }) => ({\n key,\n state,\n reason,\n ...(spec.revision\n ? {\n revision: {\n mode: spec.revision.mode,\n from: spec.revision.sourceAssetId,\n sourceSha256: spec.revision.sourceSha256,\n ...(spec.revision.maskSha256\n ? { maskSha256: spec.revision.maskSha256 }\n : {}),\n ...(spec.revision.strength == null ? {} : { strength: spec.revision.strength }),\n },\n }\n : {}),\n ...(quality ? { quality: { state: quality.state, reason: quality.reason } } : {}),\n })),\n }, null, 2))\n } else {\n printPlan(plan)\n }\n if (\n args.check && plan.items.some(\n (item) => item.state !== \"ok\" || (item.quality && item.quality.state !== \"approved\"),\n )\n ) process.exitCode = 1\n return\n }\n\n if (args.command === \"accept\") {\n // Re-baselines stale entries against the current spec without regenerating.\n // For when the style prose was reworded but the existing art is still wanted.\n let accepted = 0\n for (const item of plan.items) {\n if (item.state !== \"stale\") continue\n const entry = lock.entries[item.key]\n // Accepting new wording is safe; accepting a provider change would\n // relabel old remote work as if the new backend produced it.\n if (!entry || entry.provider !== item.spec.provider || entry.outputs.length === 0) continue\n let intact = true\n for (const output of entry.outputs) {\n const file = resolveOutputPath(output.path, item.spec.root)\n if (!existsSync(file) || (await sha256File(file)) !== output.sha256) {\n intact = false\n break\n }\n }\n if (!intact) continue\n upsertLock(lock, item.key, { specHash: item.spec.specHash })\n accepted++\n }\n await saveLock(args.lock, lock)\n log(` accepted ${accepted} existing file(s) as satisfying the current spec`)\n log(` (their artwork is unchanged; only the recorded spec hash moved)`)\n return\n }\n\n if (args.command === \"prune\") {\n // Removes lock entries no style/asset pair in the manifest resolves to.\n // These accumulate when an asset is renamed or moved between styles: the\n // old entry keeps claiming the output path the new one now owns, which is\n // `doctor`'s lock-outputs error. Until `remove` existed there was no way\n // to clear one short of hand-editing the lockfile.\n //\n // Deliberately resolved from the whole manifest rather than the filtered\n // `specs`: under `--style base` every other style's entries would look\n // undeclared, and prune would delete the lot.\n if (args.styles.length || args.assets.length) {\n throw new Error(\n \"prune compares the lockfile against the entire manifest, so --style \" +\n \"and --only would make it delete the entries they filter out. Run it unfiltered.\",\n )\n }\n const declared = new Set((await resolveSpecs(loaded)).map((s) => lockKey(s.styleId, s.assetId)))\n const orphans = Object.keys(lock.entries).filter((key) => !declared.has(key)).sort()\n if (!orphans.length) {\n log(` every lock entry is declared by the manifest — nothing to prune`)\n return\n }\n\n log(`\n ${orphans.length} lock entr(ies) the manifest no longer declares:`)\n for (const key of orphans.slice(0, 20)) {\n const outputs = lock.entries[key]?.outputs ?? []\n const where = outputs[0]?.path ?? \"no recorded output\"\n log(` ${key.padEnd(44)} ${where}`)\n }\n if (orphans.length > 20) log(` … and ${orphans.length - 20} more`)\n\n if (args.dryRun) {\n log(`\n --dry-run: nothing removed.`)\n return\n }\n log(`\n This drops their provenance from the lockfile. The art on disk is`)\n log(` untouched, and nothing is deleted from your provider account — but`)\n log(` the link from those files back to the objects that made them is gone,`)\n log(` and the objects will read as unclaimed the next time you run salvage.`)\n if (!(await confirm(` Remove ${orphans.length} lock entr(ies)?`, args.yes))) {\n log(` aborted`)\n return\n }\n\n let removed = 0\n for (const key of orphans) if (removeLock(lock, key)) removed++\n await saveLock(args.lock, lock)\n log(` removed ${removed} lock entr(ies); ${Object.keys(lock.entries).length} remain`)\n return\n }\n\n if (args.command === \"pack\") {\n // The --inputs form is handled earlier, before the manifest is required\n // at all — reaching here means the manifest-driven (lockfile) form.\n if (args.primaryOnly && args.outputRoles.length) {\n throw new Error(\"pack accepts either --primary-only or --output-role, not both\")\n }\n const manifestDir = path.dirname(path.resolve(args.manifest))\n const styleIds = args.styles.length ? args.styles : Object.keys(loaded.manifest.styles)\n\n for (const styleId of styleIds) {\n const packagingSpecs = await resolveSpecs(loaded, { styles: [styleId] })\n const qualitySources = await requireApprovedQualitySources(packagingSpecs, lock)\n const { png, atlas, skipped, sources } = packStyle(lock, styleId, manifestDir, {\n columns: args.columns,\n outputRoles: args.outputRoles,\n primaryOnly: args.primaryOnly,\n sourceOverrides: qualitySources,\n })\n\n // Default beside the style's own output tree, so sheets for different\n // styles cannot overwrite each other when --out is omitted.\n const style = loaded.manifest.styles[styleId]\n const base = args.out\n ? path.resolve(args.out.replace(/\\.png$/, \"\"))\n : path.resolve(manifestDir, style!.outDir, `${styleId}-sheet`)\n\n const outputs: ArtifactFile[] = [\n { path: `${base}.png`, data: png },\n { path: `${base}.json`, data: JSON.stringify(atlas, null, 2) + \"\\n\" },\n ]\n const qualityRecords = qualitySources\n ? await Promise.all(\n packagingSpecs.filter((spec) => spec.quality).map((spec) =>\n provenanceFile(\n `$quality/${spec.assetId}`,\n qualityRecordPath(spec.quality!.outFile),\n )),\n )\n : []\n await writeManagedArtifactBundle(`${base}.pixelkiln.json`, outputs, {\n kind: \"pack\",\n sources: [\n await provenanceFile(\"$manifest\", args.manifest),\n await provenanceFile(\"$lock\", args.lock),\n ...qualityRecords,\n ...sources,\n ],\n options: {\n columns: args.columns ?? null,\n order: \"id\",\n outputRoles: [...args.outputRoles].sort(),\n primaryOnly: args.primaryOnly,\n style: styleId,\n },\n }, { force: args.force })\n\n log(\n ` ${styleId} — ${atlas.frames.length} sprite(s), ` +\n `${atlas.sheet.width}x${atlas.sheet.height} in ${atlas.columns} column(s)`,\n )\n log(` ${path.relative(process.cwd(), base)}.png + .json + .pixelkiln.json`)\n for (const s of skipped) log(` skipped ${s.id}: ${s.reason}`)\n }\n return\n }\n\n if (args.command === \"mount\") {\n const manifestDir = path.dirname(path.resolve(args.manifest))\n const styleIds = args.styles.length ? args.styles : Object.keys(loaded.manifest.styles)\n\n for (const styleId of styleIds) {\n const style = loaded.manifest.styles[styleId]\n if (!style?.mount) {\n // Not an error when the caller did not name a style — `mount` with no\n // --style should do the mounted ones and stay quiet about the rest.\n if (args.styles.length) {\n throw new Error(\n `Style \"${styleId}\" has no \\`mount\\` block. Add one, or use \\`pack\\` ` +\n `to let pixelkiln choose the layout.`,\n )\n }\n continue\n }\n\n const cells: Record<string, [number, number]> = {}\n const sources: Record<string, string> = {}\n const outputRoles: Record<string, string> = {}\n for (const [assetId, asset] of Object.entries(loaded.manifest.assets)) {\n if (!asset.cell) continue\n cells[assetId] = asset.cell\n if (asset.source) sources[assetId] = asset.source\n if (asset.outputRole) outputRoles[assetId] = asset.outputRole\n }\n const packagingSpecs = await resolveSpecs(loaded, { styles: [styleId] })\n const qualitySources = await requireApprovedQualitySources(\n packagingSpecs,\n lock,\n new Set(Object.keys(cells)),\n outputRoles,\n )\n if (qualitySources) Object.assign(sources, qualitySources)\n\n const { png, atlas, skipped, overBase, sources: artifactSources } = mountStyle(\n lock,\n styleId,\n manifestDir,\n style.mount,\n cells,\n sources,\n outputRoles,\n )\n\n const out = path.resolve(manifestDir, style.mount.out)\n const metadata = out.replace(/\\.png$/, \"\") + \".json\"\n const companion = out.replace(/\\.png$/, \"\") + \".pixelkiln.json\"\n const outputs: ArtifactFile[] = [\n { path: out, data: png },\n { path: metadata, data: JSON.stringify(atlas, null, 2) + \"\\n\" },\n ]\n const qualityRecords = qualitySources\n ? await Promise.all(\n packagingSpecs\n .filter((spec) => spec.quality && Object.hasOwn(cells, spec.assetId))\n .map((spec) =>\n provenanceFile(\n `$quality/${spec.assetId}`,\n qualityRecordPath(spec.quality!.outFile),\n )),\n )\n : []\n await writeManagedArtifactBundle(companion, outputs, {\n kind: \"mount\",\n sources: [\n await provenanceFile(\"$manifest\", args.manifest),\n await provenanceFile(\"$lock\", args.lock),\n ...qualityRecords,\n ...artifactSources.filter(\n (source) => source.id !== \"$base\" || path.resolve(source.path) !== out,\n ),\n ],\n options: {\n cellHeight: style.mount.cellHeight,\n cellWidth: style.mount.cellWidth,\n cells: Object.entries(cells).sort(([a], [b]) => a.localeCompare(b)),\n style: styleId,\n },\n }, { force: args.force })\n\n log(\n ` ${styleId} — ${atlas.frames.length} cell(s) into ` +\n `${atlas.sheet.width}x${atlas.sheet.height}` +\n (overBase ? ` over ${style.mount.base}` : \" (new sheet)\"),\n )\n log(` ${path.relative(process.cwd(), out)} + atlas/provenance JSON`)\n for (const s of skipped) log(` skipped ${s.id}: ${s.reason}`)\n }\n return\n }\n\n if (args.command === \"audit\") {\n const styleIds = args.styles.length ? args.styles : Object.keys(loaded.manifest.styles)\n const reports: Array<{\n audit: Awaited<ReturnType<typeof auditStyle>>\n evaluation: ReturnType<typeof evaluateAudit>\n }> = []\n for (const styleId of styleIds) {\n const audit = await auditStyle(loaded, specs, styleId, lock)\n const evaluation = evaluateAudit(audit, {\n maxDistance: args.maxDistance,\n minTransparency: args.minTransparency,\n maxColors: args.maxColors,\n sigma: args.sigma,\n })\n reports.push({ audit, evaluation })\n if (args.json) continue\n log(`\\n ${styleId} — ${audit.assets.length} asset(s) measured`)\n log(\n ` reference palette: ${audit.referenceFromStyleImages ? \"style images\" : \"the set's own average\"}` +\n ` ${audit.reference.slice(0, 6).map(hex).join(\" \")}`,\n )\n if (!audit.referenceFromStyleImages) {\n log(` (no styleImages set — this finds outliers but cannot tell you the whole set drifted)`)\n }\n\n const offIds = new Set(evaluation.outliers)\n log(`\\n most off-style first:`)\n for (const asset of audit.assets.slice(0, 12)) {\n const flag = offIds.has(asset.id) ? \" ← outlier\" : \"\"\n log(\n ` ${asset.id.padEnd(28)} dist ${asset.paletteDistance.toFixed(1).padStart(6)}` +\n ` colours ${String(asset.colorCount).padStart(4)}` +\n ` transparent ${(asset.transparency * 100).toFixed(0).padStart(3)}%` +\n ` ${asset.palette.slice(0, 3).map(hex).join(\" \")}${flag}`,\n )\n }\n if (audit.assets.length > 12) log(` … and ${audit.assets.length - 12} more`)\n log(`\\n ${evaluation.outliers.length} outlier(s) beyond ${evaluation.thresholds.sigma} sd`)\n if (audit.missing.length) log(` ${audit.missing.length} asset(s) not on disk`)\n for (const u of audit.unreadable) log(` unreadable ${u}`)\n for (const violation of evaluation.violations) {\n log(` check ${violation.id}: ${violation.reasons.join(\"; \")}`)\n }\n }\n if (args.json) {\n log(JSON.stringify({\n version: 1,\n safe: reports.every((report) => report.evaluation.safe),\n styles: reports.map(({ audit, evaluation }) => ({ ...audit, evaluation })),\n }, null, 2))\n }\n if (args.check && reports.some((report) => !report.evaluation.safe)) process.exitCode = 1\n return\n }\n\n if (args.command === \"export\") {\n const format = args.format ?? \"generic\"\n const manifestDir = path.dirname(path.resolve(args.manifest))\n const selected = specs.filter((spec) => {\n if (spec.generator !== \"tiles\") return false\n if (args.styles.length && !args.styles.includes(spec.styleId)) return false\n if (args.assets.length && !args.assets.includes(spec.assetId)) return false\n return Boolean(lock.entries[lockKey(spec.styleId, spec.assetId)])\n })\n if (!selected.length) {\n throw new Error(\"No downloaded tiles entries match the requested --style/--only filters.\")\n }\n if (args.out && selected.length > 1) {\n throw new Error(\"--out can name one tileset only; add --style/--only to select one asset.\")\n }\n\n for (const spec of selected) {\n const entry = lock.entries[lockKey(spec.styleId, spec.assetId)]!\n const style = loaded.manifest.styles[spec.styleId]!\n const defaultBase = path.resolve(manifestDir, style.outDir, `${spec.assetId}-tileset`)\n const base = args.out\n ? path.resolve(args.out.replace(/\\.(?:png|json|tsj|tres)$/i, \"\"))\n : defaultBase\n const result = exportTileset(entry, spec, {\n format,\n manifestDir,\n imageName: path.basename(`${base}.png`),\n columns: args.columns,\n })\n const outputs: ArtifactFile[] = [\n { path: `${base}.png`, data: result.png },\n { path: `${base}${result.extension}`, data: result.document },\n ]\n await writeManagedArtifactBundle(`${base}.pixelkiln.json`, outputs, {\n kind: \"tileset\",\n sources: [\n await provenanceFile(\"$manifest\", args.manifest),\n await provenanceFile(\"$lock\", args.lock),\n ...result.sources,\n ],\n options: {\n asset: spec.assetId,\n columns: args.columns ?? null,\n format,\n image: path.basename(`${base}.png`),\n providerRules: result.generic.providerRules,\n style: spec.styleId,\n tileType: spec.tileType ?? null,\n },\n }, { force: args.force })\n log(\n ` ${spec.styleId}/${spec.assetId} — ${result.generic.tiles.length} tile(s), ` +\n `${result.generic.sheet.width}x${result.generic.sheet.height} (${format})`,\n )\n log(\n ` ${path.relative(process.cwd(), base)}.png + ` +\n `${path.basename(base)}${result.extension} + .pixelkiln.json`,\n )\n }\n return\n }\n\n const providerMode: ProviderMode =\n args.command === \"restore\" || (args.command === \"fetch\" && !args.tag)\n ? \"downloads\"\n : \"online\"\n const providers = new Map<string, Provider>()\n const providerFor = (id: string) => {\n let resolved = providers.get(id)\n if (!resolved) {\n resolved = createProvider(id, providerMode)\n providers.set(id, resolved)\n }\n return resolved\n }\n if (args.command === \"adopt\") {\n const provider = providerFor(selectedAccountProvider!)\n log(`\\n Reconciling account objects against files already on disk…`)\n const res = await adopt(provider, specs, lock, args.lock, { onProgress: log })\n log(`\\n scanned ${res.scanned} remote object(s), adopted ${res.matched}`)\n if (res.ambiguous.length) {\n log(`\\n ambiguous (${res.ambiguous.length}):`)\n for (const a of res.ambiguous.slice(0, 10)) log(` ${a}`)\n }\n if (res.unmatchedLocal.length) {\n log(`\\n local files with no matching remote object (${res.unmatchedLocal.length}):`)\n for (const u of res.unmatchedLocal.slice(0, 15)) log(` ${u}`)\n }\n if (res.unmatchedRemote.length) {\n log(`\\n remote objects not matched by THIS manifest (${res.unmatchedRemote.length}):`)\n log(formatUnmatchedRemote(res.unmatchedRemote))\n log(\n `\\n One account is shared across projects, so this list mixes discarded\\n` +\n ` candidates with assets belonging to other manifests. Do not bulk-delete\\n` +\n ` it — run adopt from each project first, then \\`pixelkiln salvage\\` to\\n` +\n ` triage what is left over.`,\n )\n }\n if (args.tag) {\n const n = await tagAdopted(provider, specs, lock, { onProgress: log })\n log(`\\n tagged ${n} object(s) upstream`)\n }\n if (args.writePrompts) {\n const { filled, stillEmpty } = await writePromptsBack(path.resolve(args.manifest), lock, {\n onProgress: log,\n provider: provider.id,\n assetIds: specs.map((spec) => spec.assetId),\n })\n log(` recovered ${filled} prompt(s) into ${path.relative(process.cwd(), args.manifest)}`)\n\n // Writing prompts rewrites the manifest, which changes every spec hash.\n // Without re-baselining, an adopt that recovered the true prompts would\n // report all of its own work as stale and offer to regenerate it.\n const reloaded = await loadManifest(args.manifest)\n const rebased = (await resolveSpecs(reloaded, {\n styles: args.styles,\n assets: args.assets,\n })).filter((spec) => spec.provider === provider.id)\n let n = 0\n for (const spec of rebased) {\n const key = lockKey(spec.styleId, spec.assetId)\n if (lock.entries[key]?.status !== \"downloaded\") continue\n upsertLock(lock, key, { specHash: spec.specHash })\n n++\n }\n await saveLock(args.lock, lock)\n log(` re-baselined ${n} entr(ies) against the recovered prompts`)\n if (stillEmpty.length) {\n log(` ${stillEmpty.length} asset(s) still have no prompt (not matched upstream):`)\n for (const id of stillEmpty.slice(0, 10)) log(` ${id}`)\n if (stillEmpty.length > 10) log(` … and ${stillEmpty.length - 10} more`)\n }\n }\n log(`\\n lockfile written: ${args.lock}`)\n return\n }\n\n if (args.command === \"salvage\") {\n const provider = providerFor(selectedAccountProvider!)\n // --json is a machine-readable contract: stdout must be the JSON array\n // and nothing else, so `pixelkiln salvage --dry-run --json | jq` works.\n // Every human-oriented line below goes through `diag` instead of `log` so\n // it lands on stderr — visible in a terminal, invisible to a pipe — and\n // only the final JSON.stringify call ever reaches console.log.\n const jsonMode = args.dryRun && args.json\n const diag = jsonMode ? (msg = \"\") => console.error(msg) : log\n\n // Correctness depends on a complete claim set. Missing a lockfile makes\n // another project's shipped art look unclaimed, so this is stated loudly.\n // This project's own lockfile is optional — salvage is a reasonable first\n // command in a fresh project, which has none yet. Paths given via --claims\n // are required, because a typo there silently widens the orphan set.\n const ownLock = path.resolve(args.lock)\n let workspaceProjects: WorkspaceProject[] = []\n let workspaceDir = \"\"\n if (args.workspace) {\n const workspacePath = path.resolve(args.workspace)\n workspaceDir = path.dirname(workspacePath)\n const complete = await requireCompleteWorkspaceClaims(workspacePath)\n workspaceProjects = complete.ws.projects\n for (const d of complete.diagnostics) diag(` WARN ${d.id}: ${d.message}`)\n }\n const workspaceLockPaths = workspaceProjects.map((p) => resolveProject(workspaceDir, p).lockPath)\n const lockPaths = [\n ...new Set([\n ...workspaceLockPaths,\n ...(existsSync(ownLock) ? [ownLock] : []),\n ...args.claims.map((c) => path.resolve(c)),\n ]),\n ]\n diag(` claim set (${lockPaths.length} lockfile(s)):`)\n for (const p of lockPaths) diag(` ${path.relative(process.cwd(), p)}`)\n if (!args.claims.length && !args.workspace) {\n diag(\n `\\n Only this project's lockfile was consulted. If the account is shared,\\n` +\n ` pass every other project's lockfile via --claims a.json,b.json, or\\n` +\n ` register every project in a workspace catalog and pass --workspace.`,\n )\n } else if (\n args.workspace &&\n !workspaceProjects.some((p) => resolveProject(workspaceDir, p).manifestPath === path.resolve(args.manifest))\n ) {\n diag(\n `\\n This project's manifest is not registered in the workspace catalog. Its own\\n` +\n ` lockfile is still included above, so this run's claim set is complete — but\\n` +\n ` \\`pixelkiln workspace add ${args.manifest}\\` would keep it aggregated too.`,\n )\n }\n\n const claimed = await loadClaims(lockPaths, { provider: provider.id })\n const { orphans, total } = await findOrphans(provider, claimed, { onProgress: diag })\n diag(` ${claimed.size} claimed · ${orphans.length} unclaimed of ${total}`)\n if (!orphans.length) {\n if (jsonMode) log(\"[]\")\n else log(`\\n nothing to triage`)\n return\n }\n\n // Each sibling project's manifest, loaded purely so a single-style\n // manifest — which has no pattern of its own to check against — can still\n // recognise \"this looks like project X's art\" instead of silently\n // claiming everything by default.\n const siblings = await loadSiblingManifests(\n args.manifest,\n workspaceProjects.map((p) => resolveProject(workspaceDir, p).manifestPath),\n args.claims,\n )\n\n // Which style each orphan's prompt was most likely generated from, so a\n // shared account's orphan pool doesn't get triaged as one undifferentiated\n // blob under whichever style happens to be first in the manifest.\n const { matched, unmatched, elsewhere } = groupOrphansByStyle(orphans, accountManifest, siblings)\n const multiStyle = Object.keys(accountManifest.styles).length > 1\n if (multiStyle) {\n diag(`\\n by style (matched against each style's prompt prefix/suffix):`)\n for (const [id, list] of matched) diag(` ${id.padEnd(24)} ${list.length}`)\n if (unmatched.length) diag(` ${\"(no style match)\".padEnd(24)} ${unmatched.length}`)\n }\n if (elsewhere.size) {\n diag(`\\n matched a sibling project's own style instead of this one:`)\n for (const [label, list] of elsewhere) diag(` ${label.padEnd(28)} ${list.length}`)\n diag(` excluded from every session below — not this project's art.`)\n }\n if (unmatched.length) {\n diag(\n `\\n ${unmatched.length} object(s) don't match any known style pattern.\\n` +\n ` If the account is shared, they may belong to a different project — check\\n` +\n ` you've passed every sibling project's lockfile via --claims. They're left\\n` +\n ` out of the sessions below; force them into one style with --style <id>.`,\n )\n }\n\n if (args.dryRun) {\n if (args.json) {\n log(JSON.stringify(orphans, null, 2))\n } else {\n const shown = args.all ? orphans : orphans.slice(0, 30)\n for (const o of shown) {\n log(` ${o.id} ${o.width}x${o.height} ${o.createdAt.slice(0, 10)} ${o.prompt.slice(0, 50)}`)\n }\n if (!args.all && orphans.length > 30) {\n log(` … and ${orphans.length - 30} more (--all for the full list, --json for machine-readable)`)\n }\n }\n diag(`\\n --dry-run: nothing changed.`)\n return\n }\n\n const rebaseline = async () => {\n // Imports append to the manifest, so their spec hashes only exist after\n // it is rewritten. Without this every salvaged asset reports `stale` on\n // the next plan and offers to regenerate art that was just recovered —\n // which would re-pay for all of it.\n const reloaded = await loadManifest(args.manifest)\n const rebased = (await resolveSpecs(reloaded)).filter((spec) => spec.provider === provider.id)\n let n = 0\n for (const spec of rebased) {\n const key = lockKey(spec.styleId, spec.assetId)\n const entry = lock.entries[key]\n if (entry?.status !== \"downloaded\" || entry.specHash !== SALVAGED_SPEC_HASH) continue\n upsertLock(lock, key, { specHash: spec.specHash })\n n++\n }\n await saveLock(args.lock, lock)\n if (n) log(` baselined ${n} imported asset(s) against the manifest`)\n }\n\n const runOne = async (styleId: string, list: typeof orphans) => {\n const style = accountManifest.styles[styleId]!\n const res = await runSalvage(\n provider,\n list,\n {\n manifestPath: loaded.path,\n manifest: accountManifest,\n styleId,\n importDir: path.resolve(loaded.root, style.outDir),\n lock,\n lockPath: args.lock,\n },\n { port: args.port, open: !args.noOpen, onProgress: log },\n )\n log(\n ` imported ${res.imported} · kept ${res.kept} · tagged-discard ${res.discarded}` +\n (res.failed ? ` · failed ${res.failed}` : \"\"),\n )\n if (res.imported > 0) await rebaseline()\n return res\n }\n\n // An explicit --style bypasses grouping entirely and runs one session\n // across every unclaimed object, same as before grouping existed — for\n // when the auto-match misses a real candidate and a human already knows\n // where it belongs.\n if (args.styles.length) {\n const res = await runOne(args.styles[0]!, orphans)\n if (res.discarded) {\n log(`\\n Nothing was deleted. To actually remove the discarded objects:`)\n log(` pixelkiln purge\\n`)\n }\n return\n }\n\n if (!matched.size) {\n log(`\\n nothing matched a known style — nothing to triage`)\n return\n }\n\n log(`\\n ${matched.size} session(s), one style at a time:`)\n let totalDiscarded = 0\n for (const [styleId, list] of matched) {\n log(`\\n — ${styleId} (${list.length}) —`)\n const res = await runOne(styleId, list)\n totalDiscarded += res.discarded\n }\n if (totalDiscarded) {\n log(`\\n Nothing was deleted. To actually remove the discarded objects:`)\n log(` pixelkiln purge\\n`)\n }\n return\n }\n\n if (args.command === \"purge\") {\n const provider = providerFor(selectedAccountProvider!)\n const doomed: { id: string; prompt: string }[] = []\n for await (const obj of requireList(provider)()) {\n if (obj.tags.includes(\"pixelkiln:discard\")) {\n doomed.push({ id: obj.id, prompt: obj.prompt })\n }\n }\n if (!doomed.length) {\n log(` nothing tagged pixelkiln:discard — run \\`pixelkiln salvage\\` first`)\n return\n }\n log(`\\n ${doomed.length} object(s) tagged for discard:`)\n for (const d of doomed.slice(0, 20)) log(` ${d.id} ${d.prompt.slice(0, 60)}`)\n if (doomed.length > 20) log(` … and ${doomed.length - 20} more`)\n\n if (args.dryRun) {\n log(`\\n --dry-run: nothing deleted.`)\n return\n }\n log(`\\n This permanently deletes them from your ${provider.id} account.`)\n log(` Any local files already downloaded are untouched, but the objects`)\n log(` and their URLs are gone and cannot be re-downloaded.`)\n if (!(await confirm(` Delete ${doomed.length} object(s)?`, args.yes))) {\n log(` aborted`)\n return\n }\n\n let deleted = 0\n let failed = 0\n for (const d of doomed) {\n try {\n await requireDelete(provider)(d.id)\n deleted++\n } catch (err) {\n failed++\n log(` delete failed ${d.id}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n log(`\\n deleted ${deleted}${failed ? `, failed ${failed}` : \"\"}`)\n return\n }\n\n if (args.command === \"tag\") {\n let tagged = 0\n for (const [providerId, providerSpecsForRun] of specsByRecordedProvider(specs, lock)) {\n tagged += await pushTags(providerFor(providerId), providerSpecsForRun, lock, {\n onProgress: log,\n })\n }\n log(` tagged ${tagged} object(s)`)\n return\n }\n\n if (args.command === \"submit\" || args.command === \"gen\") {\n printPlan(plan)\n if (args.dryRun) {\n log(`\\n --dry-run: stopping before any spend.`)\n return\n }\n if (plan.actionable.length) {\n const budgets = budgetsForPlan(plan, args)\n const balances = new Map<string, BalanceInfo | null>()\n // Validate every ceiling and available balance before the first provider\n // can spend. A later group must never reveal that the whole run was\n // unaffordable only after an earlier group already submitted work.\n for (const group of plan.groups) {\n const groupProvider = providerFor(group.provider)\n const balance = groupProvider.balance ? await groupProvider.balance() : null\n balances.set(group.provider, balance)\n if (balance) {\n log(\n `\\n balance: ${formatCost(balance.unit, balance.remaining)} remaining ` +\n `(${group.provider})`,\n )\n if (balance.unit !== group.costUnit) {\n throw new Error(\n `Provider ${group.provider} estimate unit ${group.costUnit} does not match ` +\n `balance unit ${balance.unit}.`,\n )\n }\n if (balance.unit !== \"free\" && group.cost > balance.remaining) {\n throw new Error(\n `${group.provider} needs ${formatCost(balance.unit, group.cost)} but only ` +\n `${formatCost(balance.unit, balance.remaining)} remain.`,\n )\n }\n } else {\n log(\n `\\n ${group.provider} does not expose an account balance; ` +\n `enforcing its run budget`,\n )\n }\n const ceiling = budgets.get(group.provider)\n if (ceiling !== undefined && group.cost > ceiling) {\n throw new Error(\n `${group.provider} would spend ${formatCost(group.costUnit, group.cost)} but its ` +\n `budget is ${formatCost(group.costUnit, ceiling)}.`,\n )\n }\n }\n const spendSummary = plan.groups\n .map((group) => `${group.provider} ${formatCost(group.costUnit, group.cost)}`)\n .join(\"; \")\n const ok = await confirm(\n ` Spend ${spendSummary} on ${plan.actionable.length} asset(s)?`,\n args.yes,\n )\n if (!ok) {\n log(` aborted`)\n return\n }\n log(`\\n submitting…`)\n for (const group of plan.groups) {\n const groupProvider = providerFor(group.provider)\n const res = await submit(groupProvider, loaded, group.actionable, lock, args.lock, {\n budget: budgets.get(group.provider),\n onProgress: log,\n })\n log(\n `\\n ${group.provider}: submitted ${res.submitted}, failed ${res.failed}, ` +\n `estimated ${formatCost(res.unit, res.spent)}`,\n )\n try {\n const before = balances.get(group.provider)\n const after = before && groupProvider.balance ? await groupProvider.balance() : null\n if (!before || !after) throw new Error(\"balance reporting is unsupported\")\n const measured = measureBalanceChange(before, after)\n if (measured) {\n const movement = measured.credited\n ? `${formatCost(measured.unit, measured.credited)} credited`\n : `${formatCost(measured.unit, measured.spent)} consumed`\n log(` ${group.provider} balance change: ${movement}`)\n } else {\n log(` ${group.provider} changed balance units; no delta reported`)\n }\n } catch (err) {\n log(\n ` ${group.provider} balance recheck unavailable: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n if (res.failed) process.exitCode = 1\n }\n }\n if (args.command === \"submit\") return\n }\n\n if (args.command === \"poll\" || args.command === \"gen\") {\n log(`\\n polling…`)\n const total = { completed: 0, review: 0, failed: 0, stillRunning: 0 }\n for (const [providerId, providerSpecsForRun] of specsByRecordedProvider(specs, lock)) {\n const res = await poll(providerFor(providerId), lock, args.lock, {\n onProgress: log,\n specs: providerSpecsForRun,\n })\n total.completed += res.completed\n total.review += res.review\n total.failed += res.failed\n total.stillRunning += res.stillRunning\n }\n log(\n `\\n ${total.completed} ready · ${total.review} awaiting selection · ` +\n `${total.failed} failed`,\n )\n if (total.failed || total.stillRunning) process.exitCode = 1\n if (args.command === \"poll\") {\n printResumeActions(specs, lock)\n return\n }\n }\n\n if (args.command === \"pick\" || args.command === \"gen\") {\n const total = { selected: 0, skipped: 0 }\n for (const [providerId, providerSpecsForRun] of specsByRecordedProvider(specs, lock)) {\n const res = await runPicker(providerFor(providerId), lock, args.lock, {\n port: args.port,\n open: !args.noOpen,\n onProgress: log,\n onReady: announceReviewReady,\n keys: providerSpecsForRun.map((spec) => lockKey(spec.styleId, spec.assetId)),\n specs: providerSpecsForRun,\n })\n total.selected += res.selected\n total.skipped += res.skipped\n }\n if (total.selected === 0 && total.skipped === 0) {\n log(` nothing awaiting selection`)\n } else {\n log(`\\n selected ${total.selected}, left in review ${total.skipped}`)\n }\n if (args.command === \"gen\" && total.skipped) process.exitCode = 1\n if (args.command === \"pick\") {\n printResumeActions(specs, lock)\n return\n }\n }\n\n if (args.command === \"fetch\" || args.command === \"restore\" || args.command === \"gen\") {\n log(`\\n downloading…`)\n const total = { downloaded: 0, skipped: 0, failed: 0, tagged: 0 }\n for (const [providerId, providerSpecsForRun] of specsByRecordedProvider(specs, lock)) {\n const groupProvider = providerFor(providerId)\n const res = await fetchAssets(groupProvider, providerSpecsForRun, lock, args.lock, {\n onProgress: log,\n repair: args.command === \"restore\",\n force: args.force,\n })\n total.downloaded += res.downloaded\n total.skipped += res.skipped\n total.failed += res.failed\n if (args.tag) {\n total.tagged += await pushTags(groupProvider, providerSpecsForRun, lock, {\n onProgress: log,\n })\n }\n }\n log(\n `\\n downloaded ${total.downloaded}, skipped ${total.skipped}, failed ${total.failed}`,\n )\n if (total.failed) process.exitCode = 1\n if (args.tag) log(` tagged ${total.tagged} object(s) upstream`)\n await saveLock(args.lock, lock)\n log(` lockfile written: ${args.lock}`)\n const resumeActionCount = printResumeActions(specs, lock)\n if (args.command === \"gen\" && specs.some((spec) => spec.quality) && !total.failed) {\n const quality = (await Promise.all(\n specs.filter((spec) => spec.quality).map((spec) => inspectQualityProfile(spec, lock)),\n )).filter((item) => item !== null)\n const blocked = quality.filter((item) => item.state === \"blocked\")\n if (blocked.length) {\n log(\n `\\n ${blocked.length} quality source${blocked.length === 1 ? \" is\" : \"s are\"} not ready; ` +\n (resumeActionCount\n ? \"finish the resume steps above before refining.\"\n : \"run `pixelkiln plan` for the blocking reason before refining.\"),\n )\n } else {\n log(`\\n Raw provider output is ready. Run \\`pixelkiln refine\\` to build the configured quality output.`)\n log(` Packaging stays blocked until each refined PNG has a current human approval.`)\n }\n }\n return\n }\n\n log(HELP)\n}\n\nmain().catch((err) => {\n console.error(`\\n error: ${err instanceof Error ? err.message : String(err)}\\n`)\n process.exit(1)\n})\n","import { readFileSync, existsSync } from \"node:fs\"\nimport path from \"node:path\"\n\n/**\n * Loads `.env.local` then `.env` from a directory into `process.env`.\n *\n * Existing environment variables always win, so an explicit export or a CI\n * secret is never silently overridden by a checked-out file.\n *\n * This exists because the \"PIXELLAB_API_KEY is not set\" error told people to\n * put the key in a .env file next to the manifest — advice the code did not\n * actually implement, so following it correctly still failed.\n */\nexport function loadEnvFiles(dir: string): string[] {\n const loaded: string[] = []\n // .env.local last-writer-wins over .env, matching the Next.js convention\n // these projects already follow — so it is read first and .env cannot\n // clobber it, given the never-override rule below.\n for (const name of [\".env.local\", \".env\"]) {\n const file = path.join(dir, name)\n if (!existsSync(file)) continue\n try {\n applyEnv(readFileSync(file, \"utf8\"))\n loaded.push(file)\n } catch {\n // An unreadable env file is not worth failing the command over; the\n // missing-key error downstream is clearer than a parse trace.\n }\n }\n return loaded\n}\n\nfunction applyEnv(contents: string): void {\n for (const rawLine of contents.split(\"\\n\")) {\n const line = rawLine.trim()\n if (!line || line.startsWith(\"#\")) continue\n\n const eq = line.indexOf(\"=\")\n if (eq <= 0) continue\n\n const key = line.slice(0, eq).replace(/^export\\s+/, \"\").trim()\n if (!key || key in process.env) continue\n\n let value = line.slice(eq + 1).trim()\n // Strip one matching pair of surrounding quotes, if present.\n const quote = value[0]\n if ((quote === '\"' || quote === \"'\") && value.endsWith(quote) && value.length >= 2) {\n value = value.slice(1, -1)\n }\n process.env[key] = value\n }\n}\n","import type { Generator, ResolvedSpec, ResolvedStyleImage, RevisionMode } from \"./types.ts\"\nimport type { MediaType } from \"./media.ts\"\n\n/**\n * Human-readable unit attached to every estimate and recorded charge.\n * Built-ins use generations, USD, free, and compute units. Adapters may report\n * another non-convertible unit without pretending it is dollars.\n */\nexport type CostUnit = \"generations\" | \"usd\" | \"free\" | (string & {})\n\nexport interface CostEstimate {\n unit: CostUnit\n amount: number\n /**\n * How many candidates one call returns. This is a provider property, not a\n * universal truth — PixelLab's `1dir` returns up to 64 for a single fixed\n * price, whereas a per-image provider returns one and charges N times for N.\n * The \"generate small, pick from many\" strategy only pays off where this is\n * greater than 1 at no extra cost.\n */\n candidates: number\n}\n\n/** Runtime guard for third-party adapters before estimates influence a budget. */\nexport function validateCostEstimate(providerId: string, value: unknown): CostEstimate {\n if (!value || typeof value !== \"object\") {\n throw new Error(`Provider \"${providerId}\" returned an invalid cost estimate`)\n }\n const estimate = value as Partial<CostEstimate>\n if (typeof estimate.unit !== \"string\" || !estimate.unit.trim()) {\n throw new Error(`Provider \"${providerId}\" returned an invalid cost unit`)\n }\n if (!Number.isFinite(estimate.amount) || estimate.amount! < 0) {\n throw new Error(`Provider \"${providerId}\" returned an invalid cost amount`)\n }\n if (estimate.unit === \"free\" && estimate.amount !== 0) {\n throw new Error(`Provider \"${providerId}\" returned a nonzero amount with the free cost unit`)\n }\n if (!Number.isInteger(estimate.candidates) || estimate.candidates! < 1) {\n throw new Error(`Provider \"${providerId}\" returned an invalid candidate count`)\n }\n return estimate as CostEstimate\n}\n\nexport interface OutputSource {\n url: string\n /** Stable semantic/index role used in filenames and lockfile outputs. */\n role?: string\n /** Durable byte format. Omission preserves legacy PNG behavior. */\n mediaType?: MediaType\n}\n\nexport type ProviderInputScalar = string | number | boolean\nexport type ProviderInputValue = ProviderInputScalar | ProviderInputScalar[]\n\nexport interface PollContext {\n /** Distinguishes structural tile sets from independent tile candidates. */\n tileFeature?: string\n /** Current resolved intent, needed when output media depends on provider options. */\n spec?: ResolvedSpec\n}\n\n/** Provider-owned, JSON-serializable details needed by downstream exporters. */\nexport type ProviderMetadata = Record<string, unknown>\n\nexport interface ProviderSubmission {\n jobId: string\n /** Authoritative provider details known at submission, such as a live quote. */\n metadata?: ProviderMetadata\n}\n\n/** Durable progress recorded after a provider accepts one part of a submission. */\nexport interface SubmissionCheckpoint extends ProviderSubmission {\n /** False while more external requests are required for the same asset. */\n complete: boolean\n}\n\n/** Optional state for providers that submit one asset through several requests. */\nexport interface SubmitContext {\n /** Persist accepted remote identity before the provider starts its next request. */\n checkpoint(value: SubmissionCheckpoint): Promise<void>\n /** Incomplete checkpoint from an earlier run of this exact resolved spec. */\n previousJobId?: string\n /** Provider-owned details saved with the previous checkpoint. */\n previousMetadata?: ProviderMetadata\n}\n\nexport interface CandidateSelection {\n objectId: string\n sourceUrl: string | null\n /** Details known only after choosing an output, such as its durable asset id. */\n metadata?: ProviderMetadata\n}\n\nexport interface ProviderOptionContext {\n /** Absolute directory containing the manifest. */\n root: string\n styleId: string\n}\n\nexport interface ProviderInputContext extends ProviderOptionContext {\n assetId: string\n generator: Generator\n /** The already-resolved options for this style. */\n providerOptions: Record<string, unknown>\n}\n\nexport interface ResolvedProviderOptions {\n /** Runtime options passed to estimate, validate, and submit. */\n options: Record<string, unknown>\n /** Stable JSON value hashed instead of runtime-only data when present. */\n identity?: unknown\n}\n\nexport interface ResolvedProviderInputs {\n /** Runtime values passed to validate and submit. */\n inputs: Record<string, unknown>\n /** Stable JSON value hashed instead of runtime-only paths when present. */\n identity?: unknown\n}\n\n/** Terminal and non-terminal states a queued job can be observed in. */\nexport type JobState =\n | { status: \"processing\"; progressPercent?: number | null; etaSeconds?: number | null }\n | { status: \"review\"; candidateUrls: string[]; metadata?: ProviderMetadata }\n | {\n status: \"review-set\"\n objectId: string\n frameUrls: string[]\n sources: OutputSource[]\n fps: number\n metadata?: ProviderMetadata\n }\n | {\n status: \"ready\"\n objectId: string\n /** Kept for compatibility with single-output provider implementations. */\n sourceUrl: string | null\n /** Present for structural multi-output results. */\n sources?: OutputSource[]\n /** Preserved under the provider's namespace in the lockfile. */\n metadata?: ProviderMetadata\n }\n | { status: \"failed\"; error: string }\n\n/** A previously generated asset as the provider reports it. */\nexport interface RemoteAsset {\n id: string\n prompt: string\n width: number\n height: number\n createdAt: string\n previewUrl: string | null\n tags: string[]\n status: string\n}\n\nexport interface BalanceInfo {\n unit: CostUnit\n remaining: number\n total?: number\n plan?: string\n}\n\nexport interface BalanceChange {\n unit: CostUnit\n before: number\n after: number\n /** Provider-reported quota/currency consumed between the two readings. */\n spent: number\n /** Quota/currency added between readings, e.g. a refill during the run. */\n credited: number\n}\n\n/** Compare two provider readings without ever combining incompatible units. */\nexport function measureBalanceChange(\n before: BalanceInfo,\n after: BalanceInfo,\n): BalanceChange | null {\n if (\n before.unit !== after.unit ||\n !Number.isFinite(before.remaining) ||\n !Number.isFinite(after.remaining)\n ) return null\n const delta = before.remaining - after.remaining\n return {\n unit: before.unit,\n before: before.remaining,\n after: after.remaining,\n spent: Math.max(0, delta),\n credited: Math.max(0, -delta),\n }\n}\n\n/**\n * Submission constraints a backend enforces upstream, in its own units —\n * `submit` has no business knowing these numbers itself.\n */\nexport interface RateLimit {\n /** Minimum time between successive submissions, global across the account. */\n spacingMs: number\n /** Background jobs allowed in flight at once. */\n maxInFlight: number\n}\n\n/**\n * Used when a provider doesn't declare `rateLimit()` — conservative enough\n * not to be a real constraint for a provider that has none of its own, and\n * overridable per run via `submit`'s own options regardless.\n */\nexport const DEFAULT_RATE_LIMIT: RateLimit = { spacingMs: 2500, maxInFlight: 8 }\n\n/**\n * A backend that turns a resolved spec into durable image or animation bytes.\n *\n * Everything above this interface — the manifest, the lockfile, plan diffing,\n * salvage, the contact sheets — is provider-agnostic. Everything that knows a\n * URL shape or an auth header lives below it.\n *\n * The optional members are genuinely optional capabilities rather than\n * convenience: a provider with no queryable asset list cannot support `adopt`\n * or `salvage`, and the CLI reports that rather than failing obscurely.\n */\nexport interface Provider {\n readonly id: string\n\n /**\n * Resolve provider-owned local files before spec hashing. This must remain\n * offline and return JSON-serializable data. It lets adapters hash file\n * content rather than a machine-specific path.\n */\n resolveOptions?(\n options: Record<string, unknown>,\n context: ProviderOptionContext,\n ): Promise<ResolvedProviderOptions>\n\n /**\n * Resolve adapter-owned per-asset values before spec hashing. This is where\n * local control images become content hashes rather than machine paths.\n */\n resolveInputs?(\n inputs: Record<string, ProviderInputValue>,\n context: ProviderInputContext,\n ): Promise<ResolvedProviderInputs>\n\n /** False for a generator this backend cannot express (e.g. non-square). */\n supports(generator: Generator): boolean\n\n /** True only when the adapter can bind and submit this controlled edit mode. */\n supportsRevision?(mode: RevisionMode): boolean\n\n /** Never performs I/O — `plan` must stay free and offline. */\n estimate(spec: ResolvedSpec): CostEstimate\n\n /** Provider-specific, offline validation after references resolve. */\n validate?(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): void\n\n /** This backend's own submission constraints. Falls back to\n * `DEFAULT_RATE_LIMIT` when absent — see that constant's doc. */\n rateLimit?(): RateLimit\n\n submit(\n spec: ResolvedSpec,\n styleImages: ResolvedStyleImage[],\n context?: SubmitContext,\n ): Promise<ProviderSubmission>\n\n poll(jobId: string, generator: Generator, context?: PollContext): Promise<JobState>\n\n /**\n * Promote one candidate from a review-status job to a standalone asset.\n * Only meaningful where `estimate().candidates > 1`.\n *\n * `generator` is passed because \"promote\" is not universal: PixelLab's\n * frame-based generators create a new account object, while a tiles\n * variation is already a finished image and there is nothing to promote.\n * A provider that treats every candidate alike can ignore it.\n */\n selectCandidate?(\n jobId: string,\n index: number,\n commonTag?: string,\n generator?: Generator,\n ): Promise<CandidateSelection>\n\n /** Storage URLs are usually public; implementations should not send auth. */\n download(url: string): Promise<Buffer>\n\n /** Query an authoritative account balance when the service exposes one. */\n balance?(): Promise<BalanceInfo>\n\n /** Read-only connectivity probe for providers without a balance endpoint. */\n checkConnection?(): Promise<void>\n\n /** Free-form labels on the remote asset. Absent if unsupported. */\n setTags?(objectId: string, tags: string[]): Promise<void>\n\n /** Walk every asset on the account. Required by `adopt` and `salvage`. */\n list?(): AsyncGenerator<RemoteAsset>\n\n /** Irreversible. Only reached via `purge`, behind explicit confirmation. */\n delete?(assetId: string): Promise<void>\n}\n\nexport class UnsupportedCapabilityError extends Error {\n constructor(providerId: string, capability: string) {\n super(\n `Provider \"${providerId}\" does not support ${capability}. ` +\n `That command is unavailable with this backend.`,\n )\n this.name = \"UnsupportedCapabilityError\"\n }\n}\n\n/** Narrowing helpers so call sites fail with a clear message, not `undefined is not a function`. */\nexport function requireList(provider: Provider): NonNullable<Provider[\"list\"]> {\n if (!provider.list) throw new UnsupportedCapabilityError(provider.id, \"listing remote assets\")\n return provider.list.bind(provider)\n}\n\nexport function requireDelete(provider: Provider): NonNullable<Provider[\"delete\"]> {\n if (!provider.delete) throw new UnsupportedCapabilityError(provider.id, \"deleting remote assets\")\n return provider.delete.bind(provider)\n}\n\nexport function requireSelectCandidate(\n provider: Provider,\n): NonNullable<Provider[\"selectCandidate\"]> {\n if (!provider.selectCandidate) {\n throw new UnsupportedCapabilityError(provider.id, \"candidate selection\")\n }\n return provider.selectCandidate.bind(provider)\n}\n\nexport function requireBalance(provider: Provider): NonNullable<Provider[\"balance\"]> {\n if (!provider.balance) throw new UnsupportedCapabilityError(provider.id, \"account balance\")\n return provider.balance.bind(provider)\n}\n\nexport function formatCost(unit: CostUnit, amount: number): string {\n if (unit === \"free\") return \"free\"\n if (unit === \"usd\") return `$${amount.toFixed(2)}`\n if (unit === \"generations\") return `${amount} generation${amount === 1 ? \"\" : \"s\"}`\n return `${amount} ${unit}`\n}\n","import { randomUUID } from \"node:crypto\"\nimport { readFile } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { sha256 } from \"../hash.ts\"\nimport { MediaType } from \"../media.ts\"\nimport type {\n CostEstimate,\n JobState,\n PollContext,\n Provider,\n ProviderInputContext,\n ProviderInputValue,\n ProviderOptionContext,\n ProviderSubmission,\n RateLimit,\n ResolvedProviderInputs,\n ResolvedProviderOptions,\n SubmitContext,\n} from \"../provider.ts\"\nimport type { Generator, ResolvedSpec, ResolvedStyleImage, RevisionMode } from \"../types.ts\"\n\nconst DEFAULT_BASE_URL = \"http://127.0.0.1:8188\"\n\ntype JsonObject = Record<string, unknown>\ntype ComfyWorkflow = Record<string, { class_type: string; inputs: JsonObject; [key: string]: unknown }>\n\nexport interface ComfyUIBinding {\n nodeId: string\n input: string\n}\n\nexport interface ComfyUIBindings {\n [name: string]: ComfyUIBinding | undefined\n prompt: ComfyUIBinding\n width?: ComfyUIBinding\n height?: ComfyUIBinding\n batchSize?: ComfyUIBinding\n seed?: ComfyUIBinding\n /** LoadImage-compatible input populated from a hashed revision parent. */\n sourceImage?: ComfyUIBinding\n /** LoadImage-compatible input populated from an inpaint mask. */\n maskImage?: ComfyUIBinding\n /** Sampler denoise/edit-strength input. */\n strength?: ComfyUIBinding\n}\n\nexport interface ComfyUIImageInput {\n kind: \"image\"\n /** Absolute local path used only at submission time. */\n path: string\n sha256: string\n format: \"png\" | \"jpeg\"\n}\n\nexport interface ComfyUIFramesOptions {\n /** Project-defined binding whose asset value is an ordered scalar array. */\n vary: string\n /** Optional deterministic seed increment between frames. Defaults to 0. */\n seedStep?: number\n}\n\n/** Options stored under `providerOptions.comfyui` in a manifest style. */\nexport interface ComfyUIOptions {\n /** ComfyUI API-format workflow JSON, relative to the manifest. */\n workflowFile: string\n /** Node whose history output contains the final `images` array. */\n outputNodeId: string\n /** Expected final images from the output node. */\n numImages?: number\n /** Ordered still-frame generation using one varying custom binding. */\n frames?: ComfyUIFramesOptions\n /** Exact workflow inputs PixelKiln is allowed to replace. */\n bindings: ComfyUIBindings\n}\n\ninterface ResolvedComfyUIOptions extends ComfyUIOptions {\n numImages: number\n frames?: { vary: string; seedStep: number }\n workflow: ComfyWorkflow\n workflowSha256: string\n}\n\ninterface ComfyImage {\n filename: string\n subfolder: string\n type: \"output\"\n}\n\ninterface FrameSetJob {\n expectedCount: number\n outputNodeId: string\n promptIds: string[]\n}\n\nconst BUILTIN_BINDINGS = new Set([\n \"prompt\", \"width\", \"height\", \"batchSize\", \"seed\", \"sourceImage\", \"maskImage\", \"strength\",\n])\n\nclass ComfyUIClient {\n readonly baseUrl: string\n\n constructor(\n baseUrl = process.env.COMFYUI_BASE_URL ?? DEFAULT_BASE_URL,\n private readonly request: typeof fetch = fetch,\n ) {\n this.baseUrl = normalizeBaseUrl(baseUrl)\n }\n\n async checkConnection(): Promise<void> {\n const value = await this.json(\"system_stats\")\n if (!isObject(value)) throw new Error(\"ComfyUI returned invalid system stats\")\n }\n\n async submit(workflow: ComfyWorkflow): Promise<string> {\n const value = await this.json(\"prompt\", {\n method: \"POST\",\n body: JSON.stringify({ prompt: workflow, client_id: randomUUID() }),\n })\n if (!isObject(value)) throw new Error(\"ComfyUI returned an invalid queue response\")\n const promptId = value.prompt_id\n if (typeof promptId !== \"string\" || !promptId) {\n const nodes = isObject(value.node_errors) ? Object.keys(value.node_errors) : []\n throw new Error(\n \"ComfyUI did not return a prompt id\" +\n (nodes.length ? `; invalid workflow node(s): ${nodes.slice(0, 8).join(\", \")}` : \"\"),\n )\n }\n return promptId\n }\n\n async uploadImage(\n bytes: Buffer,\n sha256: string,\n format: \"png\" | \"jpeg\",\n ): Promise<string> {\n const extension = format === \"jpeg\" ? \"jpg\" : \"png\"\n const form = new FormData()\n form.append(\n \"image\",\n new Blob([new Uint8Array(bytes)], { type: format === \"jpeg\" ? \"image/jpeg\" : \"image/png\" }),\n `${sha256}.${extension}`,\n )\n form.append(\"type\", \"input\")\n form.append(\"subfolder\", \"pixelkiln\")\n form.append(\"overwrite\", \"true\")\n const url = this.endpoint(\"upload/image\")\n const response = await this.request(url, { method: \"POST\", body: form })\n const text = await response.text()\n let value: unknown = null\n try {\n value = text ? JSON.parse(text) : null\n } catch {\n value = null\n }\n if (!response.ok) {\n throw new Error(\n `ComfyUI image upload failed (${response.status})` +\n (apiError(value) ? `: ${apiError(value)}` : \"\"),\n )\n }\n if (!isObject(value) || typeof value.name !== \"string\" || !value.name) {\n throw new Error(\"ComfyUI image upload returned an invalid response\")\n }\n const subfolder = typeof value.subfolder === \"string\" ? value.subfolder : \"\"\n return subfolder ? `${subfolder.replace(/\\/+$/, \"\")}/${value.name}` : value.name\n }\n\n async history(promptId: string): Promise<unknown> {\n return this.json(`history/${encodeURIComponent(promptId)}`)\n }\n\n viewUrl(image: ComfyImage): string {\n const url = this.endpoint(\"view\")\n url.searchParams.set(\"filename\", image.filename)\n url.searchParams.set(\"subfolder\", image.subfolder)\n url.searchParams.set(\"type\", image.type)\n return url.toString()\n }\n\n async download(source: string): Promise<Buffer> {\n let target = source\n if (source.startsWith(\"comfyui://\")) target = this.viewUrl(parseSource(source))\n const response = await this.request(target)\n if (!response.ok) throw new Error(`ComfyUI download failed (${response.status})`)\n return Buffer.from(await response.arrayBuffer())\n }\n\n private endpoint(route: string): URL {\n return new URL(route.replace(/^\\/+/, \"\"), `${this.baseUrl}/`)\n }\n\n private async json(route: string, init: RequestInit = {}): Promise<unknown> {\n const url = this.endpoint(route)\n const response = await this.request(url, {\n ...init,\n headers: {\n ...(init.body ? { \"Content-Type\": \"application/json\" } : {}),\n ...init.headers,\n },\n })\n const text = await response.text()\n let value: unknown = null\n try {\n value = text ? JSON.parse(text) : null\n } catch {\n if (response.ok) throw new Error(`ComfyUI returned invalid JSON from ${url.pathname}`)\n value = null\n }\n if (!response.ok) {\n const detail = apiError(value)\n throw new Error(\n `ComfyUI request failed (${response.status}) at ${url.pathname}` +\n (detail ? `: ${detail}` : \"\"),\n )\n }\n return value\n }\n}\n\n/** Self-hosted ComfyUI workflow adapter. */\nexport class ComfyUIProvider implements Provider {\n readonly id = \"comfyui\"\n\n constructor(private readonly client: ComfyUIClient = new ComfyUIClient()) {}\n\n static fromEnv(): ComfyUIProvider {\n return new ComfyUIProvider()\n }\n\n static forOffline(): ComfyUIProvider {\n return new ComfyUIProvider(new ComfyUIClient(DEFAULT_BASE_URL))\n }\n\n static forDownloads(): ComfyUIProvider {\n return new ComfyUIProvider()\n }\n\n async resolveOptions(\n value: Record<string, unknown>,\n context: ProviderOptionContext,\n ): Promise<ResolvedProviderOptions> {\n const options = parseOptions(value)\n const workflowPath = path.resolve(context.root, options.workflowFile)\n let raw: string\n try {\n raw = await readFile(workflowPath, \"utf8\")\n } catch (err) {\n throw new Error(\n `ComfyUI workflow for style \"${context.styleId}\" could not be read at ${workflowPath}: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n let parsed: unknown\n try {\n parsed = JSON.parse(raw)\n } catch {\n throw new Error(`ComfyUI workflow for style \"${context.styleId}\" is not valid JSON: ${workflowPath}`)\n }\n const workflow = parseWorkflow(parsed, workflowPath)\n validateWorkflowBindings(workflow, options)\n const workflowSha256 = sha256(JSON.stringify(canonical(workflow)))\n const resolved: ResolvedComfyUIOptions = { ...options, workflow, workflowSha256 }\n return {\n options: resolved as unknown as Record<string, unknown>,\n identity: {\n outputNodeId: options.outputNodeId,\n numImages: options.numImages,\n ...(options.frames ? { frames: options.frames } : {}),\n bindings: options.bindings,\n workflowSha256,\n },\n }\n }\n\n async resolveInputs(\n value: Record<string, ProviderInputValue>,\n context: ProviderInputContext,\n ): Promise<ResolvedProviderInputs> {\n const options = parseOptions(context.providerOptions)\n if (!options.workflow || !options.workflowSha256) {\n throw new Error(\"ComfyUI provider inputs require resolved workflow options\")\n }\n const inputs: Record<string, unknown> = {}\n const identity: Record<string, unknown> = {}\n for (const [name, input] of Object.entries(value)) {\n if (BUILTIN_BINDINGS.has(name)) {\n throw new Error(\n `ComfyUI providerInputs.${name} is reserved; use PixelKiln's built-in ${name} field`,\n )\n }\n const binding = Object.hasOwn(options.bindings, name) ? options.bindings[name] : undefined\n if (!binding) {\n throw new Error(\n `ComfyUI providerInputs.${name} has no matching bindings.${name} target`,\n )\n }\n const resolveValue = async (\n item: string | number | boolean,\n index?: number,\n ): Promise<{ runtime: unknown; stable: unknown }> => {\n const label = `providerInputs.${name}${index == null ? \"\" : `[${index}]`}`\n if (isImageBinding(options.workflow!, binding)) {\n if (typeof item !== \"string\") {\n throw new Error(`ComfyUI ${label} must be a manifest-relative PNG or JPEG path`)\n }\n const file = path.resolve(context.root, item)\n let bytes: Buffer\n try {\n bytes = await readFile(file)\n } catch (error) {\n throw new Error(\n `ComfyUI ${label} could not be read at ${file}: ` +\n `${error instanceof Error ? error.message : String(error)}`,\n )\n }\n const format = inputImageFormat(bytes)\n if (!format) throw new Error(`ComfyUI ${label} is not a PNG or JPEG: ${file}`)\n const hash = sha256(bytes)\n return {\n runtime: { kind: \"image\", path: file, sha256: hash, format } satisfies ComfyUIImageInput,\n stable: { kind: \"image\", sha256: hash, format },\n }\n }\n\n const current = options.workflow![binding.nodeId]!.inputs[binding.input]\n if (typeof current !== \"string\" && typeof current !== \"number\" && typeof current !== \"boolean\") {\n throw new Error(\n `ComfyUI ${label} cannot replace non-scalar ${binding.nodeId}.${binding.input}`,\n )\n }\n if (typeof current !== typeof item) {\n throw new Error(\n `ComfyUI ${label} must be ${typeof current} to match ${binding.nodeId}.${binding.input}`,\n )\n }\n return { runtime: item, stable: item }\n }\n\n if (Array.isArray(input)) {\n if (!options.frames || name !== options.frames.vary) {\n throw new Error(\n `ComfyUI providerInputs.${name} is an array but frames.vary is ` +\n `${options.frames ? `\"${options.frames.vary}\"` : \"not configured\"}`,\n )\n }\n const resolved = await Promise.all(input.map((item, index) => resolveValue(item, index)))\n inputs[name] = resolved.map((item) => item.runtime)\n identity[name] = resolved.map((item) => item.stable)\n } else {\n const resolved = await resolveValue(input)\n inputs[name] = resolved.runtime\n identity[name] = resolved.stable\n }\n }\n return { inputs, identity }\n }\n\n supports(generator: Generator): boolean {\n return generator === \"map\" || generator === \"frames\"\n }\n\n supportsRevision(_mode: RevisionMode): boolean {\n return true\n }\n\n estimate(spec: ResolvedSpec): CostEstimate {\n return {\n unit: \"free\",\n amount: 0,\n candidates: spec.generator === \"frames\" ? 1 : resolvedOptions(spec).numImages,\n }\n }\n\n validate(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): void {\n const options = resolvedOptions(spec)\n // A committed source can be a revision parent in the same style, but it is\n // never submitted. Revision-only workflows therefore do not need the\n // text-to-image bindings that this placeholder spec would otherwise imply.\n if (spec.source && !spec.revision) {\n if (spec.generator === \"frames\") {\n throw new Error(\"ComfyUI frame sets require generated provider outputs, not asset.source\")\n }\n return\n }\n if (spec.width < 16 || spec.height < 16 || spec.width > 4096 || spec.height > 4096) {\n throw new Error(\"ComfyUI output dimensions must be between 16 and 4096 pixels\")\n }\n if (styleImages.length) {\n throw new Error(\"ComfyUI styleImages are not supported yet; keep references inside the workflow\")\n }\n if (spec.palette.length) {\n throw new Error(\"ComfyUI does not map PixelKiln palette values yet; encode palette control in the workflow\")\n }\n if (spec.seed != null && !options.bindings.seed) {\n throw new Error(\"ComfyUI requires bindings.seed when the style declares a seed\")\n }\n if (!options.bindings.width !== !options.bindings.height) {\n throw new Error(\"ComfyUI width and height bindings must be declared together\")\n }\n if (!spec.revision && (!options.bindings.width || !options.bindings.height)) {\n throw new Error(\"ComfyUI text-to-image generation requires width and height bindings\")\n }\n if (options.numImages > 1 && !options.bindings.batchSize) {\n throw new Error(\"ComfyUI numImages greater than 1 requires bindings.batchSize\")\n }\n if (spec.generator === \"frames\") {\n if (!options.frames) throw new Error(\"ComfyUI frames generation requires providerOptions.comfyui.frames\")\n if (options.numImages !== 1) throw new Error(\"ComfyUI frames generation requires numImages: 1\")\n if (spec.revision) throw new Error(\"ComfyUI frame sets do not support asset revisions yet\")\n const values = spec.providerInputs?.[options.frames.vary]\n if (!Array.isArray(values) || values.length < 2 || values.length > 64) {\n throw new Error(\n `ComfyUI frames.vary \"${options.frames.vary}\" requires a providerInputs array of 2–64 values`,\n )\n }\n if (options.frames.seedStep !== 0 && (spec.seed == null || !options.bindings.seed)) {\n throw new Error(\"ComfyUI frames.seedStep requires a style seed and bindings.seed\")\n }\n if (\n spec.seed != null &&\n !Number.isSafeInteger(spec.seed + (values.length - 1) * options.frames.seedStep)\n ) {\n throw new Error(\"ComfyUI frame seed schedule exceeds JavaScript's safe integer range\")\n }\n } else if (options.frames) {\n throw new Error(\"ComfyUI providerOptions.frames requires generator: frames\")\n }\n if (spec.revision) {\n if (!options.bindings.sourceImage) {\n throw new Error(\"ComfyUI revisions require bindings.sourceImage\")\n }\n if (spec.revision.mode === \"inpaint\" && !options.bindings.maskImage) {\n throw new Error(\"ComfyUI inpaint revisions require bindings.maskImage\")\n }\n if (spec.revision.strength != null && !options.bindings.strength) {\n throw new Error(\"ComfyUI revision strength requires bindings.strength\")\n }\n if (\n (!options.bindings.width || !options.bindings.height) &&\n spec.revision.sourceWidth != null &&\n spec.revision.sourceHeight != null &&\n (spec.width !== spec.revision.sourceWidth || spec.height !== spec.revision.sourceHeight)\n ) {\n throw new Error(\n \"ComfyUI revisions without width/height bindings must keep the source dimensions\",\n )\n }\n }\n validateWorkflowBindings(options.workflow, options)\n }\n\n rateLimit(): RateLimit {\n return { spacingMs: 0, maxInFlight: 1 }\n }\n\n async submit(\n spec: ResolvedSpec,\n styleImages: ResolvedStyleImage[],\n context?: SubmitContext,\n ): Promise<ProviderSubmission> {\n this.validate(spec, styleImages)\n const options = resolvedOptions(spec)\n const uploadedImages = new Map<string, string>()\n const bindInput = async (\n workflow: ComfyWorkflow,\n name: string,\n input: unknown,\n ): Promise<void> => {\n const binding = Object.hasOwn(options.bindings, name) ? options.bindings[name] : undefined\n if (!binding) throw new Error(`ComfyUI provider input \"${name}\" has no binding`)\n if (!isComfyImageInput(input)) {\n setBinding(workflow, binding, input)\n return\n }\n const bytes = await readFile(input.path)\n if (sha256(bytes) !== input.sha256) {\n throw new Error(`ComfyUI provider input \"${name}\" changed before upload`)\n }\n let uploaded = uploadedImages.get(input.sha256)\n if (!uploaded) {\n uploaded = await this.client.uploadImage(bytes, input.sha256, input.format)\n uploadedImages.set(input.sha256, uploaded)\n }\n setBinding(workflow, binding, uploaded)\n }\n const buildWorkflow = async (frameIndex?: number): Promise<ComfyWorkflow> => {\n const workflow = structuredClone(options.workflow)\n setBinding(workflow, options.bindings.prompt, spec.prompt)\n if (options.bindings.width) setBinding(workflow, options.bindings.width, spec.width)\n if (options.bindings.height) setBinding(workflow, options.bindings.height, spec.height)\n if (options.bindings.batchSize) setBinding(workflow, options.bindings.batchSize, options.numImages)\n if (spec.seed != null && options.bindings.seed) {\n const seed = frameIndex == null ? spec.seed : spec.seed + frameIndex * (options.frames?.seedStep ?? 0)\n setBinding(workflow, options.bindings.seed, seed)\n }\n for (const [name, input] of Object.entries(spec.providerInputs ?? {})) {\n const selected = Array.isArray(input)\n ? (frameIndex == null ? input : input[frameIndex])\n : input\n await bindInput(workflow, name, selected)\n }\n return workflow\n }\n\n const inputs = providerInputProvenance(spec.providerInputs)\n if (spec.generator === \"frames\") {\n const frames = options.frames!\n const values = spec.providerInputs![frames.vary] as unknown[]\n let promptIds: string[] = []\n if (context?.previousJobId) {\n const previous = decodeFrameSetJob(context.previousJobId)\n if (\n previous.outputNodeId !== options.outputNodeId ||\n previous.expectedCount !== values.length\n ) {\n throw new Error(\"Saved ComfyUI frame checkpoint does not match the current frame set\")\n }\n promptIds = [...previous.promptIds]\n }\n for (let index = promptIds.length; index < values.length; index++) {\n promptIds.push(await this.client.submit(await buildWorkflow(index)))\n const frameJob = {\n expectedCount: values.length,\n promptIds: [...promptIds],\n outputNodeId: options.outputNodeId,\n }\n await context?.checkpoint({\n jobId: encodeFrameSetJob(frameJob),\n metadata: comfyFrameSubmissionMetadata(spec, frameJob),\n complete: promptIds.length === values.length,\n })\n }\n const frameJob = {\n expectedCount: values.length,\n promptIds,\n outputNodeId: options.outputNodeId,\n }\n return {\n jobId: encodeFrameSetJob(frameJob),\n metadata: comfyFrameSubmissionMetadata(spec, frameJob),\n }\n }\n\n const workflow = await buildWorkflow()\n if (spec.revision) {\n if (!spec.revision.sourceSha256 || !spec.revision.sourceFormat) {\n throw new Error(\"ComfyUI revision source is not ready\")\n }\n const sourceBytes = await readFile(spec.revision.sourceFile)\n if (sha256(sourceBytes) !== spec.revision.sourceSha256) {\n throw new Error(\"ComfyUI revision source changed before upload\")\n }\n const uploadedSource = await this.client.uploadImage(\n sourceBytes,\n spec.revision.sourceSha256,\n spec.revision.sourceFormat,\n )\n setBinding(workflow, options.bindings.sourceImage!, uploadedSource)\n\n if (spec.revision.maskFile) {\n if (!spec.revision.maskSha256 || !spec.revision.maskFormat) {\n throw new Error(\"ComfyUI revision mask is not ready\")\n }\n const maskBytes = await readFile(spec.revision.maskFile)\n if (sha256(maskBytes) !== spec.revision.maskSha256) {\n throw new Error(\"ComfyUI revision mask changed before upload\")\n }\n const uploadedMask = await this.client.uploadImage(\n maskBytes,\n spec.revision.maskSha256,\n spec.revision.maskFormat,\n )\n setBinding(workflow, options.bindings.maskImage!, uploadedMask)\n }\n if (spec.revision.strength != null) {\n setBinding(workflow, options.bindings.strength!, spec.revision.strength)\n }\n }\n const promptId = await this.client.submit(workflow)\n const metadata = {\n ...(Object.keys(inputs).length ? { inputs } : {}),\n ...(spec.revision\n ? {\n revision: {\n mode: spec.revision.mode,\n sourceAssetId: spec.revision.sourceAssetId,\n sourceSha256: spec.revision.sourceSha256,\n ...(spec.revision.maskSha256 ? { maskSha256: spec.revision.maskSha256 } : {}),\n },\n }\n : {}),\n }\n return {\n jobId: encodeJob(promptId, options.outputNodeId),\n ...(Object.keys(metadata).length ? { metadata } : {}),\n }\n }\n\n async poll(jobId: string, generator: Generator, context?: PollContext): Promise<JobState> {\n if (generator === \"frames\") {\n const frameJob = decodeFrameSetJob(jobId)\n if (frameJob.promptIds.length < frameJob.expectedCount) {\n return { status: \"processing\" }\n }\n const images: ComfyImage[] = []\n for (let index = 0; index < frameJob.promptIds.length; index++) {\n const promptId = frameJob.promptIds[index]!\n const history = await this.client.history(promptId)\n const entry = historyEntry(history, promptId)\n if (!entry) return { status: \"processing\" }\n const status = isObject(entry.status) ? entry.status : {}\n if (status.status_str === \"error\") {\n return { status: \"failed\", error: `frame ${index}: ${historyError(status)}` }\n }\n if (status.completed === false) return { status: \"processing\" }\n const output = outputImages(entry, frameJob.outputNodeId)\n if (output instanceof Error) {\n return { status: \"failed\", error: `frame ${index}: ${output.message}` }\n }\n if (output.length !== 1) {\n return {\n status: \"failed\",\n error: `frame ${index}: ComfyUI returned ${output.length} images, expected 1`,\n }\n }\n images.push(output[0]!)\n }\n const fps = context?.spec?.quality?.fps ?? 12\n const sources = images.map((image, index) => ({\n url: sourceRef(image),\n role: frameRole(index),\n mediaType: MediaType.PNG,\n }))\n return {\n status: \"review-set\",\n objectId: jobId,\n frameUrls: images.map((image) => this.client.viewUrl(image)),\n sources,\n fps,\n metadata: context?.spec\n ? comfyFrameMetadata(context.spec, frameJob, images, fps)\n : { frameSet: { count: images.length, fps, promptIds: frameJob.promptIds } },\n }\n }\n const { promptId, outputNodeId } = decodeJob(jobId)\n const history = await this.client.history(promptId)\n const entry = historyEntry(history, promptId)\n if (!entry) return { status: \"processing\" }\n\n const status = isObject(entry.status) ? entry.status : {}\n const statusText = typeof status.status_str === \"string\" ? status.status_str : \"\"\n if (statusText === \"error\") {\n return { status: \"failed\", error: historyError(status) }\n }\n if (status.completed === false) return { status: \"processing\" }\n\n const images = outputImages(entry, outputNodeId)\n if (images instanceof Error) return { status: \"failed\", error: images.message }\n const expected = context?.spec ? resolvedOptions(context.spec).numImages : null\n if (expected != null && images.length !== expected) {\n return {\n status: \"failed\",\n error: `ComfyUI output node \"${outputNodeId}\" returned ${images.length} image(s), expected ${expected}`,\n }\n }\n const metadata = context?.spec ? comfyMetadata(context.spec, promptId, outputNodeId, images) : {\n promptId,\n outputNodeId,\n outputCount: images.length,\n }\n if (images.length > 1) {\n return {\n status: \"review\",\n candidateUrls: images.map((image) => this.client.viewUrl(image)),\n metadata,\n }\n }\n const sourceUrl = sourceRef(images[0]!)\n return {\n status: \"ready\",\n objectId: `${promptId}#${outputNodeId}#0`,\n sourceUrl,\n sources: [{ url: sourceUrl, mediaType: MediaType.PNG }],\n metadata,\n }\n }\n\n async selectCandidate(\n jobId: string,\n index: number,\n ): Promise<{ objectId: string; sourceUrl: string | null }> {\n const { promptId, outputNodeId } = decodeJob(jobId)\n const history = await this.client.history(promptId)\n const entry = historyEntry(history, promptId)\n if (!entry) throw new Error(`ComfyUI prompt ${promptId} is not complete`)\n const images = outputImages(entry, outputNodeId)\n if (images instanceof Error) throw images\n const image = images[index]\n if (!image) throw new Error(`ComfyUI prompt ${promptId} has no candidate at index ${index}`)\n return {\n objectId: `${promptId}#${outputNodeId}#${index}`,\n sourceUrl: sourceRef(image),\n }\n }\n\n async download(url: string): Promise<Buffer> {\n return this.client.download(url)\n }\n\n async checkConnection(): Promise<void> {\n await this.client.checkConnection()\n }\n}\n\nfunction parseOptions(value: Record<string, unknown>): ResolvedComfyUIOptions {\n const allowed = new Set([\n \"workflowFile\", \"outputNodeId\", \"numImages\", \"frames\", \"bindings\", \"workflow\", \"workflowSha256\",\n ])\n const extra = Object.keys(value).filter((key) => !allowed.has(key))\n if (extra.length) throw new Error(`Unknown ComfyUI option(s): ${extra.join(\", \")}`)\n const workflowFile = requiredString(value.workflowFile, \"workflowFile\")\n const outputNodeId = requiredString(value.outputNodeId, \"outputNodeId\")\n const numImages = value.numImages ?? 1\n if (!Number.isInteger(numImages) || Number(numImages) < 1 || Number(numImages) > 16) {\n throw new Error(\"ComfyUI numImages must be a whole number from 1 to 16\")\n }\n if (!isObject(value.bindings)) throw new Error(\"ComfyUI bindings must be an object\")\n const bindings = Object.fromEntries(\n Object.entries(value.bindings).map(([name, binding]) => [name, parseBinding(binding, name)]),\n ) as unknown as ComfyUIBindings\n if (!bindings.prompt) throw new Error(\"ComfyUI bindings.prompt must be an object\")\n const frames = value.frames == null ? undefined : parseFrames(value.frames)\n if (frames) {\n if (BUILTIN_BINDINGS.has(frames.vary)) {\n throw new Error(`ComfyUI frames.vary must name a custom binding, not \"${frames.vary}\"`)\n }\n if (!Object.hasOwn(bindings, frames.vary)) {\n throw new Error(`ComfyUI frames.vary \"${frames.vary}\" has no matching binding`)\n }\n }\n const workflow = value.workflow == null ? undefined : parseWorkflow(value.workflow, workflowFile)\n const workflowSha256 = value.workflowSha256 == null\n ? undefined\n : requiredString(value.workflowSha256, \"workflowSha256\")\n return {\n workflowFile,\n outputNodeId,\n numImages: Number(numImages),\n bindings,\n ...(frames ? { frames } : {}),\n ...(workflow ? { workflow } : {}),\n ...(workflowSha256 ? { workflowSha256 } : {}),\n } as ResolvedComfyUIOptions\n}\n\nfunction parseFrames(value: unknown): { vary: string; seedStep: number } {\n if (!isObject(value)) throw new Error(\"ComfyUI frames must be an object\")\n const extra = Object.keys(value).filter((key) => key !== \"vary\" && key !== \"seedStep\")\n if (extra.length) throw new Error(`Unknown ComfyUI frames field(s): ${extra.join(\", \")}`)\n const vary = requiredString(value.vary, \"frames.vary\")\n const seedStep = value.seedStep ?? 0\n if (!Number.isSafeInteger(seedStep) || Math.abs(Number(seedStep)) > 1_000_000) {\n throw new Error(\"ComfyUI frames.seedStep must be a safe integer from -1000000 to 1000000\")\n }\n return { vary, seedStep: Number(seedStep) }\n}\n\nfunction resolvedOptions(spec: ResolvedSpec): ResolvedComfyUIOptions {\n const options = parseOptions(spec.providerOptions)\n if (!options.workflow || !options.workflowSha256) {\n throw new Error(\"ComfyUI workflow options were not resolved from workflowFile\")\n }\n return options\n}\n\nfunction parseBinding(value: unknown, name: string): ComfyUIBinding {\n if (!isObject(value)) throw new Error(`ComfyUI bindings.${name} must be an object`)\n const extra = Object.keys(value).filter((key) => key !== \"nodeId\" && key !== \"input\")\n if (extra.length) throw new Error(`Unknown ComfyUI bindings.${name} field(s): ${extra.join(\", \")}`)\n return {\n nodeId: requiredString(value.nodeId, `bindings.${name}.nodeId`),\n input: requiredString(value.input, `bindings.${name}.input`),\n }\n}\n\nfunction parseWorkflow(value: unknown, label: string): ComfyWorkflow {\n if (!isObject(value) || !Object.keys(value).length) {\n throw new Error(`ComfyUI workflow is not a non-empty API-format object: ${label}`)\n }\n for (const [nodeId, node] of Object.entries(value)) {\n if (!isObject(node) || typeof node.class_type !== \"string\" || !isObject(node.inputs)) {\n throw new Error(`ComfyUI workflow node \"${nodeId}\" must contain class_type and inputs`)\n }\n }\n return value as ComfyWorkflow\n}\n\nfunction validateWorkflowBindings(workflow: ComfyWorkflow, options: ComfyUIOptions): void {\n const targets = new Map<string, string>()\n for (const [name, binding] of Object.entries(options.bindings)) {\n if (!binding) continue\n const node = workflow[binding.nodeId]\n if (!node) throw new Error(`ComfyUI ${name} binding refers to missing node \"${binding.nodeId}\"`)\n if (!Object.hasOwn(node.inputs, binding.input)) {\n throw new Error(\n `ComfyUI ${name} binding refers to missing input \"${binding.input}\" on node \"${binding.nodeId}\"`,\n )\n }\n const target = `${binding.nodeId}.${binding.input}`\n const prior = targets.get(target)\n if (prior) {\n throw new Error(`ComfyUI bindings.${name} and bindings.${prior} target the same input ${target}`)\n }\n targets.set(target, name)\n }\n if (!workflow[options.outputNodeId]) {\n throw new Error(`ComfyUI outputNodeId refers to missing node \"${options.outputNodeId}\"`)\n }\n}\n\nfunction setBinding(workflow: ComfyWorkflow, binding: ComfyUIBinding, value: unknown): void {\n const node = workflow[binding.nodeId]\n if (!node || !Object.hasOwn(node.inputs, binding.input)) {\n throw new Error(`ComfyUI binding ${binding.nodeId}.${binding.input} is unavailable`)\n }\n node.inputs[binding.input] = value\n}\n\nfunction historyEntry(history: unknown, promptId: string): JsonObject | null {\n if (!isObject(history)) throw new Error(\"ComfyUI returned invalid history JSON\")\n const entry = history[promptId]\n if (entry == null) return null\n if (!isObject(entry)) throw new Error(`ComfyUI returned invalid history for prompt ${promptId}`)\n return entry\n}\n\nfunction outputImages(entry: JsonObject, outputNodeId: string): ComfyImage[] | Error {\n if (!isObject(entry.outputs)) return new Error(\"ComfyUI completed without workflow outputs\")\n const output = entry.outputs[outputNodeId]\n if (!isObject(output) || !Array.isArray(output.images)) {\n return new Error(`ComfyUI output node \"${outputNodeId}\" returned no images`)\n }\n const images: ComfyImage[] = []\n for (const value of output.images) {\n if (\n !isObject(value) ||\n typeof value.filename !== \"string\" ||\n typeof value.subfolder !== \"string\" ||\n value.type !== \"output\"\n ) {\n return new Error(`ComfyUI output node \"${outputNodeId}\" returned an invalid image record`)\n }\n images.push({ filename: value.filename, subfolder: value.subfolder, type: \"output\" })\n }\n if (!images.length) return new Error(`ComfyUI output node \"${outputNodeId}\" returned no images`)\n return images\n}\n\nfunction comfyMetadata(\n spec: ResolvedSpec,\n promptId: string,\n outputNodeId: string,\n images: ComfyImage[],\n): JsonObject {\n const options = resolvedOptions(spec)\n const inputs = providerInputProvenance(spec.providerInputs)\n return {\n promptId,\n outputNodeId,\n outputCount: images.length,\n workflowFile: options.workflowFile,\n workflowSha256: options.workflowSha256,\n files: images.map((image) => ({ ...image })),\n ...(Object.keys(inputs).length ? { inputs } : {}),\n ...(spec.revision\n ? {\n revision: {\n mode: spec.revision.mode,\n sourceAssetId: spec.revision.sourceAssetId,\n sourceSha256: spec.revision.sourceSha256,\n ...(spec.revision.maskSha256\n ? { maskSha256: spec.revision.maskSha256 }\n : {}),\n ...(spec.revision.strength == null ? {} : { strength: spec.revision.strength }),\n },\n }\n : {}),\n }\n}\n\nfunction comfyFrameMetadata(\n spec: ResolvedSpec,\n job: FrameSetJob,\n images: ComfyImage[],\n fps: number,\n): JsonObject {\n const options = resolvedOptions(spec)\n return {\n workflowFile: options.workflowFile,\n workflowSha256: options.workflowSha256,\n outputNodeId: job.outputNodeId,\n inputs: providerInputProvenance(spec.providerInputs),\n frameSet: {\n count: images.length,\n vary: options.frames!.vary,\n seedStep: options.frames!.seedStep,\n fps,\n promptIds: job.promptIds,\n frames: images.map((image, index) => ({ role: frameRole(index), ...image })),\n },\n }\n}\n\nfunction comfyFrameSubmissionMetadata(\n spec: ResolvedSpec,\n job: FrameSetJob,\n): JsonObject {\n const options = resolvedOptions(spec)\n return {\n inputs: providerInputProvenance(spec.providerInputs),\n frameSet: {\n count: job.expectedCount,\n vary: options.frames!.vary,\n seedStep: options.frames!.seedStep,\n fps: spec.quality?.fps ?? 12,\n promptIds: job.promptIds,\n },\n }\n}\n\nfunction isImageBinding(workflow: ComfyWorkflow, binding: ComfyUIBinding): boolean {\n const node = workflow[binding.nodeId]\n return binding.input === \"image\" &&\n (node?.class_type === \"LoadImage\" || node?.class_type === \"LoadImageMask\")\n}\n\nfunction isComfyImageInput(value: unknown): value is ComfyUIImageInput {\n return isObject(value) &&\n value.kind === \"image\" &&\n typeof value.path === \"string\" &&\n typeof value.sha256 === \"string\" &&\n (value.format === \"png\" || value.format === \"jpeg\")\n}\n\nfunction providerInputProvenance(\n inputs: Record<string, unknown> | undefined,\n): Record<string, unknown> {\n return Object.fromEntries(Object.entries(inputs ?? {}).map(([name, input]) => [\n name,\n Array.isArray(input)\n ? { kind: \"sequence\", values: input.map(providerInputValueProvenance) }\n : providerInputValueProvenance(input),\n ]))\n}\n\nfunction providerInputValueProvenance(input: unknown): unknown {\n return isComfyImageInput(input)\n ? { kind: \"image\", sha256: input.sha256, format: input.format }\n : { kind: \"value\", value: input }\n}\n\nfunction inputImageFormat(bytes: Buffer): \"png\" | \"jpeg\" | null {\n if (\n bytes.length >= 24 &&\n bytes.readUInt32BE(0) === 0x89504e47 &&\n bytes.readUInt32BE(4) === 0x0d0a1a0a &&\n bytes.toString(\"ascii\", 12, 16) === \"IHDR\" &&\n bytes.readUInt32BE(16) > 0 &&\n bytes.readUInt32BE(20) > 0\n ) return \"png\"\n\n if (bytes.length < 4 || bytes[0] !== 0xff || bytes[1] !== 0xd8) return null\n let offset = 2\n while (offset + 3 < bytes.length) {\n if (bytes[offset] !== 0xff) return null\n while (bytes[offset] === 0xff) offset++\n const marker = bytes[offset++]\n if (marker == null || marker === 0xd9 || marker === 0xda) break\n if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) continue\n if (offset + 2 > bytes.length) return null\n const length = bytes.readUInt16BE(offset)\n if (length < 2 || offset + length > bytes.length) return null\n const isStartOfFrame = marker >= 0xc0 && marker <= 0xcf && ![0xc4, 0xc8, 0xcc].includes(marker)\n if (isStartOfFrame) {\n if (length < 7) return null\n return bytes.readUInt16BE(offset + 3) > 0 && bytes.readUInt16BE(offset + 5) > 0\n ? \"jpeg\"\n : null\n }\n offset += length\n }\n return null\n}\n\nfunction encodeJob(promptId: string, outputNodeId: string): string {\n return `${promptId}#${encodeURIComponent(outputNodeId)}`\n}\n\nfunction frameRole(index: number): string {\n return `frame-${String(index).padStart(2, \"0\")}`\n}\n\nfunction encodeFrameSetJob(job: FrameSetJob): string {\n return `frames:${Buffer.from(JSON.stringify(job)).toString(\"base64url\")}`\n}\n\nfunction decodeFrameSetJob(jobId: string): FrameSetJob {\n if (!jobId.startsWith(\"frames:\")) throw new Error(`Invalid ComfyUI frame-set job id \"${jobId}\"`)\n let value: unknown\n try {\n value = JSON.parse(Buffer.from(jobId.slice(7), \"base64url\").toString(\"utf8\"))\n } catch {\n throw new Error(`Invalid ComfyUI frame-set job id \"${jobId}\"`)\n }\n if (!isObject(value) || !Array.isArray(value.promptIds)) {\n throw new Error(`Invalid ComfyUI frame-set job id \"${jobId}\"`)\n }\n const expectedCount = value.expectedCount === undefined\n ? value.promptIds.length\n : value.expectedCount\n if (\n typeof value.outputNodeId !== \"string\" ||\n !value.outputNodeId ||\n typeof expectedCount !== \"number\" ||\n !Number.isSafeInteger(expectedCount) ||\n expectedCount < 2 ||\n expectedCount > 64 ||\n value.promptIds.length < 1 ||\n value.promptIds.length > expectedCount ||\n !value.promptIds.every((id) => typeof id === \"string\" && id.length > 0)\n ) {\n throw new Error(`Invalid ComfyUI frame-set job id \"${jobId}\"`)\n }\n return {\n expectedCount,\n outputNodeId: value.outputNodeId,\n promptIds: value.promptIds as string[],\n }\n}\n\nfunction decodeJob(jobId: string): { promptId: string; outputNodeId: string } {\n const split = jobId.lastIndexOf(\"#\")\n if (split < 1 || split === jobId.length - 1) throw new Error(`Invalid ComfyUI job id \"${jobId}\"`)\n return {\n promptId: jobId.slice(0, split),\n outputNodeId: decodeURIComponent(jobId.slice(split + 1)),\n }\n}\n\nfunction sourceRef(image: ComfyImage): string {\n const url = new URL(\"comfyui://output\")\n url.searchParams.set(\"filename\", image.filename)\n url.searchParams.set(\"subfolder\", image.subfolder)\n url.searchParams.set(\"type\", image.type)\n return url.toString()\n}\n\nfunction parseSource(source: string): ComfyImage {\n let url: URL\n try {\n url = new URL(source)\n } catch {\n throw new Error(\"Invalid ComfyUI output reference\")\n }\n const filename = url.searchParams.get(\"filename\")\n const subfolder = url.searchParams.get(\"subfolder\")\n const type = url.searchParams.get(\"type\")\n if (url.protocol !== \"comfyui:\" || url.hostname !== \"output\" || !filename || subfolder == null || type !== \"output\") {\n throw new Error(\"Invalid ComfyUI output reference\")\n }\n return { filename, subfolder, type }\n}\n\nfunction normalizeBaseUrl(value: string): string {\n let url: URL\n try {\n url = new URL(value)\n } catch {\n throw new Error(\"COMFYUI_BASE_URL must be an absolute HTTP(S) URL\")\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"COMFYUI_BASE_URL must use HTTP or HTTPS\")\n }\n url.hash = \"\"\n url.search = \"\"\n return url.toString().replace(/\\/$/, \"\")\n}\n\nfunction historyError(status: JsonObject): string {\n const messages = Array.isArray(status.messages) ? status.messages : []\n for (const message of messages) {\n if (!Array.isArray(message) || message[0] !== \"execution_error\" || !isObject(message[1])) continue\n const detail = message[1].exception_message\n if (typeof detail === \"string\" && detail.trim()) {\n return `ComfyUI execution failed: ${detail.trim().slice(0, 300)}`\n }\n }\n return \"ComfyUI execution failed\"\n}\n\nfunction apiError(value: unknown): string | null {\n if (!isObject(value)) return null\n const raw = typeof value.error === \"string\"\n ? value.error\n : isObject(value.error) && typeof value.error.message === \"string\"\n ? value.error.message\n : typeof value.message === \"string\"\n ? value.message\n : null\n const nodes = isObject(value.node_errors) ? Object.keys(value.node_errors) : []\n if (nodes.length) {\n return `${raw ? `${raw}; ` : \"\"}invalid workflow node(s): ${nodes.slice(0, 8).join(\", \")}`\n }\n return raw?.trim().slice(0, 300) || null\n}\n\nfunction requiredString(value: unknown, name: string): string {\n if (typeof value !== \"string\" || !value.trim()) throw new Error(`ComfyUI ${name} must be a non-empty string`)\n return value.trim()\n}\n\nfunction isObject(value: unknown): value is JsonObject {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value)\n}\n\nfunction canonical(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(canonical)\n if (!isObject(value)) return value\n return Object.fromEntries(\n Object.keys(value)\n .sort()\n .map((key) => [key, canonical(value[key])]),\n )\n}\n","import { createHash } from \"node:crypto\"\nimport { createReadStream } from \"node:fs\"\nimport type { ResolvedSpec } from \"./types.ts\"\n\nexport function sha256(data: Buffer | string): string {\n return createHash(\"sha256\").update(data).digest(\"hex\")\n}\n\nexport async function sha256File(path: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const hash = createHash(\"sha256\")\n const stream = createReadStream(path)\n stream.on(\"data\", (chunk) => hash.update(chunk))\n stream.on(\"error\", reject)\n stream.on(\"end\", () => resolve(hash.digest(\"hex\")))\n })\n}\n\n/**\n * Identity of a spec: everything that would change the generated image.\n * Project root, `outFile`, committed `source`, and `tags` are deliberately excluded —\n * moving a checkout, renaming the destination, swapping the committed art a\n * `mount` places, or retagging should not regenerate art.\n *\n * Generator-specific parameters are hashed only where they apply, and are\n * left `undefined` otherwise so `JSON.stringify` drops the key entirely.\n * That matters: adding a field unconditionally rewrites the hash of every\n * spec in every existing lockfile, and each one then reports as `stale` and\n * invites a full regeneration of art that never changed. Adding `palette`\n * unconditionally did exactly that once already.\n */\nexport function specHash(\n spec: Omit<ResolvedSpec, \"specHash\" | \"root\" | \"outFile\" | \"quality\" | \"source\" | \"tags\">,\n styleImageHashes: string[],\n providerOptionIdentity: unknown = spec.providerOptions,\n providerInputIdentity: unknown = spec.providerInputs ?? {},\n): string {\n return sha256(\n JSON.stringify({\n // Preserve every existing PixelLab hash while making a provider switch\n // invalidate the spec. Older manifests implicitly mean pixellab.\n provider: spec.provider === \"pixellab\" ? undefined : spec.provider,\n providerOptions:\n providerOptionIdentity &&\n (typeof providerOptionIdentity !== \"object\" || Object.keys(providerOptionIdentity).length > 0)\n ? providerOptionIdentity\n : undefined,\n providerInputs:\n providerInputIdentity &&\n (typeof providerInputIdentity !== \"object\" || Object.keys(providerInputIdentity).length > 0)\n ? providerInputIdentity\n : undefined,\n generator: spec.generator,\n prompt: spec.prompt,\n width: spec.width,\n height: spec.height,\n view: spec.view,\n outline: spec.outline ?? null,\n shading: spec.shading ?? null,\n detail: spec.detail ?? null,\n seed: spec.seed ?? null,\n palette: spec.palette,\n // `noBackground` only reaches the wire for pixflux; the tile fields are\n // undefined for every other generator. `tileSize` is intentionally\n // absent — width/height are derived from it, so it is already covered.\n noBackground:\n spec.generator === \"pixflux\" || spec.provider !== \"pixellab\"\n ? spec.noBackground\n : undefined,\n tileType: spec.tileType,\n tileView: spec.tileView,\n tileFeature: spec.tileFeature,\n outlineMode: spec.outlineMode,\n styleImages: styleImageHashes,\n revision: spec.revision\n ? {\n mode: spec.revision.mode,\n from: spec.revision.sourceAssetId,\n sourceSha256: spec.revision.sourceSha256,\n maskSha256: spec.revision.maskSha256,\n strength: spec.revision.strength,\n }\n : undefined,\n }),\n )\n}\n","import { deflateSync, inflateSync } from \"node:zlib\"\n\nexport interface DecodedPng {\n width: number\n height: number\n /** RGBA, 4 bytes per pixel, row-major. */\n pixels: Buffer\n}\n\nconst SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])\nconst MAX_DECODED_BYTES = 256 * 1024 * 1024\n\ninterface PngHeader {\n width: number\n height: number\n bitDepth: number\n colorType: number\n channels: number\n}\n\nconst CHANNELS = new Map([\n [0, 1], // greyscale\n [2, 3], // RGB\n [3, 1], // indexed colour\n [4, 2], // greyscale + alpha\n [6, 4], // RGBA\n])\n\nconst LEGAL_DEPTHS = new Map<number, Set<number>>([\n [0, new Set([1, 2, 4, 8, 16])],\n [2, new Set([8, 16])],\n [3, new Set([1, 2, 4, 8])],\n [4, new Set([8, 16])],\n [6, new Set([8, 16])],\n])\n\n/**\n * Dependency-free decoder for standard non-interlaced PNG colour modes.\n *\n * Inputs are normalized to 8-bit RGBA for the audit and sheet pipelines. Adam7\n * remains deliberately unsupported: provider and game-art PNGs are normally\n * non-interlaced, and refusing the uncommon layout is safer than implementing\n * a second scanline geometry without a dedicated image dependency.\n */\nexport function decodePng(buf: Buffer): DecodedPng {\n if (buf.length < 8 || !buf.subarray(0, 8).equals(SIGNATURE)) {\n throw new Error(\"not a PNG\")\n }\n\n let header: PngHeader | null = null\n let palette: Buffer | null = null\n let transparency: Buffer | null = null\n let sawImageData = false\n let sawEnd = false\n const idat: Buffer[] = []\n\n let offset = 8\n while (offset < buf.length) {\n if (offset + 12 > buf.length) throw new Error(\"truncated PNG chunk header\")\n const length = buf.readUInt32BE(offset)\n const type = buf.toString(\"ascii\", offset + 4, offset + 8)\n if (!/^[A-Za-z]{4}$/.test(type) || /[a-z]/.test(type[2]!)) {\n throw new Error(`PNG has an invalid chunk type ${JSON.stringify(type)}`)\n }\n const end = offset + 12 + length\n if (!Number.isSafeInteger(end) || end > buf.length) {\n throw new Error(`truncated PNG chunk ${type || \"(unknown)\"}`)\n }\n const data = buf.subarray(offset + 8, offset + 8 + length)\n const expectedCrc = buf.readUInt32BE(offset + 8 + length)\n const actualCrc = crc32(buf.subarray(offset + 4, offset + 8 + length)) >>> 0\n if (actualCrc !== expectedCrc) throw new Error(`PNG chunk ${type} has an invalid checksum`)\n\n if (!header && type !== \"IHDR\") throw new Error(\"PNG is missing its leading IHDR chunk\")\n\n if (type === \"IHDR\") {\n if (header) throw new Error(\"PNG has more than one IHDR chunk\")\n if (data.length !== 13) throw new Error(\"PNG has an invalid IHDR chunk\")\n const width = data.readUInt32BE(0)\n const height = data.readUInt32BE(4)\n const bitDepth = data[8]!\n const colorType = data[9]!\n const channels = CHANNELS.get(colorType)\n if (!width || !height) throw new Error(\"PNG dimensions must be positive\")\n if (!channels || !LEGAL_DEPTHS.get(colorType)?.has(bitDepth)) {\n throw new Error(`unsupported PNG: bitDepth=${bitDepth} colorType=${colorType}`)\n }\n if (data[10] !== 0) throw new Error(`unsupported PNG compression method ${data[10]}`)\n if (data[11] !== 0) throw new Error(`unsupported PNG filter method ${data[11]}`)\n if (data[12] !== 0) throw new Error(\"unsupported PNG: interlaced\")\n header = { width, height, bitDepth, colorType, channels }\n } else if (type === \"PLTE\") {\n if (sawImageData) throw new Error(\"PNG palette appears after image data\")\n if (palette) throw new Error(\"PNG has more than one palette\")\n if (!data.length || data.length % 3 !== 0 || data.length > 256 * 3) {\n throw new Error(\"PNG has an invalid palette\")\n }\n palette = Buffer.from(data)\n } else if (type === \"tRNS\") {\n if (sawImageData) throw new Error(\"PNG transparency appears after image data\")\n if (transparency) throw new Error(\"PNG has more than one transparency chunk\")\n transparency = Buffer.from(data)\n } else if (type === \"IDAT\") {\n sawImageData = true\n idat.push(data)\n } else if (type === \"IEND\") {\n if (data.length !== 0) throw new Error(\"PNG has an invalid IEND chunk\")\n sawEnd = true\n break\n } else if (/^[A-Z]/.test(type)) {\n throw new Error(`unsupported critical PNG chunk ${type}`)\n }\n offset = end\n }\n\n if (!header) throw new Error(\"PNG has no image header\")\n if (!sawEnd) throw new Error(\"PNG has no IEND chunk\")\n if (!idat.length) throw new Error(\"PNG has no image data\")\n validatePalette(header, palette)\n validateTransparency(header.colorType, transparency, palette)\n\n const bitsPerPixel = header.channels * header.bitDepth\n const stride = Math.ceil((header.width * bitsPerPixel) / 8)\n const rawLength = (stride + 1) * header.height\n const rgbaLength = header.width * header.height * 4\n if (\n !Number.isSafeInteger(rawLength) ||\n !Number.isSafeInteger(rgbaLength) ||\n rawLength > MAX_DECODED_BYTES ||\n rgbaLength > MAX_DECODED_BYTES\n ) {\n throw new Error(\"PNG dimensions exceed the 256 MiB decoded-image limit\")\n }\n\n let raw: Buffer\n try {\n raw = inflateSync(Buffer.concat(idat), { maxOutputLength: rawLength })\n } catch (err) {\n throw new Error(`invalid PNG image data: ${err instanceof Error ? err.message : String(err)}`)\n }\n if (raw.length !== rawLength) {\n throw new Error(`invalid PNG image data length: expected ${rawLength}, got ${raw.length}`)\n }\n\n const filterBytes = Math.max(1, Math.ceil(bitsPerPixel / 8))\n const samples = unfilter(raw, stride, header.height, filterBytes)\n return {\n width: header.width,\n height: header.height,\n pixels: toRgba(samples, header, stride, palette, transparency),\n }\n}\n\nfunction validatePalette(header: PngHeader, palette: Buffer | null): void {\n if (header.colorType === 3 && !palette) throw new Error(\"indexed PNG has no palette\")\n if ((header.colorType === 0 || header.colorType === 4) && palette) {\n throw new Error(\"greyscale PNG cannot contain a palette\")\n }\n if (header.colorType === 3 && palette && palette.length / 3 > 2 ** header.bitDepth) {\n throw new Error(\"indexed PNG palette has more entries than its bit depth permits\")\n }\n}\n\n/**\n * Reverses PNG's per-scanline filters. Each row is prefixed with a filter byte\n * and predicted from the row above and the pixel to the left.\n */\nfunction unfilter(raw: Buffer, stride: number, height: number, bpp: number): Buffer {\n const out = Buffer.alloc(stride * height)\n\n for (let y = 0; y < height; y++) {\n const filter = raw[y * (stride + 1)]!\n const src = raw.subarray(y * (stride + 1) + 1, y * (stride + 1) + 1 + stride)\n const dst = out.subarray(y * stride, (y + 1) * stride)\n const prev = y > 0 ? out.subarray((y - 1) * stride, y * stride) : null\n\n for (let x = 0; x < stride; x++) {\n const a = x >= bpp ? dst[x - bpp]! : 0 // left\n const b = prev ? prev[x]! : 0 // above\n const c = prev && x >= bpp ? prev[x - bpp]! : 0 // upper-left\n const v = src[x]!\n switch (filter) {\n case 0: dst[x] = v; break\n case 1: dst[x] = (v + a) & 0xff; break\n case 2: dst[x] = (v + b) & 0xff; break\n case 3: dst[x] = (v + ((a + b) >> 1)) & 0xff; break\n case 4: dst[x] = (v + paeth(a, b, c)) & 0xff; break\n default: throw new Error(`unknown PNG filter ${filter} on row ${y}`)\n }\n }\n }\n return out\n}\n\nfunction validateTransparency(\n colorType: number,\n transparency: Buffer | null,\n palette: Buffer | null,\n): void {\n if (!transparency) return\n if (colorType === 0 && transparency.length !== 2) {\n throw new Error(\"greyscale PNG has an invalid transparency chunk\")\n }\n if (colorType === 2 && transparency.length !== 6) {\n throw new Error(\"RGB PNG has an invalid transparency chunk\")\n }\n if (colorType === 3 && transparency.length > (palette?.length ?? 0) / 3) {\n throw new Error(\"indexed PNG transparency exceeds its palette\")\n }\n if (colorType === 4 || colorType === 6) {\n throw new Error(\"PNG with an alpha channel cannot also contain tRNS\")\n }\n}\n\nfunction toRgba(\n samples: Buffer,\n header: PngHeader,\n stride: number,\n palette: Buffer | null,\n transparency: Buffer | null,\n): Buffer {\n const out = Buffer.alloc(header.width * header.height * 4)\n const transparentGrey = header.colorType === 0 && transparency\n ? transparency.readUInt16BE(0)\n : null\n const transparentRgb = header.colorType === 2 && transparency\n ? [\n transparency.readUInt16BE(0),\n transparency.readUInt16BE(2),\n transparency.readUInt16BE(4),\n ]\n : null\n\n for (let y = 0; y < header.height; y++) {\n const row = samples.subarray(y * stride, (y + 1) * stride)\n for (let x = 0; x < header.width; x++) {\n const dst = (y * header.width + x) * 4\n if (header.colorType === 0) {\n const grey = sample(row, x, 0, header.channels, header.bitDepth)\n const byte = sampleToByte(grey, header.bitDepth)\n out[dst] = byte\n out[dst + 1] = byte\n out[dst + 2] = byte\n out[dst + 3] = grey === transparentGrey ? 0 : 255\n } else if (header.colorType === 2) {\n const rgb = [0, 1, 2].map((channel) =>\n sample(row, x, channel, header.channels, header.bitDepth))\n out[dst] = sampleToByte(rgb[0]!, header.bitDepth)\n out[dst + 1] = sampleToByte(rgb[1]!, header.bitDepth)\n out[dst + 2] = sampleToByte(rgb[2]!, header.bitDepth)\n out[dst + 3] = transparentRgb && rgb.every((value, i) => value === transparentRgb[i])\n ? 0\n : 255\n } else if (header.colorType === 3) {\n const index = sample(row, x, 0, 1, header.bitDepth)\n const paletteOffset = index * 3\n if (!palette || paletteOffset + 2 >= palette.length) {\n throw new Error(`indexed PNG pixel references missing palette entry ${index}`)\n }\n out[dst] = palette[paletteOffset]!\n out[dst + 1] = palette[paletteOffset + 1]!\n out[dst + 2] = palette[paletteOffset + 2]!\n out[dst + 3] = transparency?.[index] ?? 255\n } else if (header.colorType === 4) {\n const grey = sampleToByte(sample(row, x, 0, 2, header.bitDepth), header.bitDepth)\n out[dst] = grey\n out[dst + 1] = grey\n out[dst + 2] = grey\n out[dst + 3] = sampleToByte(sample(row, x, 1, 2, header.bitDepth), header.bitDepth)\n } else {\n out[dst] = sampleToByte(sample(row, x, 0, 4, header.bitDepth), header.bitDepth)\n out[dst + 1] = sampleToByte(sample(row, x, 1, 4, header.bitDepth), header.bitDepth)\n out[dst + 2] = sampleToByte(sample(row, x, 2, 4, header.bitDepth), header.bitDepth)\n out[dst + 3] = sampleToByte(sample(row, x, 3, 4, header.bitDepth), header.bitDepth)\n }\n }\n }\n return out\n}\n\nfunction sample(\n row: Buffer,\n x: number,\n channel: number,\n channels: number,\n bitDepth: number,\n): number {\n if (bitDepth === 8) return row[x * channels + channel]!\n if (bitDepth === 16) return row.readUInt16BE((x * channels + channel) * 2)\n const bitOffset = x * bitDepth\n const shift = 8 - bitDepth - (bitOffset % 8)\n return (row[Math.floor(bitOffset / 8)]! >> shift) & ((1 << bitDepth) - 1)\n}\n\nfunction sampleToByte(value: number, bitDepth: number): number {\n if (bitDepth === 8) return value\n if (bitDepth === 16) return Math.round(value / 257)\n return Math.round((value * 255) / ((1 << bitDepth) - 1))\n}\n\nfunction paeth(a: number, b: number, c: number): number {\n const p = a + b - c\n const pa = Math.abs(p - a)\n const pb = Math.abs(p - b)\n const pc = Math.abs(p - c)\n if (pa <= pb && pa <= pc) return a\n return pb <= pc ? b : c\n}\n\nexport interface PaletteEntry {\n r: number\n g: number\n b: number\n /** Share of opaque pixels using this colour, 0-1. */\n weight: number\n}\n\n/**\n * Dominant colours of an image, ignoring transparency.\n *\n * Pixel art uses a small deliberate palette, so exact colour counting works —\n * no clustering needed. Nearly-transparent pixels are excluded because\n * anti-aliased edges would otherwise dominate the histogram of a small sprite.\n */\nexport function extractPalette(png: DecodedPng, topN = 8, alphaThreshold = 128): PaletteEntry[] {\n const counts = new Map<number, number>()\n let opaque = 0\n\n for (let i = 0; i < png.pixels.length; i += 4) {\n const alpha = png.pixels[i + 3]!\n if (alpha < alphaThreshold) continue\n opaque++\n const key = (png.pixels[i]! << 16) | (png.pixels[i + 1]! << 8) | png.pixels[i + 2]!\n counts.set(key, (counts.get(key) ?? 0) + 1)\n }\n if (opaque === 0) return []\n\n return [...counts.entries()]\n .sort((a, b) => b[1] - a[1])\n .slice(0, topN)\n .map(([key, n]) => ({\n r: (key >> 16) & 0xff,\n g: (key >> 8) & 0xff,\n b: key & 0xff,\n weight: n / opaque,\n }))\n}\n\n/** Fraction of pixels that are effectively transparent — a silhouette check. */\nexport function transparencyRatio(png: DecodedPng, alphaThreshold = 128): number {\n let clear = 0\n const total = png.pixels.length / 4\n for (let i = 0; i < png.pixels.length; i += 4) {\n if (png.pixels[i + 3]! < alphaThreshold) clear++\n }\n return total === 0 ? 0 : clear / total\n}\n\n/** CRC-32 as PNG specifies it. Small enough not to warrant a dependency. */\nfunction crc32(buf: Buffer): number {\n let c = ~0\n for (const byte of buf) {\n c ^= byte\n for (let k = 0; k < 8; k++) c = (c >>> 1) ^ (0xedb88320 & -(c & 1))\n }\n return ~c\n}\n\nfunction chunk(type: string, data: Buffer): Buffer {\n const len = Buffer.alloc(4)\n len.writeUInt32BE(data.length)\n const body = Buffer.concat([Buffer.from(type, \"ascii\"), data])\n const crc = Buffer.alloc(4)\n crc.writeUInt32BE(crc32(body) >>> 0)\n return Buffer.concat([len, body, crc])\n}\n\n/**\n * Writes an 8-bit RGB PNG. Used to build the small swatch image that carries a\n * forced palette to the API — not a general encoder.\n */\nexport function encodeRgbPng(width: number, height: number, rgb: Buffer): Buffer {\n if (rgb.length !== width * height * 3) {\n throw new Error(`expected ${width * height * 3} bytes of RGB, got ${rgb.length}`)\n }\n const stride = width * 3\n // Filter byte 0 (none) per scanline.\n const raw = Buffer.alloc((stride + 1) * height)\n for (let y = 0; y < height; y++) {\n raw[y * (stride + 1)] = 0\n rgb.copy(raw, y * (stride + 1) + 1, y * stride, (y + 1) * stride)\n }\n const ihdr = Buffer.alloc(13)\n ihdr.writeUInt32BE(width, 0)\n ihdr.writeUInt32BE(height, 4)\n ihdr[8] = 8 // bit depth\n ihdr[9] = 2 // colour type: RGB\n return Buffer.concat([\n Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),\n chunk(\"IHDR\", ihdr),\n chunk(\"IDAT\", deflateSync(raw)),\n chunk(\"IEND\", Buffer.alloc(0)),\n ])\n}\n\n/**\n * Writes an 8-bit RGBA PNG.\n *\n * Separate from `encodeRgbPng` rather than replacing it: the palette swatch\n * the API accepts is RGB, and sprite sheets must keep their alpha channel —\n * flattening it would fill every sprite's transparent background with black\n * and the sheet would be unusable over anything but that colour.\n */\nexport function encodeRgbaPng(width: number, height: number, rgba: Buffer): Buffer {\n if (rgba.length !== width * height * 4) {\n throw new Error(`expected ${width * height * 4} bytes of RGBA, got ${rgba.length}`)\n }\n const stride = width * 4\n // Filter byte 0 (none) per scanline. Pixel art compresses well enough that\n // the adaptive filters are not worth the complexity here.\n const raw = Buffer.alloc((stride + 1) * height)\n for (let y = 0; y < height; y++) {\n raw[y * (stride + 1)] = 0\n rgba.copy(raw, y * (stride + 1) + 1, y * stride, (y + 1) * stride)\n }\n const ihdr = Buffer.alloc(13)\n ihdr.writeUInt32BE(width, 0)\n ihdr.writeUInt32BE(height, 4)\n ihdr[8] = 8 // bit depth\n ihdr[9] = 6 // colour type: RGBA\n return Buffer.concat([\n Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),\n chunk(\"IHDR\", ihdr),\n chunk(\"IDAT\", deflateSync(raw)),\n chunk(\"IEND\", Buffer.alloc(0)),\n ])\n}\n\n/**\n * Builds the palette swatch the API expects: a block of solid colour per entry.\n *\n * Deliberately chunky rather than one pixel per colour — a 4x1 image was\n * rejected outright with \"cannot identify image file\", while a 64x64 block\n * swatch was accepted.\n */\nexport function paletteSwatch(hexes: string[], size = 64): Buffer {\n const colours = hexes.map(parseHex)\n if (!colours.length) throw new Error(\"palette is empty\")\n const rgb = Buffer.alloc(size * size * 3)\n const band = Math.max(1, Math.floor(size / colours.length))\n for (let y = 0; y < size; y++) {\n for (let x = 0; x < size; x++) {\n const c = colours[Math.min(colours.length - 1, Math.floor(x / band))]!\n const o = (y * size + x) * 3\n rgb[o] = c.r\n rgb[o + 1] = c.g\n rgb[o + 2] = c.b\n }\n }\n return encodeRgbPng(size, size, rgb)\n}\n\nexport function parseHex(hex: string): { r: number; g: number; b: number } {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim())\n if (!m) throw new Error(`invalid hex colour \"${hex}\" — expected #rrggbb`)\n const n = parseInt(m[1]!, 16)\n return { r: (n >> 16) & 0xff, g: (n >> 8) & 0xff, b: n & 0xff }\n}\n","import { decodePng } from \"./png.ts\"\n\nexport const MediaType = {\n PNG: \"image/png\",\n GIF: \"image/gif\",\n} as const\n\nexport type MediaType = (typeof MediaType)[keyof typeof MediaType]\n\nconst PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])\n\nexport function mediaExtension(mediaType: MediaType): \".png\" | \".gif\" {\n return mediaType === MediaType.GIF ? \".gif\" : \".png\"\n}\n\nexport function mediaTypeFromExtension(file: string): MediaType | null {\n const lower = file.toLowerCase()\n if (lower.endsWith(\".png\")) return MediaType.PNG\n if (lower.endsWith(\".gif\")) return MediaType.GIF\n return null\n}\n\nexport function detectMediaType(bytes: Buffer): MediaType | null {\n if (bytes.subarray(0, PNG_SIGNATURE.length).equals(PNG_SIGNATURE)) return MediaType.PNG\n const header = bytes.subarray(0, 6).toString(\"ascii\")\n if (header === \"GIF87a\" || header === \"GIF89a\") return MediaType.GIF\n return null\n}\n\n/** Validate durable provider output before it reaches disk or the recovery cache. */\nexport function validateMedia(bytes: Buffer, expected?: MediaType): MediaType {\n const actual = detectMediaType(bytes)\n if (!actual) throw new Error(`response was not a supported PNG or GIF (${bytes.length} bytes)`)\n if (expected && actual !== expected) {\n throw new Error(`response was ${actual}, expected ${expected}`)\n }\n if (actual === MediaType.PNG) {\n decodePng(bytes)\n } else {\n validateGif(bytes)\n }\n return actual\n}\n\n/** Walk GIF blocks far enough to reject truncated/error-page payloads. */\nfunction validateGif(bytes: Buffer): void {\n if (bytes.length < 14) throw new Error(\"invalid GIF: truncated logical screen descriptor\")\n const width = bytes.readUInt16LE(6)\n const height = bytes.readUInt16LE(8)\n if (!width || !height) throw new Error(\"invalid GIF: zero-sized logical screen\")\n\n const packed = bytes[10]!\n let offset = 13\n if (packed & 0x80) offset += 3 * 2 ** ((packed & 0x07) + 1)\n if (offset > bytes.length) throw new Error(\"invalid GIF: truncated global color table\")\n\n let sawImage = false\n while (offset < bytes.length) {\n const marker = bytes[offset]!\n if (marker === 0x3b) {\n if (!sawImage) throw new Error(\"invalid GIF: contains no image frame\")\n return\n }\n if (marker === 0x2c) {\n if (offset + 10 > bytes.length) throw new Error(\"invalid GIF: truncated image descriptor\")\n const imagePacked = bytes[offset + 9]!\n offset += 10\n if (imagePacked & 0x80) offset += 3 * 2 ** ((imagePacked & 0x07) + 1)\n if (offset >= bytes.length) throw new Error(\"invalid GIF: missing image data\")\n offset++ // LZW minimum code size\n offset = skipSubBlocks(bytes, offset)\n sawImage = true\n continue\n }\n if (marker === 0x21) {\n if (offset + 2 > bytes.length) throw new Error(\"invalid GIF: truncated extension\")\n offset = skipSubBlocks(bytes, offset + 2)\n continue\n }\n throw new Error(`invalid GIF: unexpected block marker 0x${marker.toString(16)}`)\n }\n throw new Error(\"invalid GIF: missing trailer\")\n}\n\nfunction skipSubBlocks(bytes: Buffer, start: number): number {\n let offset = start\n for (;;) {\n if (offset >= bytes.length) throw new Error(\"invalid GIF: truncated data blocks\")\n const size = bytes[offset]!\n offset++\n if (size === 0) return offset\n offset += size\n if (offset > bytes.length) throw new Error(\"invalid GIF: truncated data block\")\n }\n}\n\nexport function cacheFileName(hash: string, mediaType: MediaType = MediaType.PNG): string {\n return `${hash}${mediaExtension(mediaType)}`\n}\n","import { mkdirSync, existsSync, readFileSync, writeFileSync } from \"node:fs\"\nimport { randomUUID } from \"node:crypto\"\nimport os from \"node:os\"\nimport path from \"node:path\"\nimport { PixelLabClient, PixelLabError, clientFromEnv } from \"../client.ts\"\nimport { paletteSwatch } from \"../png.ts\"\nimport {\n candidateCount,\n generationCost,\n type Generator,\n type ResolvedSpec,\n type ResolvedStyleImage,\n} from \"../types.ts\"\nimport type { BalanceInfo, CostEstimate, JobState, PollContext, Provider, RateLimit, RemoteAsset } from \"../provider.ts\"\n\n/**\n * PixelLab, the reference implementation.\n *\n * All PixelLab-specific knowledge lives here: the three generators and their\n * very different pricing, the review/candidate flow, the fact that a map\n * object's job record expires while its image does not, and that pixflux\n * returns bytes inline instead of a job id.\n */\nexport class PixelLabProvider implements Provider {\n readonly id = \"pixellab\"\n\n constructor(private readonly client: PixelLabClient) {}\n\n static fromEnv(): PixelLabProvider {\n return new PixelLabProvider(clientFromEnv())\n }\n\n /** Public storage URLs and the local content cache do not require API auth. */\n static forDownloads(): PixelLabProvider {\n return PixelLabProvider.forOffline()\n }\n\n /** Capability and cost estimation only; makes no network request itself. */\n static forOffline(): PixelLabProvider {\n return new PixelLabProvider(new PixelLabClient(\"download-only\"))\n }\n\n supports(generator: Generator): boolean {\n return (\n generator === \"1dir\" ||\n generator === \"map\" ||\n generator === \"pixflux\" ||\n generator === \"tiles\"\n )\n }\n\n /** PixelLab's own constraints: submissions must be >2s apart, and\n * background jobs in flight are capped by subscription tier (Tier 1=8,\n * Tier 2=10, Tier 3=20) — 8 is the safe floor across every tier. */\n rateLimit(): RateLimit {\n return { spacingMs: 2500, maxInFlight: 8 }\n }\n\n /**\n * Where synchronous pixflux results are parked between `submit` and `fetch`.\n *\n * pixflux returns the PNG inline rather than a job id, but the pipeline is\n * built around submit → poll → fetch running as separate commands. Writing\n * the bytes to a known path keeps that model intact: the \"job id\" is the\n * filename, polling is an existence check, and downloading is a file read.\n */\n private static cacheDir(): string {\n const dir = path.join(os.tmpdir(), \"pixelkiln-pixflux\")\n mkdirSync(dir, { recursive: true })\n return dir\n }\n\n estimate(spec: ResolvedSpec): CostEstimate {\n // `tiles` prices and counts off the whole set, both of which the manifest\n // layer already worked out — see tilesCost / tileVariationCount.\n if (spec.generator === \"tiles\") {\n return { unit: \"generations\", amount: spec.cost, candidates: spec.candidates }\n }\n return {\n unit: \"generations\",\n amount: generationCost(spec.width, spec.height, spec.generator),\n candidates: spec.generator === \"1dir\" ? candidateCount(spec.size) : 1,\n }\n }\n\n validate(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): void {\n if (spec.generator === \"1dir\" && (spec.width < 32 || spec.width > 256)) {\n throw new Error(\"PixelLab 1dir dimensions must be between 32 and 256 pixels\")\n }\n if (\n (spec.generator === \"map\" || spec.generator === \"pixflux\") &&\n (spec.width < 16 || spec.height < 16 || spec.width > 400 || spec.height > 400)\n ) {\n throw new Error(`PixelLab ${spec.generator} dimensions must be between 16 and 400 pixels`)\n }\n if (spec.generator === \"map\") {\n requirePixelLabOption(\"view\", spec.view, [\"low top-down\", \"high top-down\", \"side\"])\n requirePixelLabOption(\"outline\", spec.outline, [\n \"single color outline\", \"selective outline\", \"lineless\",\n ])\n requirePixelLabOption(\"shading\", spec.shading, [\n \"flat shading\", \"basic shading\", \"medium shading\", \"detailed shading\",\n ])\n requirePixelLabOption(\"detail\", spec.detail, [\n \"low detail\", \"medium detail\", \"high detail\",\n ])\n }\n if ((spec.generator === \"map\" || spec.generator === \"pixflux\") && styleImages.length) {\n throw new Error(`PixelLab ${spec.generator} does not support style images`)\n }\n for (const image of styleImages) {\n if (image.width > 256 || image.height > 256) {\n throw new Error(\n `Style image exceeds PixelLab's 256x256 limit (${image.width}x${image.height})`,\n )\n }\n }\n if (spec.tags.length > 20) {\n throw new Error(\n `${spec.styleId}/${spec.assetId} resolves to ${spec.tags.length} tags, ` +\n `but PixelLab allows at most 20`,\n )\n }\n }\n\n async submit(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): Promise<{ jobId: string }> {\n this.validate(spec, styleImages)\n if (spec.generator === \"pixflux\") {\n const swatch = spec.palette.length\n ? paletteSwatch(spec.palette).toString(\"base64\")\n : undefined\n const { png } = await this.client.createImagePixflux({\n description: spec.prompt,\n width: spec.width,\n height: spec.height,\n noBackground: spec.noBackground,\n paletteSwatchBase64: swatch,\n seed: spec.seed,\n })\n const jobId = randomUUID()\n writeFileSync(path.join(PixelLabProvider.cacheDir(), `${jobId}.png`), png)\n return { jobId }\n }\n\n if (spec.generator === \"tiles\") {\n const res = await this.client.createTilesPro({\n description: spec.prompt,\n tileSize: spec.tileSize,\n tileType: spec.tileType,\n tileView: spec.tileView,\n tileFeature: spec.tileFeature,\n outlineMode: spec.outlineMode,\n seed: spec.seed,\n // TilesProStyleImage is flat and wants the reference's real dimensions,\n // unlike 1dir's {type, base64, format} payload.\n styleImages: styleImages.map(({ base64, width, height }) => ({ base64, width, height })),\n })\n return { jobId: res.tile_id }\n }\n\n if (spec.generator === \"1dir\") {\n const res = await this.client.create1Direction({\n description: spec.prompt,\n size: spec.size,\n view: spec.view === \"sidescroller\" ? \"sidescroller\" : \"top-down\",\n styleImages,\n })\n return { jobId: res.object_id }\n }\n const res = await this.client.createMapObject({\n description: spec.prompt,\n width: spec.width,\n height: spec.height,\n view: spec.view,\n outline: spec.outline,\n shading: spec.shading,\n detail: spec.detail,\n seed: spec.seed,\n })\n return { jobId: res.object_id }\n }\n\n async poll(jobId: string, generator: Generator, context?: PollContext): Promise<JobState> {\n if (generator === \"pixflux\") {\n const file = path.join(PixelLabProvider.cacheDir(), `${jobId}.png`)\n if (existsSync(file)) {\n const sourceUrl = `file://${file}`\n return { status: \"ready\", objectId: jobId, sourceUrl, sources: [{ url: sourceUrl }] }\n }\n // The bytes only ever lived here, so a missing file means the temp dir\n // was cleared. Nothing to recover from upstream — say so plainly.\n return {\n status: \"failed\",\n error: \"pixflux result is no longer cached locally; re-run submit for this asset\",\n }\n }\n if (generator === \"map\") return this.pollMap(jobId)\n if (generator === \"tiles\") return this.pollTiles(jobId, Boolean(context?.tileFeature))\n\n const obj = await this.client.getObject(jobId)\n if (obj.status === \"review\") {\n return { status: \"review\", candidateUrls: obj.frame_urls ?? [] }\n }\n if (obj.status === \"completed\") {\n const url = firstUrl(obj.rotation_urls) ?? obj.preview_url ?? null\n return { status: \"ready\", objectId: obj.id, sourceUrl: url, sources: url ? [{ url }] : [] }\n }\n if (obj.status === \"failed\") return { status: \"failed\", error: \"generation failed upstream\" }\n return {\n status: \"processing\",\n progressPercent: obj.progress_percent ?? null,\n etaSeconds: obj.eta_seconds ?? null,\n }\n }\n\n /**\n * Map objects need their own path because the `/map-objects/{id}` record is\n * deleted upstream roughly 8 hours after creation while the image survives in\n * the objects collection. Verified: a March 2026 sprite still resolves from\n * `/objects` four months on, with `/map-objects` returning 404 for the same\n * id. So a 404 here is not evidence the work is lost.\n */\n private async pollMap(jobId: string): Promise<JobState> {\n try {\n const obj = await this.client.getMapObject(jobId)\n if (obj.status === \"completed\" && obj.download_url) {\n return {\n status: \"ready\",\n objectId: jobId,\n sourceUrl: obj.download_url,\n sources: [{ url: obj.download_url }],\n }\n }\n if (obj.status === \"failed\") return { status: \"failed\", error: \"generation failed upstream\" }\n return { status: \"processing\" }\n } catch (err) {\n if (!(err instanceof PixelLabError) || err.status !== 404) throw err\n const survivor = await this.client.getObject(jobId).catch(() => null)\n const url = firstUrl(survivor?.rotation_urls) ?? survivor?.preview_url ?? null\n if (survivor?.status === \"completed\" && url) {\n return { status: \"ready\", objectId: survivor.id, sourceUrl: url, sources: [{ url }] }\n }\n return {\n status: \"failed\",\n error: \"map object record deleted upstream and no surviving image found\",\n }\n }\n }\n\n /**\n * Tiles report progress through the HTTP status: 423 while drawing, 200 with\n * `storage_urls` once finished. There is no `status` field to read and no\n * progress percentage on offer, so \"processing\" here carries no ETA.\n */\n private async pollTiles(tileId: string, connectable: boolean): Promise<JobState> {\n try {\n const set = await this.client.getTilesPro(tileId)\n const tiles = tilesInIndexOrder(set.storage_urls)\n if (!tiles.length) return { status: \"failed\", error: \"tiles job returned no storage urls\" }\n if (!connectable) return { status: \"review\", candidateUrls: tiles.map((tile) => tile.url) }\n return {\n status: \"ready\",\n objectId: tileId,\n sourceUrl: tiles[0]?.url ?? null,\n sources: tiles.map((tile) => ({\n url: tile.url,\n role: `tile-${String(tile.index).padStart(2, \"0\")}`,\n })),\n metadata: {\n tileKind: set.kind,\n ...(set.tile_rules ? { tileRules: set.tile_rules } : {}),\n },\n }\n } catch (err) {\n if (err instanceof PixelLabError && err.status === 423) return { status: \"processing\" }\n throw err\n }\n }\n\n async selectCandidate(\n jobId: string,\n index: number,\n commonTag?: string,\n generator?: Generator,\n ): Promise<{ objectId: string; sourceUrl: string | null }> {\n // A tiles variation is already a finished image at a stable URL — there is\n // no frame to promote and no new account object to create. The identity we\n // record is the job plus the index, which is what actually reproduces it.\n if (generator === \"tiles\") {\n const set = await this.client.getTilesPro(jobId)\n const url = tilesInIndexOrder(set.storage_urls)[index]?.url\n if (!url) throw new Error(`tiles job ${jobId} has no variation at index ${index}`)\n return { objectId: `${jobId}#${index}`, sourceUrl: url }\n }\n const promoted = await this.client.selectFrames(jobId, [index], commonTag)\n const objectId = promoted.created_object_ids?.[0]\n if (!objectId) {\n // The review parent is transient; recording its id would leave a mapping\n // that breaks once the parent is emptied. Fail loudly instead.\n throw new Error(`select-frames returned no created_object_ids for job ${jobId}`)\n }\n const obj = await this.client.getObject(objectId).catch(() => null)\n return { objectId, sourceUrl: firstUrl(obj?.rotation_urls) ?? obj?.preview_url ?? null }\n }\n\n async download(url: string): Promise<Buffer> {\n if (url.startsWith(\"file://\")) return readFileSync(url.slice(\"file://\".length))\n return this.client.download(url)\n }\n\n async balance(): Promise<BalanceInfo> {\n const b = await this.client.balance()\n return { unit: \"generations\", remaining: b.generations, total: b.total, plan: b.plan }\n }\n\n async setTags(objectId: string, tags: string[]): Promise<void> {\n await this.client.setTags(objectId, tags.slice(0, 20))\n }\n\n async *list(): AsyncGenerator<RemoteAsset> {\n for await (const obj of this.client.iterateObjects(100)) {\n yield {\n id: obj.id,\n prompt: obj.prompt ?? \"\",\n width: obj.size.width,\n height: obj.size.height,\n createdAt: obj.created_at,\n previewUrl: obj.preview_url ?? null,\n tags: obj.tags ?? [],\n status: obj.status ?? \"unknown\",\n }\n }\n }\n\n async delete(assetId: string): Promise<void> {\n await this.client.deleteObject(assetId)\n }\n}\n\nfunction requirePixelLabOption(\n name: string,\n value: string | undefined,\n allowed: readonly string[],\n): void {\n if (value != null && !allowed.includes(value)) {\n throw new Error(`PixelLab map ${name} must be one of: ${allowed.join(\", \")}`)\n }\n}\n\n/**\n * `storage_urls` is an object keyed `tile_0`, `tile_1`, ... — JSON object order\n * is not something to rely on, and a connectable set is sliced by index, so\n * sort numerically rather than taking Object.values() as it comes.\n */\nfunction tilesInIndexOrder(urls: Record<string, string>): Array<{ index: number; url: string }> {\n return Object.entries(urls)\n .map(([key, url]) => ({ index: Number(key.replace(/^tile_/, \"\")), url }))\n .filter((tile) => Number.isFinite(tile.index))\n .sort((a, b) => a.index - b.index)\n}\n\nfunction firstUrl(urls: Record<string, string | null> | null | undefined): string | null {\n if (!urls) return null\n return Object.values(urls).find((u): u is string => typeof u === \"string\") ?? null\n}\n","import type { ResolvedStyleImage } from \"./types.ts\"\nimport { z } from \"zod\"\n\n/**\n * PixelLab REST client.\n *\n * Verified against https://api.pixellab.ai/v2/openapi.json. Every endpoint used\n * here was exercised against a live account before being written, so the shapes\n * are observed rather than assumed.\n *\n * Notably this needs no LLM and no MCP client — it is ordinary HTTP.\n */\n\nconst BASE = process.env.PIXELLAB_API_BASE ?? \"https://api.pixellab.ai/v2\"\n\nexport const MAX_RETRIES = 4\nexport const MAX_DOWNLOAD_BYTES = 64 * 1024 * 1024\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))\n\nexport function shouldRetry(status: number): boolean {\n return status === 429 || status === 408 || status >= 500\n}\n\n/** Exponential backoff with jitter, so parallel workers don't retry in lockstep. */\nexport function backoffMs(attempt: number): number {\n const base = Math.min(1000 * 2 ** attempt, 16_000)\n return base + Math.floor(Math.random() * 400)\n}\n\n/** Supports both Retry-After forms: seconds and an HTTP date. */\nexport function retryAfterMs(value: string | null, now = Date.now()): number | null {\n if (!value) return null\n const seconds = Number(value)\n if (Number.isFinite(seconds) && seconds >= 0) return seconds * 1000\n const date = Date.parse(value)\n if (!Number.isFinite(date)) return null\n return Math.max(0, date - now)\n}\n\nexport interface Balance {\n usd: number\n generations: number\n total: number\n plan: string\n}\n\nexport interface PixelLabObject {\n id: string\n name: string | null\n prompt: string\n size: { width: number; height: number }\n directions: number\n created_at: string\n view: string | null\n preview_url?: string | null\n rotation_urls?: Record<string, string | null> | null\n /** Populated only while status === \"review\". Index order is what select-frames expects. */\n frame_urls?: string[] | null\n tags: string[]\n status: string | null\n progress_percent?: number | null\n eta_seconds?: number | null\n}\n\n/**\n * A tiles-pro job. Unlike an object or a map object there is no `status`\n * field: GET /tiles-pro/{id} answers 423 while the set is still drawing and\n * 200 with `storage_urls` once it is done, so the HTTP code IS the status.\n */\nexport interface TilesPro {\n /** Keyed `tile_0`, `tile_1`, ... Index order is load-bearing for a\n * connectable set (`tile_feature`), where a consumer slices by index. */\n storage_urls: Record<string, string>\n kind: string | null\n tile_rules?: Record<string, unknown> | null\n}\n\nexport interface MapObject {\n object_id: string\n status: string\n description: string | null\n width: number | null\n height: number | null\n download_url: string | null\n}\n\nconst BalanceResponseSchema = z\n .object({\n credits: z.object({ usd: z.number() }).passthrough(),\n subscription: z\n .object({\n generations: z.number(),\n total: z.number(),\n plan: z.string().nullable().optional(),\n })\n .passthrough(),\n })\n .passthrough()\n\nconst ObjectSubmitSchema = z\n .object({\n background_job_id: z.string().min(1),\n object_id: z.string().min(1),\n status: z.string().default(\"queued\"),\n n_frames: z.number().int().min(0),\n })\n .passthrough()\nconst MapSubmitSchema = z\n .object({\n background_job_id: z.string().min(1),\n object_id: z.string().min(1),\n status: z.string().default(\"processing\"),\n })\n .passthrough()\nconst TilesSubmitSchema = z\n .object({\n tile_id: z.string().min(1),\n background_job_id: z.string().min(1),\n status: z.literal(\"processing\").default(\"processing\"),\n })\n .passthrough()\nconst TilesProSchema = z\n .object({\n storage_urls: z.record(z.string()),\n kind: z.string().nullable().default(null),\n tile_rules: z.record(z.unknown()).nullable().optional(),\n })\n .passthrough()\nconst PixelLabObjectSchema = z\n .object({\n id: z.string().min(1),\n name: z.string().nullable().default(null),\n prompt: z.string().default(\"\"),\n size: z.object({ width: z.number().int().positive(), height: z.number().int().positive() }),\n directions: z.number().default(0),\n created_at: z.string(),\n view: z.string().nullable().default(null),\n preview_url: z.string().nullable().optional(),\n rotation_urls: z.record(z.string().nullable()).nullable().optional(),\n frame_urls: z.array(z.string()).nullable().optional(),\n tags: z.array(z.string()).default([]),\n status: z.string().nullable().default(null),\n progress_percent: z.number().nullable().optional(),\n eta_seconds: z.number().nullable().optional(),\n })\n .passthrough()\nconst MapObjectSchema = z\n .object({\n object_id: z.string().min(1),\n status: z.string(),\n description: z.string().nullable().default(null),\n width: z.number().nullable().default(null),\n height: z.number().nullable().default(null),\n download_url: z.string().nullable().default(null),\n })\n .passthrough()\nconst ObjectListSchema = z\n .object({ objects: z.array(PixelLabObjectSchema), total: z.number().int().min(0) })\n .passthrough()\nconst PixfluxResponseSchema = z\n .object({ image: z.object({ base64: z.string().min(1) }).passthrough(), usage: z.unknown().optional() })\n .passthrough()\nconst SelectFramesSchema = z.object({ created_object_ids: z.array(z.string()) }).passthrough()\n\nfunction validateResponse<S extends z.ZodTypeAny>(\n schema: S,\n raw: unknown,\n operation: string,\n): z.output<S> {\n const parsed = schema.safeParse(raw)\n if (parsed.success) return parsed.data\n const issues = parsed.error.issues\n .slice(0, 4)\n .map((i) => `${i.path.join(\".\") || \"response\"}: ${i.message}`)\n .join(\"; \")\n throw new Error(`Invalid PixelLab response for ${operation}: ${issues}`)\n}\n\nexport class PixelLabError extends Error {\n constructor(\n message: string,\n readonly status: number,\n readonly body: string,\n ) {\n super(message)\n this.name = \"PixelLabError\"\n }\n}\n\nexport class PixelLabClient {\n constructor(\n private readonly apiKey: string,\n private readonly timeoutMs = 120_000,\n ) {\n if (!apiKey) throw new Error(\"PIXELLAB_API_KEY is required\")\n }\n\n /**\n * Retries only what is safe to retry: transport failures, 429, and 5xx.\n * A 4xx other than 429 is a bad request and retrying it just wastes time.\n *\n * POSTs that create objects are included, which is a deliberate trade: the\n * failure mode of not retrying (a dropped asset in a 65-item run) is more\n * common than the failure mode of retrying (a duplicate object), and a\n * duplicate is visible and free to delete whereas a silent gap is neither.\n */\n private async request<T>(path: string, init?: RequestInit, attempt = 0): Promise<T> {\n const auth = this.apiKey.startsWith(\"Bearer \") ? this.apiKey : `Bearer ${this.apiKey}`\n let res: Response\n try {\n res = await fetch(`${BASE}${path}`, {\n ...init,\n signal: init?.signal ?? AbortSignal.timeout(this.timeoutMs),\n headers: {\n Authorization: auth,\n \"Content-Type\": \"application/json\",\n ...(init?.headers ?? {}),\n },\n })\n } catch (err) {\n if (attempt < MAX_RETRIES) {\n await sleep(backoffMs(attempt))\n return this.request<T>(path, init, attempt + 1)\n }\n throw err\n }\n\n if (!res.ok && shouldRetry(res.status) && attempt < MAX_RETRIES) {\n // Honour Retry-After when the server sends one; it knows better than we do.\n const waitMs = retryAfterMs(res.headers.get(\"retry-after\")) ?? backoffMs(attempt)\n await sleep(waitMs)\n return this.request<T>(path, init, attempt + 1)\n }\n\n const text = await res.text()\n if (!res.ok) {\n throw new PixelLabError(`${init?.method ?? \"GET\"} ${path} → ${res.status}`, res.status, text)\n }\n if (!text) return {} as T\n try {\n return JSON.parse(text) as T\n } catch {\n throw new Error(`${init?.method ?? \"GET\"} ${path} returned invalid JSON`)\n }\n }\n\n async balance(): Promise<Balance> {\n const raw = validateResponse(BalanceResponseSchema, await this.request<unknown>(\"/balance\"), \"balance\")\n return {\n usd: raw.credits?.usd ?? 0,\n generations: raw.subscription?.generations ?? 0,\n total: raw.subscription?.total ?? 0,\n plan: raw.subscription?.plan ?? \"unknown\",\n }\n }\n\n /**\n * Square objects that persist indefinitely.\n *\n * `size` and `styleImages` are mutually exclusive at the API level: when style\n * images are supplied the largest one dictates the output size. So style\n * references must already be at the target resolution — a 128px reference\n * silently produces 128px output and a different candidate count.\n */\n async create1Direction(args: {\n description: string\n size?: number\n view?: string\n styleImages?: ResolvedStyleImage[]\n itemDescriptions?: string[]\n }): Promise<{ object_id: string; status: string; n_frames: number }> {\n const body: Record<string, unknown> = { description: args.description }\n if (args.styleImages?.length) {\n body.style_images = args.styleImages.map(({ base64, format }) => ({\n type: \"base64\",\n base64,\n format,\n }))\n } else if (args.size != null) {\n body.size = args.size\n }\n if (args.view) body.view = args.view\n if (args.itemDescriptions?.length) body.item_descriptions = args.itemDescriptions\n const raw = await this.request<unknown>(\"/create-1-direction-object\", {\n method: \"POST\",\n body: JSON.stringify(body),\n })\n const parsed = validateResponse(ObjectSubmitSchema, raw, \"create-1-direction-object\")\n return parsed\n }\n\n /**\n * Arbitrary width x height. Returns a single result — no selection step.\n *\n * These AUTO-DELETE AFTER 8 HOURS, so `fetch` must run in the same session as\n * `submit`. The pipeline warns when a map-object entry is older than that.\n */\n async createMapObject(args: {\n description: string\n width: number\n height: number\n view?: string\n outline?: string\n shading?: string\n detail?: string\n seed?: number\n }): Promise<{ object_id: string; status: string }> {\n const body: Record<string, unknown> = {\n description: args.description,\n image_size: { width: args.width, height: args.height },\n }\n if (args.view) body.view = args.view\n if (args.outline) body.outline = args.outline\n if (args.shading) body.shading = args.shading\n if (args.detail) body.detail = args.detail\n if (args.seed != null) body.seed = args.seed\n return validateResponse(\n MapSubmitSchema,\n await this.request<unknown>(\"/map-objects\", { method: \"POST\", body: JSON.stringify(body) }),\n \"create map object\",\n )\n }\n\n /**\n * Draws a whole tile set in one call — many variations, or a connectable\n * set when `tileFeature` is given.\n *\n * `styleImages` here is NOT the shape `create-1-direction-object` uses.\n * TilesProStyleImage is flat — `{base64, width, height}`, all three\n * required — where 1dir wants `{type, base64, format}`. Confirmed against\n * the OpenAPI schema; sending 1dir's shape is rejected as an extra field.\n *\n * Passing style images also makes the API ignore `tileType` and `tileView`\n * and copy the reference's tile geometry instead.\n */\n async createTilesPro(args: {\n description: string\n tileSize?: number\n tileType?: string\n tileView?: string\n tileFeature?: string\n outlineMode?: string\n seed?: number\n styleImages?: { base64: string; width: number; height: number }[]\n }): Promise<{ tile_id: string; background_job_id: string; status: string }> {\n const body: Record<string, unknown> = { description: args.description }\n if (args.tileSize != null) body.tile_size = args.tileSize\n if (args.tileType) body.tile_type = args.tileType\n if (args.tileView) body.tile_view = args.tileView\n if (args.tileFeature) body.tile_feature = args.tileFeature\n if (args.outlineMode) body.outline_mode = args.outlineMode\n if (args.seed != null) body.seed = args.seed\n if (args.styleImages?.length) body.style_images = args.styleImages\n return validateResponse(\n TilesSubmitSchema,\n await this.request<unknown>(\"/create-tiles-pro\", { method: \"POST\", body: JSON.stringify(body) }),\n \"create tiles\",\n )\n }\n\n /** Throws PixelLabError(423) while the set is still drawing — see TilesPro. */\n async getTilesPro(tileId: string): Promise<TilesPro> {\n return validateResponse(\n TilesProSchema,\n await this.request<unknown>(`/tiles-pro/${tileId}`),\n \"get tiles\",\n )\n }\n\n /**\n * Synchronous single-image generation. Returns the PNG inline rather than a\n * job id, and is the only endpoint that honours a forced palette —\n * `color_image` on /map-objects returns a 500 whatever the payload shape.\n */\n async createImagePixflux(args: {\n description: string\n width: number\n height: number\n noBackground?: boolean\n paletteSwatchBase64?: string\n seed?: number\n }): Promise<{ png: Buffer; usage: unknown }> {\n const body: Record<string, unknown> = {\n description: args.description,\n image_size: { width: args.width, height: args.height },\n no_background: args.noBackground ?? true,\n }\n if (args.paletteSwatchBase64) {\n body.color_image = { type: \"base64\", base64: args.paletteSwatchBase64, format: \"png\" }\n }\n if (args.seed != null) body.seed = args.seed\n\n const res = validateResponse(\n PixfluxResponseSchema,\n await this.request<unknown>(\"/create-image-pixflux\", {\n method: \"POST\",\n body: JSON.stringify(body),\n }),\n \"create pixflux image\",\n )\n const b64 = res.image.base64\n return { png: Buffer.from(b64, \"base64\"), usage: res.usage }\n }\n\n async getObject(objectId: string): Promise<PixelLabObject> {\n return validateResponse(\n PixelLabObjectSchema,\n await this.request<unknown>(`/objects/${objectId}`),\n \"get object\",\n )\n }\n\n async getMapObject(objectId: string): Promise<MapObject> {\n return validateResponse(\n MapObjectSchema,\n await this.request<unknown>(`/map-objects/${objectId}`),\n \"get map object\",\n )\n }\n\n async listObjects(limit = 50, offset = 0): Promise<{ objects: PixelLabObject[]; total: number }> {\n return validateResponse(\n ObjectListSchema,\n await this.request<unknown>(`/objects?limit=${limit}&offset=${offset}`),\n \"list objects\",\n )\n }\n\n /** Walks the whole account. Used by `adopt` to reconcile orphaned objects. */\n async *iterateObjects(pageSize = 100): AsyncGenerator<PixelLabObject> {\n let offset = 0\n for (;;) {\n const page = await this.listObjects(pageSize, offset)\n for (const obj of page.objects) yield obj\n offset += page.objects.length\n if (page.objects.length === 0 || offset >= page.total) return\n }\n }\n\n /**\n * Promotes chosen candidates to standalone objects, each with its own id.\n * The review parent survives until nothing is left in it, so the returned\n * `created_object_ids` — not the parent id — is what should be recorded.\n */\n async selectFrames(\n objectId: string,\n indices: number[],\n commonTag?: string,\n ): Promise<{ created_object_ids?: string[] }> {\n const raw = await this.request<unknown>(`/objects/${objectId}/select-frames`, {\n method: \"POST\",\n body: JSON.stringify(commonTag ? { indices, common_tag: commonTag } : { indices }),\n })\n return validateResponse(SelectFramesSchema, raw, \"select frames\")\n }\n\n /** Irreversible. Only reached via `purge`, behind an explicit confirmation. */\n deleteObject(objectId: string): Promise<unknown> {\n return this.request(`/objects/${objectId}`, { method: \"DELETE\" })\n }\n\n dismissReview(objectId: string): Promise<unknown> {\n return this.request(`/objects/${objectId}/dismiss-review`, { method: \"POST\" })\n }\n\n /** Free and synchronous. Replaces the full tag set — include tags you want to keep. */\n setTags(objectId: string, tags: string[]): Promise<unknown> {\n return this.request(`/objects/${objectId}/tags`, { method: \"PATCH\", body: JSON.stringify({ tags }) })\n }\n\n /** Storage URLs are public; no auth header, and sending one can break the CDN request. */\n async download(url: string): Promise<Buffer> {\n const res = await fetch(url, { signal: AbortSignal.timeout(this.timeoutMs) })\n if (!res.ok) throw new PixelLabError(`download ${url} → ${res.status}`, res.status, \"\")\n const declared = Number(res.headers.get(\"content-length\"))\n if (Number.isFinite(declared) && declared > MAX_DOWNLOAD_BYTES) {\n throw new Error(`download ${url} exceeds the ${MAX_DOWNLOAD_BYTES}-byte safety limit`)\n }\n const buf = Buffer.from(await res.arrayBuffer())\n if (buf.length > MAX_DOWNLOAD_BYTES) {\n throw new Error(`download ${url} exceeds the ${MAX_DOWNLOAD_BYTES}-byte safety limit`)\n }\n return buf\n }\n}\n\nexport function clientFromEnv(): PixelLabClient {\n const key = process.env.PIXELLAB_API_KEY\n if (!key) {\n throw new Error(\n \"PIXELLAB_API_KEY is not set.\\n\" +\n \"Looked in the environment, and in .env.local / .env beside the manifest and in the current directory.\",\n )\n }\n return new PixelLabClient(key)\n}\n","import { z } from \"zod\"\n\nconst MediaTypeSchema = z.enum([\"image/png\", \"image/gif\"])\n\n/**\n * Which provider capability produces the asset. The choice is mostly about cost,\n * and the gap is enormous — all figures measured against a live account.\n *\n * map POST /map-objects — THE DEFAULT.\n * A flat 1 generation at any size. Purpose-built for standalone props\n * with transparent backgrounds, which is what an icon or a prop is.\n * Arbitrary width x height. Returns exactly one result, so there is no\n * selection step: if you dislike it, re-roll for 1 more.\n *\n * 1dir POST /create-1-direction-object — 20-40 generations.\n * The single-facing sibling of create-8-direction-object, meant for\n * objects you may later want rotations or animations of. Square only.\n * Returns 4-64 candidates for its one fixed price, which is genuinely\n * useful when you want to compare options side by side — but at 40x the\n * cost of a map object, re-rolling a map object forty times is the same\n * money. Reach for this when you need rotations, or when the extra\n * rendering detail is worth 40x.\n *\n * Rule of thumb: if the asset is a standalone image and you are not going to\n * animate or rotate it, `map` is the right call. Generating 65 icons costs 65\n * generations that way and 2,600 the other.\n *\n * Not yet implemented, but measured and worth knowing (see README):\n * POST /create-image-pixflux also costs 1 generation, returns the image\n * INLINE with no polling, and accepts `color_image` — a forced palette that\n * constrains output to exact hex values. Verified: a four-colour Game Boy\n * swatch produced output containing precisely those four colours. The same\n * parameter on /map-objects returns a 500, so the palette lock is\n * pixflux-only. Its rendering is flatter than 1dir's.\n */\nexport const GeneratorSchema = z.enum([\"1dir\", \"map\", \"pixflux\", \"tiles\", \"animation\", \"frames\"])\nexport type Generator = z.infer<typeof GeneratorSchema>\n\nexport const GridConfidenceSchema = z.enum([\"low\", \"medium\", \"high\"])\nexport type GridConfidence = z.infer<typeof GridConfidenceSchema>\n\nexport const RevisionModeSchema = z.enum([\"image-to-image\", \"inpaint\", \"outpaint\"])\nexport type RevisionMode = z.infer<typeof RevisionModeSchema>\n\n/** A decoded style reference ready for a provider-specific request body. */\nexport interface ResolvedStyleImage {\n base64: string\n width: number\n height: number\n format: \"png\" | \"jpeg\"\n}\n\n/**\n * `tiles` is the odd one out: the unit of work is a *set*, not a sprite.\n *\n * POST /create-tiles-pro draws tile shape outlines and fills them, returning\n * many variations from one call. Independent variations land in the same\n * review-then-pick flow as `1dir`; connectable features are structural sets\n * and every returned storage URL is retained. There is no select-frames step\n * to run for either form.\n *\n * Two properties make it worth a generator of its own rather than a flag on\n * `1dir`:\n *\n * - **Style mode overrides geometry.** Passing `styleImages` makes the API\n * copy tile shape and dimensions from the reference and ignore\n * `tileType`/`tileView` entirely. For an existing tileset that is the\n * point: it is the only way to land new art on the same ground plane as\n * the tiles already in the sheet.\n * - **`tileFeature` generates connectable sets.** `\"tileset\"` returns a\n * 16-tile Wang corner set for a terrain transition, `\"roads\"` an\n * 18-configuration path set. Those are structural outputs; a consumer\n * slices them by index, not by eye.\n */\n\n/**\n * Variations a `tiles` call returns. The API derives this from the tile size\n * and how many numbered descriptions the prompt contains; observed at 4 per\n * numbered description for 32px isometric tiles. Clamped so a prompt with no\n * numbering still reports at least one.\n */\nexport function tileVariationCount(descriptions: number): number {\n return Math.max(1, descriptions) * 4\n}\n\n/** Known structural output counts for connectable tile features. */\nexport function tileFeatureOutputCount(feature: string | undefined): number | null {\n if (feature === \"roads\") return 18\n if (feature === \"tileset\") return 16\n // PixelLab does not document a stable count for the building kit. Its\n // returned storage URLs remain authoritative at download time.\n return null\n}\n\n/**\n * Numbered items in a `tiles` prompt. The endpoint documents `\"1). grass\n * 2). dirt\"` as the way to control what comes back, and returns a group of\n * variations per number.\n */\nexport function countNumberedDescriptions(prompt: string): number {\n return (prompt.match(/\\d+\\s*\\)\\s*\\./g) ?? []).length\n}\n\n/** Candidate frames returned per call, derived from size. Extra candidates are free. */\nexport function candidateCount(size: number): number {\n if (size <= 42) return 64\n if (size <= 85) return 16\n if (size <= 170) return 4\n return 1\n}\n\n/**\n * Generation cost per call. Measured against a live account, not inferred.\n *\n * The two generators are priced completely differently, and the gap is wide\n * enough to change which one you should reach for:\n *\n * map FLAT 1 generation, any size. Verified: a 32x36 and a 64x96 map object\n * each cost exactly 1 (balance 4751 → 4750 → 4749). Single result.\n *\n * 1dir 20-40 by canvas tier (1K=20, 2K=25, 4K=40), returning 4-64\n * candidates for that one price.\n *\n * tiles 20-40 on the same canvas tiers as `1dir`, but the canvas is picked\n * from tile size x variation count rather than a single sprite, so a\n * small tile in a large set can still reach the top tier. Reported by\n * the API at submit time; estimated here from the widest canvas the\n * request can produce, which is the honest direction to be wrong in\n * for a `--budget` check.\n *\n * So `1dir` buys candidate variety at 20-40x the price, and `map` buys\n * arbitrary (non-square) dimensions nearly free. For a single-result asset,\n * forty re-rolls of a map object cost the same as one 1dir call.\n */\nexport function generationCost(\n width: number,\n height: number,\n generator: Generator = \"map\",\n): number {\n if (generator === \"map\" || generator === \"pixflux\") return 1\n const px = width * height\n if (px <= 1024) return 20\n if (px <= 2048) return 25\n return 40\n}\n\n/**\n * Cost of one `tiles` call. Same canvas tiers as `1dir`, but the canvas is the\n * sheet the API lays the variations out on, not one tile — so tile size alone\n * under-reads it badly (a 32px tile is 1024px on its own and would always\n * price at the floor).\n *\n * Estimated from tileSize^2 x variations, which is the area actually drawn.\n * `plan` prints this before anything is spent and `--budget` refuses on it, so\n * over-reading is the safe direction: a call that comes in cheaper than\n * budgeted is a pleasant surprise, one that comes in dearer is an overspend.\n */\nexport function tilesCost(tileSize: number, variations: number): number {\n const px = tileSize * tileSize * Math.max(1, variations)\n if (px <= 1024) return 20\n if (px <= 2048) return 25\n return 40\n}\n\nconst StyleImageSchema = z.object({\n /** Path to a PNG/JPEG, relative to the manifest; the active provider validates limits. */\n path: z.string(),\n})\n\nconst HexColorSchema = z.string().regex(/^#?[0-9a-f]{6}$/i, \"expected a six-digit hex colour\")\n\n/** Required derived-art policy for one style's single-image outputs. */\nconst QualityProfileObjectSchema = z\n .object({\n /** Output root for approved refined art, relative to the manifest. */\n outDir: z.string().min(1),\n /** Closed final palette applied after native-grid recovery, without dithering. */\n palette: z.array(HexColorSchema).min(2).max(256),\n /** Minimum Pixel Art Fixer detector confidence accepted by the mechanical gate. */\n minGridConfidence: GridConfidenceSchema.default(\"high\"),\n /** Optional alpha requirement for isolated assets. */\n minTransparency: z.number().min(0).max(1).optional(),\n /** Pixel Art Fixer revision written into the quality record. */\n fixerRevision: z.string().min(1).optional(),\n /** Python executable containing Pixel Art Fixer, relative to the manifest unless absolute. */\n fixerPython: z.string().min(1).optional(),\n /** Playback rate recorded for an ordered frame set. */\n fps: z.number().int().min(1).max(60).optional(),\n })\n .strict()\n\nexport const QualityProfileSchema = QualityProfileObjectSchema\n .refine(\n (profile) =>\n new Set(profile.palette.map((color) => color.replace(/^#/, \"\").toLowerCase())).size ===\n profile.palette.length,\n { message: \"quality palette colors must be unique\", path: [\"palette\"] },\n )\n\nexport type QualityProfile = z.infer<typeof QualityProfileSchema>\n\nexport interface ResolvedQualityProfile {\n outFile: string\n palette: string[]\n minGridConfidence: GridConfidence\n minTransparency?: number\n fixerRevision?: string\n /** Absolute local executable path resolved from the manifest. */\n fixerPython?: string\n fps?: number\n}\n\n/** A provider generation whose visual starting point is another manifest asset. */\nexport const RevisionSchema = z\n .object({\n /** What kind of controlled change the provider workflow performs. */\n mode: RevisionModeSchema,\n /** Parent asset id in the same style. */\n from: z.string().min(1),\n /** Manifest-relative black/white PNG. Required only for masked inpainting. */\n mask: z.string().min(1).optional(),\n /** Provider-neutral edit strength. The active adapter must bind it explicitly. */\n strength: z.number().min(0).max(1).optional(),\n })\n .strict()\n .superRefine((revision, context) => {\n if (revision.mode === \"inpaint\" && !revision.mask) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"inpaint revisions require a mask\",\n path: [\"mask\"],\n })\n }\n if (revision.mode !== \"inpaint\" && revision.mask) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n message: `${revision.mode} revisions do not accept a mask`,\n path: [\"mask\"],\n })\n }\n })\n\nexport type Revision = z.infer<typeof RevisionSchema>\n\n/** Resolved immutable inputs supplied to a revision-capable provider. */\nexport interface ResolvedRevision {\n mode: RevisionMode\n sourceAssetId: string\n /** Absolute path selected from the parent asset's approved/final output. */\n sourceFile: string\n /** Null keeps planning possible while the parent is not ready. */\n sourceSha256: string | null\n sourceWidth: number | null\n sourceHeight: number | null\n sourceFormat: \"png\" | \"jpeg\" | null\n /** Full parent intent used to prove the dependency is current before spending. */\n sourceSpec: ResolvedSpec\n maskFile?: string\n maskSha256?: string | null\n maskWidth?: number | null\n maskHeight?: number | null\n maskFormat?: \"png\" | \"jpeg\" | null\n strength?: number\n}\n\nconst StyleObjectSchema = z\n .object({\n /** Generation backend for this style. Omit to inherit the manifest default. */\n provider: z.string().min(1).optional(),\n // `map` is the default because it is 20-40x cheaper and correct for any\n // asset that is not going to be rotated or animated.\n generator: GeneratorSchema.default(\"map\"),\n /** Square edge length. The active provider owns its exact limit. */\n size: z.number().int().min(16).max(8192).optional(),\n view: z.string().optional(),\n /** Appended to every asset prompt in this style. Where the look is defined. */\n promptSuffix: z.string().default(\"\"),\n /** Prepended to every asset prompt in this style. */\n promptPrefix: z.string().default(\"\"),\n /** Style reference images. */\n styleImages: z.array(StyleImageSchema).default([]),\n /** Output root for this style, relative to the manifest. */\n outDir: z.string(),\n /** `map` generator only. */\n outline: z.string().optional(),\n shading: z.string().optional(),\n detail: z.string().optional(),\n /**\n * `tiles` generator only. Edge length of one tile, 16-256.\n *\n * Ignored when `styleImages` is set — style mode takes the tile's shape\n * and dimensions from the reference image, which is the whole reason to\n * use it against an existing sheet.\n */\n tileSize: z.number().int().min(16).max(256).optional(),\n /** `tiles` generator only. Defaults to the API's `isometric`. */\n tileType: z\n .enum([\"hex\", \"hex_pointy\", \"isometric\", \"oblique\", \"octagon\", \"square_topdown\"])\n .optional(),\n /** `tiles` generator only. Defaults to the API's `low top-down`. */\n tileView: z.enum([\"top-down\", \"high top-down\", \"low top-down\", \"side\"]).optional(),\n /**\n * `tiles` generator only. Asks for a connectable set instead of\n * independent variations:\n *\n * roads 18-configuration path set\n * tileset 16-tile Wang corner set for a terrain transition — describe\n * the asset as the transition itself (\"fairway grass to rough\n * meadow\"), not as one terrain\n * building floor/wall/doorway construction kit\n *\n * A consumer slices these by index, so the order the API returns them in\n * is load-bearing; do not sort a connectable set by anything else.\n */\n tileFeature: z.enum([\"roads\", \"tileset\", \"building\"]).optional(),\n /**\n * `tiles` generator only. How tile edges are drawn.\n *\n * The API default is `outline`, which draws a dark border around every\n * tile. That is right for tiles meant to read as discrete objects and\n * wrong for ground: laid on a grid, the per-tile borders turn a continuous\n * surface into visible quilting, with a dark seam at every cell edge.\n * `segmentation` omits them and the same set tiles seamlessly.\n *\n * Measured on a fairway-to-rough terrain set — the difference decided\n * whether the art was usable at all, so it is worth setting deliberately\n * rather than inheriting.\n */\n outlineMode: z.enum([\"outline\", \"segmentation\"]).optional(),\n /**\n * `pixflux` only. Whether to strip the generated background.\n *\n * Defaults to true, which is right for the sprites this tool was built\n * for — a prop or an icon wants to sit on whatever is behind it. It is\n * wrong for anything that IS a scene: a cover banner, a splash, a\n * backdrop. The API's own default is false; forcing it true unconditionally\n * meant a full-bleed image came back as a small subject floating in a\n * mostly-empty frame, and prose asking for an \"opaque background\" does not\n * override it.\n */\n noBackground: z.boolean().default(true),\n /** Fixed seed for reproducibility where the endpoint supports it. */\n seed: z.number().int().optional(),\n /**\n * Forced palette, as `#rrggbb` values. `pixflux` only.\n *\n * Unlike prose, this is a hard constraint — the API is handed a swatch\n * image and the output is limited to those colours. Verified: a four-colour\n * Game Boy palette produced output containing exactly those four values.\n * Prose asking for the same thing does not reliably hold, which is why the\n * map-generated monochrome sets came back with a yellow star and a brown\n * chocolate bar.\n */\n palette: z\n .array(HexColorSchema)\n .default([]),\n /** Fail-closed native-grid, palette, and human-approval policy for derived art. */\n quality: QualityProfileSchema.optional(),\n /**\n * Composites this style's assets into declared cells of a sheet, rather\n * than letting `pack` derive a layout. Use it when the atlas coordinates\n * are already load-bearing somewhere else — a tile engine naming tiles by\n * cell, or saved data storing cell indices — since `pack`'s id-sorted grid\n * moves every position when an asset is added or renamed.\n *\n * Assets in a mounted style declare their own `cell`; ones that do not are\n * left out of the sheet.\n */\n mount: z\n .object({\n /**\n * Existing sheet to composite into, relative to the manifest. Every\n * pixel outside a declared cell survives byte-for-byte, so a\n * hand-authored sheet can be part generated and part drawn. Omit to\n * start from transparent.\n */\n base: z.string().optional(),\n cellWidth: z.number().int().positive(),\n cellHeight: z.number().int().positive(),\n /** Where the composited sheet is written, relative to the manifest. */\n out: z.string(),\n })\n .strict()\n .optional(),\n /** Tags applied to every object generated in this style, for server-side filtering. */\n tags: z.array(z.string()).default([]),\n /** Adapter-owned settings, keyed by provider id. */\n providerOptions: z.record(z.record(z.unknown())).default({}),\n })\n .strict()\n\nexport const StyleSchema = StyleObjectSchema\n /**\n * The API rejects a connectable set combined with style tiles:\n * \"Connectable features (roads/tileset/building) cannot be combined with\n * style tiles\". Catching it here means `plan` reports it for free rather\n * than a `submit` discovering it after the run has started — and the two\n * are individually the best reasons to use this generator, so reaching for\n * both at once is an easy mistake to make.\n */\n .refine((s) => !(s.tileFeature && s.styleImages.length), {\n message:\n \"tileFeature and styleImages cannot be combined — a connectable set \" +\n \"derives its own tile geometry, so remove one or the other\",\n path: [\"tileFeature\"],\n })\n .superRefine((style, ctx) => {\n if (style.quality && (style.generator === \"tiles\" || style.generator === \"animation\")) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"quality profiles currently support single-image generators only\",\n path: [\"quality\"],\n })\n }\n })\n\n/**\n * Hand-authored child style before inheritance is resolved. Defaults must not\n * run here: an omitted value means \"inherit\", not \"reset to the default\".\n */\nexport const InheritedStyleSchema = StyleObjectSchema.partial()\n .extend({\n extends: z.string().min(1),\n /** Children own their destination; sharing a parent's output is never implicit. */\n outDir: z.string(),\n /** A child may override only part of the inherited final-art policy. */\n quality: QualityProfileObjectSchema.partial().optional(),\n })\n .strict()\n\nexport const StyleInputSchema = z.union([StyleSchema, InheritedStyleSchema])\nexport type StyleInput = z.infer<typeof StyleInputSchema>\n\nexport const AssetSchema = z\n .object({\n /** The subject. Style wrapping comes from the style's prefix/suffix. */\n prompt: z.string(),\n /** Subdirectory under the style's outDir. Optional. */\n category: z.string().optional(),\n /** Overrides the style default. `map` generator only. */\n width: z.number().int().min(16).max(8192).optional(),\n height: z.number().int().min(16).max(8192).optional(),\n /** Overrides the style default. `1dir` generator only. */\n size: z.number().int().min(32).max(256).optional(),\n /** Explicit output path relative to outDir. Media-aware providers may replace its extension. */\n file: z.string().optional(),\n /**\n * Grid cell this asset owns in a mounted style, as [column, row].\n *\n * Declared rather than derived, which is the point of `mount`: the\n * coordinate is a contract with whatever already reads the sheet, so it\n * must not move when the asset set changes. Assets without one are left\n * out of the mounted sheet.\n */\n cell: z.tuple([z.number().int().min(0), z.number().int().min(0)]).optional(),\n /**\n * Path, relative to the manifest, of the art that goes on a mounted\n * sheet — when that is not the raw generated output.\n *\n * `mount` otherwise takes its pixels from the lockfile, which records\n * what the API returned. That is the wrong file whenever the art needs a\n * step pixelkiln does not perform: a palette reduction onto a sheet's\n * closed palette, a hand touch-up, an alignment shift. Without somewhere\n * to say so, the choice is to mount the unprocessed art or to abandon\n * `mount` and composite by hand — and the hand-composited sheet is\n * exactly the unreproducible artifact `mount` exists to replace.\n *\n * An asset with a `source` needs no lockfile entry at all, so art\n * generated outside pixelkiln can still be placed by cell alongside art\n * that wasn't. `prompt` still records what was asked for.\n */\n source: z.string().optional(),\n /** Controlled generation derived from another asset in the same style. */\n revision: RevisionSchema.optional(),\n /**\n * Generated output role to place in `cell` when this asset expands to\n * several files. Omit for ordinary single-output assets. A structural set\n * is otherwise ambiguous and `mount` refuses to guess by taking index zero.\n */\n outputRole: z.string().min(1).optional(),\n tags: z.array(z.string()).default([]),\n /** Restrict this asset to specific styles. Empty means all styles. */\n styles: z.array(z.string()).default([]),\n /**\n * Per-style replacement for `prompt`, keyed by style id.\n *\n * A style can need different wording rather than different styling. A\n * monochrome style is the clear case: prompts that name colours\n * (\"green purple gold\", \"colorful rainbow\") override the palette\n * instruction and survive into the output, while the same prompt is\n * exactly right for a colour style. Editing the shared prompt to suit one\n * style would invalidate every other style's already-generated art.\n */\n promptByStyle: z.record(z.string()).default({}),\n /**\n * Named per-asset values consumed by the active provider's declared\n * bindings. Values are JSON scalars, or a frame-set sequence of scalars;\n * adapters may interpret a string as a manifest-relative uploaded file.\n */\n providerInputs: z\n .record(z.union([\n z.string(),\n z.number().finite(),\n z.boolean(),\n z.array(z.union([z.string(), z.number().finite(), z.boolean()])).min(2).max(64),\n ]))\n .default({}),\n })\n .strict()\n .superRefine((asset, context) => {\n if (asset.source && asset.revision) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n message: \"source and revision are mutually exclusive\",\n path: [\"revision\"],\n })\n }\n })\n\nexport const ManifestSchema = z\n .object({\n $schema: z.string().optional(),\n name: z.string(),\n /** Generation backend. Existing manifests remain PixelLab by default. */\n provider: z.string().min(1).default(\"pixellab\"),\n styles: z.record(StyleSchema),\n assets: z.record(AssetSchema),\n })\n .strict()\n\n/** Manifest contract accepted from disk before style inheritance is resolved. */\nexport const ManifestInputSchema = z\n .object({\n $schema: z.string().optional(),\n name: z.string(),\n provider: z.string().min(1).default(\"pixellab\"),\n styles: z.record(StyleInputSchema),\n assets: z.record(AssetSchema),\n })\n .strict()\n\nexport type Manifest = z.infer<typeof ManifestSchema>\nexport type Style = z.infer<typeof StyleSchema>\nexport type Asset = z.infer<typeof AssetSchema>\n\n/**\n * One line of the lockfile: the mapping from a spec to the provider work that\n * satisfies it and the file on disk that came from it. This is the record that\n * did not exist before — without it, generated objects and downloaded files are\n * two unrelated piles.\n */\nexport const LockEntrySchema = z.object({\n styleId: z.string(),\n assetId: z.string(),\n /** sha256 of the resolved spec. Changing a prompt/size/style invalidates it. */\n specHash: z.string(),\n generator: GeneratorSchema,\n /** Connectable tiles must remain multi-output even when polling is resumed later. */\n tileFeature: z.string().nullable().default(null),\n /** The resolved prompt actually sent, kept for auditing and for adopt matching. */\n prompt: z.string(),\n width: z.number().int(),\n height: z.number().int(),\n /** Explicit parent/input lineage for a revision generation. */\n revision: z\n .object({\n mode: RevisionModeSchema,\n sourceAssetId: z.string().min(1),\n sourceSha256: z.string().regex(/^[0-9a-f]{64}$/),\n maskSha256: z.string().regex(/^[0-9a-f]{64}$/).optional(),\n strength: z.number().min(0).max(1).optional(),\n })\n .strict()\n .nullable()\n .default(null),\n\n /**\n * Output hashes owned by the previous generation while its replacement is\n * pending. They authorize replacing only unchanged PixelKiln-owned files.\n */\n supersededOutputs: z\n .array(\n z.object({\n path: z.string(),\n sha256: z.string(),\n role: z.string().optional(),\n mediaType: MediaTypeSchema.optional(),\n }),\n )\n .optional(),\n\n /** Set at submit time, before the request is awaited, so a crash is recoverable. */\n jobId: z.string().nullable().default(null),\n /** False only when a provider checkpoint says more requests remain. */\n submissionComplete: z.boolean().optional(),\n /** For `1dir`: the multi-candidate parent object awaiting selection. */\n reviewObjectId: z.string().nullable().default(null),\n /** The chosen candidate's own object id, once selected. */\n objectId: z.string().nullable().default(null),\n candidateIndex: z.number().int().nullable().default(null),\n\n status: z\n .enum([\n \"pending\",\n \"processing\",\n \"review\",\n \"selected\",\n \"downloaded\",\n \"download-failed\",\n \"failed\",\n ])\n .default(\"pending\"),\n error: z.string().nullable().default(null),\n\n sourceUrl: z.string().nullable().default(null),\n /** Every source in a structural multi-output result, in provider order. */\n sourceUrls: z\n .array(\n z.object({\n url: z.string(),\n role: z.string().optional(),\n mediaType: MediaTypeSchema.optional(),\n }),\n )\n .default([]),\n\n /**\n * Files this entry produced. A plain object generates one; asset kinds that\n * expand into many — an animated character is ~35 spritesheets plus an engine\n * resource — need the list, which is why v1's single `file` became this.\n *\n * `role` labels non-primary artifacts (e.g. \"portrait\", \"spriteframes\") so a\n * consumer can find the one it wants without pattern-matching on paths.\n */\n outputs: z\n .array(\n z.object({\n path: z.string(),\n sha256: z.string(),\n role: z.string().optional(),\n mediaType: MediaTypeSchema.optional(),\n }),\n )\n .default([]),\n\n /**\n * Provider-owned data retained for downstream consumers, namespaced by\n * provider id. PixelLab connectable sets keep their exact `tileRules` here\n * so exporters can map images to adjacency rules.\n */\n providerMetadata: z.record(z.record(z.unknown())).default({}),\n\n submittedAt: z.string().nullable().default(null),\n downloadedAt: z.string().nullable().default(null),\n /** Successful-submission estimate in `costUnit`; may be fractional USD. */\n cost: z.number().finite().nonnegative().default(0),\n /** Unit for `cost`. Defaults preserve pre-unit PixelLab lockfiles. */\n costUnit: z.string().min(1).default(\"generations\"),\n /** Which provider produced this. Absent on entries written before providers. */\n provider: z.string().default(\"pixellab\"),\n})\n\nexport const LockSchema = z.object({\n version: z.literal(2),\n entries: z.record(LockEntrySchema),\n})\n\nexport type LockEntry = z.infer<typeof LockEntrySchema>\nexport type Lock = z.infer<typeof LockSchema>\nexport type LockOutput = LockEntry[\"outputs\"][number]\n\n/**\n * Parses a lockfile, rejecting anything that is not v2.\n *\n * There is deliberately no migration path. Both consuming projects were\n * onboarded after v2 landed, so a v1 file would be a corruption or a\n * hand-edit rather than a legacy artifact — better to fail loudly than to\n * quietly reinterpret it.\n */\nexport function parseLock(raw: unknown): Lock {\n const parsed = LockSchema.safeParse(raw)\n if (parsed.success) return parsed.data\n throw new Error(\n `Lockfile is not valid v2:\\n${parsed.error.issues\n .slice(0, 5)\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\")}`,\n )\n}\n\n/** The file a consumer means when it says \"the asset\" — the first output. */\nexport function primaryOutput(entry: LockEntry): LockOutput | null {\n return entry.outputs.find((o) => !o.role) ?? entry.outputs[0] ?? null\n}\n\n/** Lock entries are keyed `<styleId>/<assetId>`, which makes styles a namespace. */\nexport function lockKey(styleId: string, assetId: string): string {\n return `${styleId}/${assetId}`\n}\n\n/** A manifest entry resolved against its style — everything needed to generate. */\nexport interface ResolvedSpec {\n /** Absolute directory containing the manifest; excluded from the spec hash. */\n root: string\n styleId: string\n assetId: string\n /** Backend whose request semantics and estimate produced this spec. */\n provider: string\n /** Adapter-owned settings selected from the active provider namespace. */\n providerOptions: Record<string, unknown>\n /** Adapter-resolved per-asset inputs. Their stable identity participates in the spec hash. */\n providerInputs?: Record<string, unknown>\n generator: Generator\n prompt: string\n width: number\n height: number\n view: string\n size: number\n styleImagePaths: string[]\n outFile: string\n /** Derived quality output. Excluded from provider request identity and spend. */\n quality?: ResolvedQualityProfile\n /** Provider generation derived from another current manifest asset. */\n revision?: ResolvedRevision\n /**\n * Manifest-relative path of committed art that stands in for generated\n * output; excluded from the spec hash. Set only when the asset declares\n * `source`, which also means it needs no lock entry.\n */\n source?: string\n tags: string[]\n specHash: string\n cost: number\n costUnit: import(\"./provider.ts\").CostUnit\n candidates: number\n outline?: string\n shading?: string\n detail?: string\n seed?: number\n /** Forced palette hex values; empty unless the style sets one. */\n palette: string[]\n /** `pixflux` only — strip the generated background. Defaults to true. */\n noBackground: boolean\n /** `tiles` generator only — see StyleSchema for what each one means. */\n tileSize?: number\n tileType?: string\n tileView?: string\n tileFeature?: string\n outlineMode?: string\n}\n","import { paletteSwatch } from \"../png.ts\"\nimport type {\n BalanceInfo,\n CostEstimate,\n JobState,\n PollContext,\n Provider,\n} from \"../provider.ts\"\nimport type { Generator, ResolvedSpec, ResolvedStyleImage } from \"../types.ts\"\nimport { MediaType, type MediaType as MediaKind } from \"../media.ts\"\n\nconst DEFAULT_BASE_URL = \"https://api.retrodiffusion.ai/v1\"\nconst SOURCE_PROTOCOL = \"retrodiffusion:\"\n\nexport interface RetroDiffusionOptions {\n /** Live style id returned by GET /styles/selector. */\n promptStyle?: string\n /** Candidate images produced by one request. */\n numImages?: number\n /** Override the style's shared noBackground setting. */\n removeBg?: boolean\n /** Animation frame duration accepted by Retro Diffusion. */\n framesDuration?: 4 | 6 | 8 | 10 | 12 | 16\n /** Return a PNG spritesheet instead of the default animated GIF. */\n returnSpritesheet?: boolean\n /** Outside texture description for rd_tile__tileset_advanced. */\n extraPrompt?: string\n /** Ask a still image to tile seamlessly on each axis. */\n tileX?: boolean\n tileY?: boolean\n}\n\ninterface InferenceResult {\n balance_cost?: number\n remaining_balance?: number\n base64_images?: string[]\n output_urls?: string[]\n}\n\ninterface TaskResponse {\n status: \"pending\" | \"running\" | \"succeeded\" | \"failed\"\n result?: InferenceResult | null\n error?: string | { message?: string } | null\n}\n\nclass RetroDiffusionClient {\n constructor(\n private readonly token: string | undefined,\n private readonly baseUrl = DEFAULT_BASE_URL,\n private readonly request: typeof fetch = fetch,\n ) {}\n\n async submit(body: Record<string, unknown>): Promise<string> {\n const response = await this.call(\"/inferences\", { method: \"POST\", body: JSON.stringify(body) })\n const taskId = (response as { task_id?: unknown }).task_id\n if (typeof taskId !== \"string\" || !taskId) {\n throw new Error(\"Retro Diffusion did not return an async task id\")\n }\n return taskId\n }\n\n async quote(body: Record<string, unknown>): Promise<number> {\n const response = await this.call(\"/inferences\", {\n method: \"POST\",\n body: JSON.stringify({ ...body, check_cost: true }),\n })\n const amount = (response as { balance_cost?: unknown }).balance_cost\n if (typeof amount !== \"number\" || !Number.isFinite(amount) || amount < 0) {\n throw new Error(\"Retro Diffusion returned an invalid cost quote\")\n }\n return amount\n }\n\n async task(id: string): Promise<TaskResponse> {\n return (await this.call(`/inferences/tasks/${encodeURIComponent(id)}`)) as TaskResponse\n }\n\n async balance(): Promise<number> {\n const response = await this.call(\"/inferences/credits\")\n const balance = (response as { balance?: unknown }).balance\n if (typeof balance !== \"number\" || !Number.isFinite(balance)) {\n throw new Error(\"Retro Diffusion returned an invalid balance\")\n }\n return balance\n }\n\n private async call(path: string, init: RequestInit = {}): Promise<unknown> {\n if (!this.token) throw new Error(\"RD_API_KEY is not set\")\n const response = await this.request(`${this.baseUrl}${path}`, {\n ...init,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-RD-Token\": this.token,\n ...init.headers,\n },\n })\n const text = await response.text()\n let value: unknown = null\n try {\n value = text ? JSON.parse(text) : null\n } catch {\n value = text\n }\n if (!response.ok) {\n const retry = response.headers.get(\"retry-after\")\n const detail = retroError(value)\n throw new Error(\n `Retro Diffusion request failed (${response.status}): ${detail}` +\n (retry ? `; retry after ${retry}s` : \"\"),\n )\n }\n return value\n }\n}\n\n/** Experimental native pixel-art still, tileset, and animation adapter. */\nexport class RetroDiffusionProvider implements Provider {\n readonly id = \"retrodiffusion\"\n\n constructor(private readonly client: RetroDiffusionClient) {}\n\n static fromEnv(): RetroDiffusionProvider {\n return new RetroDiffusionProvider(new RetroDiffusionClient(process.env.RD_API_KEY))\n }\n\n static forOffline(): RetroDiffusionProvider {\n return new RetroDiffusionProvider(new RetroDiffusionClient(undefined))\n }\n\n static forDownloads(): RetroDiffusionProvider {\n // Ordinary public URLs and cached bytes need no credential. A durable\n // retrodiffusion:// reference resolves a fresh provider result and the\n // client reports a clear RD_API_KEY error only if that fallback is used.\n return new RetroDiffusionProvider(new RetroDiffusionClient(process.env.RD_API_KEY))\n }\n\n supports(generator: Generator): boolean {\n return generator === \"map\" || generator === \"pixflux\" ||\n generator === \"tiles\" || generator === \"animation\"\n }\n\n estimate(spec: ResolvedSpec): CostEstimate {\n const options = retroOptions(spec)\n const style = resolvedPromptStyle(spec, options)\n const count = options.numImages ?? 1\n const pixels = spec.width * spec.height\n let each: number\n if (style.startsWith(\"rd_advanced_animation__\")) {\n each = /__(?:custom_action|subtle_motion)$/.test(style) ? 0.25 : 0.14\n } else if (style.startsWith(\"rd_animation__\")) {\n each = /__(?:any_animation|8_dir_rotation)$/.test(style) ? 0.25 : 0.07\n } else if (/^rd_tile__tileset(?:_advanced)?$/.test(style)) {\n each = 0.1\n } else if (style.startsWith(\"rd_pro__\")) {\n each = 0.18\n } else if (style.startsWith(\"rd_fast__\")) {\n each = Math.max(0.015, (pixels + 100_000) / 6_000_000)\n } else if (isLowResolutionStyle(style)) {\n each = Math.max(0.02, (pixels + 13_700) / 600_000)\n } else {\n each = Math.max(0.025, (pixels + 50_000) / 2_000_000)\n }\n return { unit: \"usd\", amount: roundUsdEstimate(each * count), candidates: count }\n }\n\n validate(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): void {\n const options = retroOptions(spec)\n const promptStyle = resolvedPromptStyle(spec, options)\n const count = options.numImages ?? 1\n const isAnimation = /^(?:rd_animation__|rd_advanced_animation__)/.test(promptStyle)\n const isTile = promptStyle.startsWith(\"rd_tile__\")\n if (\n !promptStyle ||\n (spec.generator === \"animation\" && !isAnimation) ||\n (spec.generator === \"tiles\" && !isTile) ||\n (spec.generator !== \"animation\" && spec.generator !== \"tiles\" && (isAnimation || isTile))\n ) {\n throw new Error(\n `Retro Diffusion style \"${promptStyle}\" does not match generator \"${spec.generator}\"`,\n )\n }\n if (!Number.isInteger(count) || count < 1 || count > 16) {\n throw new Error(\"Retro Diffusion numImages must be a whole number from 1 to 16\")\n }\n if (spec.width < 16 || spec.height < 16 || spec.width > 512 || spec.height > 512) {\n throw new Error(\"Retro Diffusion output dimensions must be between 16 and 512 pixels\")\n }\n if (styleImages.length > 9) {\n throw new Error(\"Retro Diffusion accepts at most 9 reference images\")\n }\n if (spec.generator === \"animation\") {\n if (count !== 1) throw new Error(\"Retro Diffusion animations currently require numImages: 1\")\n validateAnimation(promptStyle, spec, styleImages, options)\n } else if (spec.generator === \"tiles\") {\n validateTile(promptStyle, spec, styleImages, count, options)\n } else if (styleImages.length && !/^(?:rd_pro__|user__)/.test(promptStyle)) {\n throw new Error(\n `Retro Diffusion style \"${promptStyle}\" does not accept reference_images; ` +\n \"use an RD Pro or user style\",\n )\n }\n }\n\n async submit(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): Promise<{ jobId: string }> {\n this.validate(spec, styleImages)\n const options = retroOptions(spec)\n const promptStyle = resolvedPromptStyle(spec, options)\n const animation = spec.generator === \"animation\"\n const tiles = spec.generator === \"tiles\"\n const body: Record<string, unknown> = {\n prompt: spec.prompt,\n prompt_style: promptStyle,\n width: spec.width,\n height: spec.height,\n num_images: options.numImages ?? 1,\n ...(!animation && !tiles ? { remove_bg: options.removeBg ?? spec.noBackground } : {}),\n ...(spec.seed != null ? { seed: spec.seed } : {}),\n ...(animation || tiles\n ? styleImages[0]\n ? { input_image: styleImages[0].base64 }\n : {}\n : styleImages.length\n ? { reference_images: styleImages.map((image) => image.base64) }\n : {}),\n ...(tiles && styleImages[1] ? { extra_input_image: styleImages[1].base64 } : {}),\n ...(tiles && options.extraPrompt ? { extra_prompt: options.extraPrompt } : {}),\n ...(animation && options.framesDuration ? { frames_duration: options.framesDuration } : {}),\n ...(animation && options.returnSpritesheet ? { return_spritesheet: true } : {}),\n ...(!animation && options.tileX != null ? { tile_x: options.tileX } : {}),\n ...(!animation && options.tileY != null ? { tile_y: options.tileY } : {}),\n ...(spec.palette.length\n ? { input_palette: paletteSwatch(spec.palette).toString(\"base64\") }\n : {}),\n }\n const quoted = await this.client.quote(body)\n const estimated = this.estimate(spec).amount\n if (quoted > estimated + 0.000001) {\n throw new Error(\n `Retro Diffusion quoted $${quoted.toFixed(6)}, above the offline estimate ` +\n `$${estimated.toFixed(6)}; no paid request was sent`,\n )\n }\n return {\n jobId: await this.client.submit({ ...body, async: true, upload_outputs: true }),\n }\n }\n\n async poll(jobId: string, generator: Generator, context?: PollContext): Promise<JobState> {\n const task = await this.client.task(jobId)\n if (task.status === \"pending\" || task.status === \"running\") return { status: \"processing\" }\n if (task.status === \"failed\") return { status: \"failed\", error: retroError(task.error) }\n if (task.status !== \"succeeded\") {\n return { status: \"failed\", error: `Retro Diffusion returned unknown task status \"${String(task.status)}\"` }\n }\n\n const options = context?.spec ? retroOptions(context.spec) : {}\n const mediaType = generator === \"animation\" && !options.returnSpritesheet\n ? MediaType.GIF\n : MediaType.PNG\n const sources = resultSources(task.result, mediaType)\n const urls = sources.map((source) => source.url)\n if (!urls.length) return { status: \"failed\", error: \"Retro Diffusion task returned no images\" }\n if (urls.length > 1) return { status: \"review\", candidateUrls: urls }\n const durableSources = sources.map((source, index) => ({\n ...source,\n url: sourceRef(jobId, index, mediaType),\n }))\n return {\n status: \"ready\",\n objectId: `${jobId}#0`,\n sourceUrl: durableSources[0]!.url,\n sources: durableSources,\n metadata: {\n balanceCost: task.result?.balance_cost ?? null,\n remainingBalance: task.result?.remaining_balance ?? null,\n mediaType,\n kind: generator === \"animation\" ? \"animation\" : generator === \"tiles\" ? \"tileset\" : \"image\",\n ...(context?.spec\n ? {\n promptStyle: resolvedPromptStyle(context.spec, options),\n width: context.spec.width,\n height: context.spec.height,\n }\n : {}),\n },\n }\n }\n\n async selectCandidate(\n jobId: string,\n index: number,\n ): Promise<{ objectId: string; sourceUrl: string | null }> {\n const task = await this.client.task(jobId)\n if (task.status !== \"succeeded\") throw new Error(`Retro Diffusion task ${jobId} is not ready`)\n const url = resultSources(task.result, MediaType.PNG)[index]?.url\n if (!url) throw new Error(`Retro Diffusion task ${jobId} has no candidate at index ${index}`)\n return { objectId: `${jobId}#${index}`, sourceUrl: sourceRef(jobId, index, MediaType.PNG) }\n }\n\n async download(url: string): Promise<Buffer> {\n if (url.startsWith(`${SOURCE_PROTOCOL}//`)) {\n const reference = parseSourceRef(url)\n const task = await this.client.task(reference.jobId)\n if (task.status !== \"succeeded\") {\n throw new Error(`Retro Diffusion task ${reference.jobId} is not ready`)\n }\n const source = resultSources(task.result, reference.mediaType)[reference.index]?.url\n if (!source) {\n throw new Error(\n `Retro Diffusion task ${reference.jobId} has no output at index ${reference.index}`,\n )\n }\n return this.downloadResolved(source)\n }\n return this.downloadResolved(url)\n }\n\n private async downloadResolved(url: string): Promise<Buffer> {\n const data = /^data:[^;]+;base64,(.+)$/.exec(url)?.[1]\n if (data) return Buffer.from(data, \"base64\")\n const response = await fetch(url)\n if (!response.ok) throw new Error(`Retro Diffusion download failed (${response.status})`)\n return Buffer.from(await response.arrayBuffer())\n }\n\n async balance(): Promise<BalanceInfo> {\n return { unit: \"usd\", remaining: await this.client.balance() }\n }\n}\n\nfunction sourceRef(jobId: string, index: number, mediaType: MediaKind): string {\n const url = new URL(\"retrodiffusion://output\")\n url.searchParams.set(\"job\", jobId)\n url.searchParams.set(\"index\", String(index))\n url.searchParams.set(\"mediaType\", mediaType)\n return url.href\n}\n\nfunction parseSourceRef(value: string): { jobId: string; index: number; mediaType: MediaKind } {\n const url = new URL(value)\n const jobId = url.searchParams.get(\"job\")\n const index = Number(url.searchParams.get(\"index\"))\n const rawMediaType = url.searchParams.get(\"mediaType\")\n if (\n url.protocol !== SOURCE_PROTOCOL ||\n url.hostname !== \"output\" ||\n !jobId ||\n !Number.isInteger(index) ||\n index < 0 ||\n (rawMediaType !== MediaType.PNG && rawMediaType !== MediaType.GIF)\n ) {\n throw new Error(\"Invalid durable Retro Diffusion source reference\")\n }\n return { jobId, index, mediaType: rawMediaType }\n}\n\nfunction retroOptions(spec: ResolvedSpec): RetroDiffusionOptions {\n return spec.providerOptions as RetroDiffusionOptions\n}\n\nfunction resultSources(\n result: InferenceResult | null | undefined,\n mediaType: MediaKind,\n): Array<{ url: string; mediaType: MediaKind }> {\n const hosted = (result?.output_urls ?? [])\n .filter((url): url is string => typeof url === \"string\" && url.length > 0)\n .map((url) => ({ url, mediaType }))\n if (hosted.length) return hosted\n return (result?.base64_images ?? [])\n .filter((data): data is string => typeof data === \"string\" && data.length > 0)\n .map((data) => ({\n url: `data:${mediaType};base64,${data}`,\n mediaType,\n }))\n}\n\nfunction resolvedPromptStyle(spec: ResolvedSpec, options: RetroDiffusionOptions): string {\n return options.promptStyle ??\n (spec.generator === \"animation\"\n ? \"rd_animation__any_animation\"\n : spec.generator === \"tiles\"\n ? \"rd_tile__tileset\"\n : \"rd_plus__default\")\n}\n\nfunction validateAnimation(\n style: string,\n spec: ResolvedSpec,\n styleImages: ResolvedStyleImage[],\n options: RetroDiffusionOptions,\n): void {\n if (spec.width !== spec.height) throw new Error(\"Retro Diffusion animations must be square\")\n if (style.startsWith(\"rd_advanced_animation__\")) {\n if (styleImages.length !== 1) {\n throw new Error(`Retro Diffusion advanced animation style \"${style}\" requires one input image`)\n }\n if (spec.width < 32 || spec.width > 256) {\n throw new Error(\"Retro Diffusion advanced animations require dimensions from 32 to 256 pixels\")\n }\n } else if (styleImages.length > 1) {\n throw new Error(\"Retro Diffusion prompt animations accept at most one input image\")\n }\n const exact = style.includes(\"four_angle_walking\") ? 48\n : style.endsWith(\"__small_sprites\") ? 32\n : style.endsWith(\"__any_animation\") ? 64\n : style.endsWith(\"__big_animation\") ? 128\n : style.endsWith(\"__8_dir_rotation\") ? 80\n : null\n if (exact && spec.width !== exact) {\n throw new Error(`Retro Diffusion style \"${style}\" requires ${exact}x${exact} dimensions`)\n }\n if (style.endsWith(\"__vfx\") && (spec.width < 24 || spec.width > 96)) {\n throw new Error(\"Retro Diffusion VFX animations require dimensions from 24 to 96 pixels\")\n }\n if (options.framesDuration != null && ![4, 6, 8, 10, 12, 16].includes(options.framesDuration)) {\n throw new Error(\"Retro Diffusion framesDuration must be 4, 6, 8, 10, 12, or 16\")\n }\n}\n\nfunction validateTile(\n style: string,\n spec: ResolvedSpec,\n styleImages: ResolvedStyleImage[],\n count: number,\n options: RetroDiffusionOptions,\n): void {\n if (spec.width !== spec.height) throw new Error(\"Retro Diffusion tiles must be square\")\n const size = spec.width\n if (/^rd_tile__tileset(?:_advanced)?$/.test(style)) {\n if (size < 16 || size > 32) throw new Error(\"Retro Diffusion tilesets require 16–32px tiles\")\n if (count !== 1) throw new Error(\"Retro Diffusion tilesets require numImages: 1\")\n } else if (style === \"rd_tile__single_tile\" && (size < 16 || size > 64)) {\n throw new Error(\"Retro Diffusion single tiles require dimensions from 16 to 64 pixels\")\n } else if (style === \"rd_tile__tile_variation\") {\n if (size < 16 || size > 128) throw new Error(\"Retro Diffusion tile variations require 16–128px tiles\")\n if (styleImages.length !== 1) throw new Error(\"Retro Diffusion tile variations require one input image\")\n } else if (style === \"rd_tile__tile_object\" && (size < 16 || size > 96)) {\n throw new Error(\"Retro Diffusion tile objects require dimensions from 16 to 96 pixels\")\n } else if (style === \"rd_tile__scene_object\" && (size < 64 || size > 384)) {\n throw new Error(\"Retro Diffusion tile scene objects require dimensions from 64 to 384 pixels\")\n }\n if (style === \"rd_tile__tileset\" && styleImages.length > 1) {\n throw new Error(\"Retro Diffusion basic tilesets accept at most one input image\")\n }\n if (style === \"rd_tile__tileset_advanced\") {\n if (styleImages.length > 2) throw new Error(\"Retro Diffusion advanced tilesets accept at most two input images\")\n if (!options.extraPrompt && styleImages.length < 2) {\n throw new Error(\"Retro Diffusion advanced tilesets require extraPrompt or a second input image\")\n }\n }\n}\n\nfunction isLowResolutionStyle(style: string): boolean {\n return /(?:^|__)(?:mc_|low_res|classic|skill_icon|topdown_item)/.test(style)\n}\n\nfunction roundUsdEstimate(value: number): number {\n // Live quotes may round a formula result up to the nearest $0.001. Planning\n // must be conservative or submit() will correctly reject that rounded quote\n // as higher than the offline estimate.\n return Math.ceil((value - 1e-9) * 1_000) / 1_000\n}\n\nfunction retroError(value: unknown): string {\n if (typeof value === \"string\") return value || \"unknown error\"\n if (!value || typeof value !== \"object\") return \"unknown error\"\n const record = value as Record<string, unknown>\n if (typeof record.message === \"string\") return record.message\n if (typeof record.detail === \"string\") return record.detail\n if (Array.isArray(record.detail)) {\n const details = record.detail\n .map((item) => {\n if (!item || typeof item !== \"object\") return String(item)\n const detail = item as Record<string, unknown>\n return typeof detail.msg === \"string\" ? detail.msg : JSON.stringify(item)\n })\n .filter(Boolean)\n if (details.length) return details.join(\"; \")\n }\n if (record.detail && typeof record.detail === \"object\") {\n const message = (record.detail as Record<string, unknown>).message\n if (typeof message === \"string\") return message\n }\n return JSON.stringify(value)\n}\n","import { MAX_DOWNLOAD_BYTES } from \"../client.ts\"\nimport { MediaType } from \"../media.ts\"\nimport type {\n CandidateSelection,\n CostEstimate,\n JobState,\n PollContext,\n Provider,\n ProviderMetadata,\n ProviderSubmission,\n RateLimit,\n} from \"../provider.ts\"\nimport type { Generator, ResolvedSpec, ResolvedStyleImage } from \"../types.ts\"\n\nconst DEFAULT_BASE_URL = \"https://api.cloud.scenario.com/v1\"\nconst SOURCE_PROTOCOL = \"scenario:\"\nconst PROTECTED_PARAMETERS = new Set([\n \"dryRun\",\n \"height\",\n \"maxComputeUnits\",\n \"numOutputs\",\n \"projectId\",\n \"prompt\",\n \"seed\",\n \"width\",\n])\n\nexport interface ScenarioOptions {\n /** Scenario model passed to POST /generate/custom/{modelId}. */\n modelId: string\n /** Conservative per-asset ceiling used by offline planning and live preflight. */\n maxComputeUnits: number\n /** Number of images requested. More than one enters PixelKiln review. */\n numOutputs?: number\n /** Optional Scenario project ownership/routing id. */\n projectId?: string\n /** Additional model-specific JSON inputs that cannot replace PixelKiln-owned intent. */\n parameters?: Record<string, unknown>\n}\n\ninterface ScenarioQuote {\n total: number\n creativeUnitsCost: number\n costDetails: Record<string, number>\n ipDetectionCost: number\n}\n\ninterface ScenarioJob {\n jobId: string\n status: string\n progress?: number\n metadata?: {\n assetIds?: unknown\n error?: unknown\n }\n billing?: {\n cuCost?: unknown\n cuDiscount?: unknown\n cuCostDetails?: unknown\n }\n}\n\ninterface ScenarioAsset {\n id: string\n url: string\n originalFileUrl?: string\n originalMimeType?: string\n outputIndex: number\n}\n\nclass ScenarioClient {\n constructor(\n private readonly apiKey: string | undefined,\n private readonly apiSecret: string | undefined,\n private readonly baseUrl = DEFAULT_BASE_URL,\n private readonly request: typeof fetch = fetch,\n ) {}\n\n async quote(modelId: string, body: Record<string, unknown>, projectId?: string): Promise<ScenarioQuote> {\n const response = await this.call(\n `/generate/custom/${encodeURIComponent(modelId)}`,\n { method: \"POST\", body: JSON.stringify(body) },\n { dryRun: \"true\", projectId },\n )\n const creativeUnitsCost = finiteNonnegative(\n (response as { creativeUnitsCost?: unknown })?.creativeUnitsCost,\n \"Scenario dry run returned an invalid creativeUnitsCost\",\n )\n const costDetails = numericRecord((response as { costDetails?: unknown })?.costDetails)\n const ipDetectionCost = optionalFiniteNonnegative(\n (response as { ipDetection?: { creativeUnitsCharged?: unknown } })?.ipDetection\n ?.creativeUnitsCharged,\n \"Scenario dry run returned an invalid IP-detection cost\",\n )\n return {\n total: creativeUnitsCost + ipDetectionCost,\n creativeUnitsCost,\n costDetails,\n ipDetectionCost,\n }\n }\n\n async submit(\n modelId: string,\n body: Record<string, unknown>,\n projectId?: string,\n ): Promise<string> {\n const response = await this.call(\n `/generate/custom/${encodeURIComponent(modelId)}`,\n { method: \"POST\", body: JSON.stringify(body) },\n { projectId },\n )\n const job = (response as { job?: unknown })?.job\n const jobId = readJobId(job)\n if (!jobId) throw new Error(\"Scenario did not return an async job id\")\n return jobId\n }\n\n async job(id: string, projectId?: string): Promise<ScenarioJob> {\n const response = await this.call(`/jobs/${encodeURIComponent(id)}`, {}, { projectId })\n const raw = (response as { job?: unknown })?.job\n if (!raw || typeof raw !== \"object\") throw new Error(\"Scenario returned an invalid job\")\n const record = raw as Record<string, unknown>\n const jobId = readJobId(raw)\n if (!jobId || typeof record.status !== \"string\") {\n throw new Error(\"Scenario returned an invalid job\")\n }\n return {\n jobId,\n status: record.status,\n ...(typeof record.progress === \"number\" ? { progress: record.progress } : {}),\n ...(record.metadata && typeof record.metadata === \"object\"\n ? { metadata: record.metadata as ScenarioJob[\"metadata\"] }\n : {}),\n ...(record.billing && typeof record.billing === \"object\"\n ? { billing: record.billing as ScenarioJob[\"billing\"] }\n : {}),\n }\n }\n\n async asset(id: string, projectId?: string): Promise<ScenarioAsset> {\n const response = await this.call(\n `/assets/${encodeURIComponent(id)}`,\n {},\n { originalAssets: \"true\", projectId },\n )\n const raw = (response as { asset?: unknown })?.asset\n if (!raw || typeof raw !== \"object\") throw new Error(`Scenario returned an invalid asset ${id}`)\n const asset = raw as Record<string, unknown>\n const assetId = typeof asset.id === \"string\" && asset.id ? asset.id : id\n const url = typeof asset.url === \"string\" ? asset.url : \"\"\n const originalFileUrl = typeof asset.originalFileUrl === \"string\"\n ? asset.originalFileUrl\n : undefined\n if (!originalFileUrl && !url) throw new Error(`Scenario asset ${assetId} has no download URL`)\n const metadata = isRecord(asset.metadata) ? asset.metadata : {}\n const rawOutputIndex = asset.outputIndex ?? metadata.outputIndex\n const outputIndex = Number.isInteger(rawOutputIndex) && Number(rawOutputIndex) >= 0\n ? Number(rawOutputIndex)\n : Number.MAX_SAFE_INTEGER\n const originalMimeType = typeof asset.originalMimeType === \"string\"\n ? asset.originalMimeType\n : typeof asset.mimeType === \"string\"\n ? asset.mimeType\n : undefined\n return {\n id: assetId,\n url,\n ...(originalFileUrl ? { originalFileUrl } : {}),\n ...(originalMimeType ? { originalMimeType } : {}),\n outputIndex,\n }\n }\n\n async download(url: string): Promise<Buffer> {\n const parsed = new URL(url)\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n throw new Error(\"Scenario downloads must use HTTP or HTTPS\")\n }\n const response = await this.request(parsed)\n if (!response.ok) throw new Error(`Scenario download failed (${response.status})`)\n const declared = Number(response.headers.get(\"content-length\"))\n if (Number.isFinite(declared) && declared > MAX_DOWNLOAD_BYTES) {\n throw new Error(`Scenario download exceeds the ${MAX_DOWNLOAD_BYTES}-byte safety limit`)\n }\n const bytes = Buffer.from(await response.arrayBuffer())\n if (bytes.length > MAX_DOWNLOAD_BYTES) {\n throw new Error(`Scenario download exceeds the ${MAX_DOWNLOAD_BYTES}-byte safety limit`)\n }\n return bytes\n }\n\n async checkConnection(): Promise<void> {\n await this.call(\"/models\", {}, { pageSize: \"1\" })\n }\n\n private async call(\n pathname: string,\n init: RequestInit = {},\n query: Record<string, string | undefined> = {},\n ): Promise<unknown> {\n if (!this.apiKey || !this.apiSecret) {\n const missing = [\n !this.apiKey ? \"SCENARIO_SDK_API_KEY\" : null,\n !this.apiSecret ? \"SCENARIO_SDK_API_SECRET\" : null,\n ].filter(Boolean)\n throw new Error(`${missing.join(\" and \")} ${missing.length > 1 ? \"are\" : \"is\"} not set`)\n }\n const url = new URL(`${this.baseUrl.replace(/\\/$/, \"\")}${pathname}`)\n for (const [key, value] of Object.entries(query)) {\n if (value != null) url.searchParams.set(key, value)\n }\n const auth = Buffer.from(`${this.apiKey}:${this.apiSecret}`).toString(\"base64\")\n const response = await this.request(url, {\n ...init,\n headers: {\n Accept: \"application/json\",\n Authorization: `Basic ${auth}`,\n ...(init.body ? { \"Content-Type\": \"application/json\" } : {}),\n ...init.headers,\n },\n })\n const text = await response.text()\n let value: unknown = null\n try {\n value = text ? JSON.parse(text) : null\n } catch {\n value = text\n }\n if (!response.ok) {\n const retry = response.headers.get(\"retry-after\")\n const detail = redactScenarioError(value, [this.apiKey, this.apiSecret, auth])\n throw new Error(\n `Scenario request failed (${response.status}): ${detail}` +\n (retry ? `; retry after ${retry}s` : \"\"),\n )\n }\n return value\n }\n}\n\n/** Experimental Scenario still-image adapter with mandatory CU preflight. */\nexport class ScenarioProvider implements Provider {\n readonly id = \"scenario\"\n\n constructor(private readonly client: ScenarioClient) {}\n\n static fromEnv(): ScenarioProvider {\n return new ScenarioProvider(new ScenarioClient(\n process.env.SCENARIO_SDK_API_KEY,\n process.env.SCENARIO_SDK_API_SECRET,\n scenarioBaseUrl(process.env.SCENARIO_API_BASE_URL ?? DEFAULT_BASE_URL),\n ))\n }\n\n static forOffline(): ScenarioProvider {\n return new ScenarioProvider(new ScenarioClient(undefined, undefined))\n }\n\n static forDownloads(): ScenarioProvider {\n return ScenarioProvider.fromEnv()\n }\n\n supports(generator: Generator): boolean {\n return generator === \"map\"\n }\n\n estimate(spec: ResolvedSpec): CostEstimate {\n const options = scenarioOptions(spec)\n return {\n unit: \"compute-units\",\n amount: options.maxComputeUnits,\n candidates: options.numOutputs ?? 1,\n }\n }\n\n validate(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): void {\n const options = scenarioOptions(spec)\n if (typeof options.modelId !== \"string\" || !options.modelId.trim()) {\n throw new Error(\"Scenario modelId is required\")\n }\n if (!Number.isFinite(options.maxComputeUnits) || options.maxComputeUnits <= 0) {\n throw new Error(\"Scenario maxComputeUnits must be a positive number\")\n }\n const count = options.numOutputs ?? 1\n if (!Number.isInteger(count) || count < 1 || count > 4) {\n throw new Error(\"Scenario numOutputs must be a whole number from 1 to 4\")\n }\n if (\n spec.width < 128 || spec.width > 2048 || spec.width % 16 !== 0 ||\n spec.height < 128 || spec.height > 2048 || spec.height % 16 !== 0\n ) {\n throw new Error(\"Scenario width and height must be multiples of 16 from 128 to 2048\")\n }\n if (styleImages.length) {\n throw new Error(\"Scenario styleImages are not supported yet; use a reusable Scenario model\")\n }\n if (options.projectId != null && (typeof options.projectId !== \"string\" || !options.projectId.trim())) {\n throw new Error(\"Scenario projectId must be a non-empty string\")\n }\n validateParameters(options.parameters ?? {})\n }\n\n rateLimit(): RateLimit {\n return { spacingMs: 1000, maxInFlight: 4 }\n }\n\n async submit(spec: ResolvedSpec, styleImages: ResolvedStyleImage[]): Promise<ProviderSubmission> {\n this.validate(spec, styleImages)\n const options = scenarioOptions(spec)\n const body = requestBody(spec, options)\n const quote = await this.client.quote(options.modelId, body, options.projectId)\n if (quote.total > options.maxComputeUnits + Number.EPSILON) {\n throw new Error(\n `Scenario quoted ${quote.total} compute-units, above maxComputeUnits ` +\n `${options.maxComputeUnits}; no paid request was sent`,\n )\n }\n const apiJobId = await this.client.submit(options.modelId, body, options.projectId)\n return {\n jobId: jobRef(apiJobId, options.projectId),\n metadata: {\n modelId: options.modelId,\n projectId: options.projectId ?? null,\n maxComputeUnits: options.maxComputeUnits,\n quotedComputeUnits: quote.total,\n creativeUnitsCost: quote.creativeUnitsCost,\n costDetails: quote.costDetails,\n ipDetectionCost: quote.ipDetectionCost,\n },\n }\n }\n\n async poll(jobReference: string, _generator: Generator, context?: PollContext): Promise<JobState> {\n const reference = parseJobRef(jobReference)\n const job = await this.client.job(reference.jobId, reference.projectId)\n const metadata = jobMetadata(job, context?.spec ? scenarioOptions(context.spec) : undefined)\n if ([\"pending\", \"queued\", \"warming-up\", \"in-progress\", \"finalizing\", \"processing\"].includes(job.status)) {\n return {\n status: \"processing\",\n progressPercent: validProgress(job.progress),\n }\n }\n if ([\"failure\", \"failed\", \"canceled\"].includes(job.status)) {\n return { status: \"failed\", error: scenarioJobError(job) }\n }\n if (job.status !== \"success\") {\n return { status: \"failed\", error: `Scenario returned unknown job status \"${job.status}\"` }\n }\n const assetIds = scenarioAssetIds(job)\n if (!assetIds.length) return { status: \"failed\", error: \"Scenario job returned no asset IDs\" }\n const assets = await this.assets(assetIds, reference.projectId)\n if (assets.length > 1) {\n return {\n status: \"review\",\n candidateUrls: assets.map(assetDownloadUrl),\n metadata: { ...metadata, assetIds: assets.map((asset) => asset.id) },\n }\n }\n const asset = assets[0]!\n return {\n status: \"ready\",\n objectId: asset.id,\n sourceUrl: assetRef(asset.id, reference.projectId),\n sources: [{ url: assetRef(asset.id, reference.projectId), mediaType: MediaType.PNG }],\n metadata: {\n ...metadata,\n assetId: asset.id,\n outputIndex: asset.outputIndex === Number.MAX_SAFE_INTEGER ? null : asset.outputIndex,\n },\n }\n }\n\n async selectCandidate(jobReference: string, index: number): Promise<CandidateSelection> {\n const reference = parseJobRef(jobReference)\n const job = await this.client.job(reference.jobId, reference.projectId)\n if (job.status !== \"success\") throw new Error(`Scenario job ${reference.jobId} is not ready`)\n const assets = await this.assets(scenarioAssetIds(job), reference.projectId)\n const asset = assets[index]\n if (!asset) throw new Error(`Scenario job ${reference.jobId} has no candidate at index ${index}`)\n return {\n objectId: asset.id,\n sourceUrl: assetRef(asset.id, reference.projectId),\n metadata: {\n ...jobMetadata(job),\n assetId: asset.id,\n outputIndex: asset.outputIndex === Number.MAX_SAFE_INTEGER ? null : asset.outputIndex,\n },\n }\n }\n\n async download(source: string): Promise<Buffer> {\n if (!source.startsWith(`${SOURCE_PROTOCOL}//`)) return this.client.download(source)\n const reference = parseAssetRef(source)\n const asset = await this.client.asset(reference.assetId, reference.projectId)\n assertPngAsset(asset)\n return this.client.download(assetDownloadUrl(asset))\n }\n\n async checkConnection(): Promise<void> {\n await this.client.checkConnection()\n }\n\n private async assets(ids: string[], projectId?: string): Promise<ScenarioAsset[]> {\n const assets = await Promise.all(ids.map((id) => this.client.asset(id, projectId)))\n const jobOrder = new Map(ids.map((id, index) => [id, index]))\n for (const asset of assets) assertPngAsset(asset)\n return assets.sort((left, right) =>\n left.outputIndex - right.outputIndex ||\n (jobOrder.get(left.id) ?? Number.MAX_SAFE_INTEGER) -\n (jobOrder.get(right.id) ?? Number.MAX_SAFE_INTEGER) ||\n left.id.localeCompare(right.id))\n }\n}\n\nfunction scenarioOptions(spec: ResolvedSpec): ScenarioOptions {\n return spec.providerOptions as unknown as ScenarioOptions\n}\n\nfunction scenarioBaseUrl(value: string): string {\n let url: URL\n try {\n url = new URL(value)\n } catch {\n throw new Error(\"SCENARIO_API_BASE_URL must be an absolute HTTP(S) URL\")\n }\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n throw new Error(\"SCENARIO_API_BASE_URL must use HTTP or HTTPS\")\n }\n return url.href.replace(/\\/$/, \"\")\n}\n\nfunction requestBody(spec: ResolvedSpec, options: ScenarioOptions): Record<string, unknown> {\n return {\n ...(options.parameters ?? {}),\n prompt: spec.prompt,\n width: spec.width,\n height: spec.height,\n numOutputs: options.numOutputs ?? 1,\n ...(spec.seed != null ? { seed: spec.seed } : {}),\n }\n}\n\nfunction validateParameters(parameters: Record<string, unknown>): void {\n if (!parameters || typeof parameters !== \"object\" || Array.isArray(parameters)) {\n throw new Error(\"Scenario parameters must be a JSON object\")\n }\n for (const key of Object.keys(parameters)) {\n if (PROTECTED_PARAMETERS.has(key)) {\n throw new Error(`Scenario parameters.${key} is managed by PixelKiln and cannot be overridden`)\n }\n }\n assertJsonValue(parameters, \"Scenario parameters\")\n}\n\nfunction assertJsonValue(value: unknown, label: string, seen = new Set<object>()): void {\n if (value == null || typeof value === \"string\" || typeof value === \"boolean\") return\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) throw new Error(`${label} contains a non-finite number`)\n return\n }\n if (typeof value !== \"object\") throw new Error(`${label} must contain only JSON values`)\n if (!Array.isArray(value)) {\n const prototype = Object.getPrototypeOf(value)\n if (prototype !== Object.prototype && prototype !== null) {\n throw new Error(`${label} must contain only plain JSON objects`)\n }\n }\n if (seen.has(value)) throw new Error(`${label} contains a circular value`)\n seen.add(value)\n if (Array.isArray(value)) {\n value.forEach((item, index) => assertJsonValue(item, `${label}[${index}]`, seen))\n } else {\n for (const [key, item] of Object.entries(value)) {\n assertJsonValue(item, `${label}.${key}`, seen)\n }\n }\n seen.delete(value)\n}\n\nfunction jobRef(jobId: string, projectId?: string): string {\n const url = new URL(\"scenario://job\")\n url.searchParams.set(\"id\", jobId)\n if (projectId) url.searchParams.set(\"projectId\", projectId)\n return url.href\n}\n\nfunction parseJobRef(value: string): { jobId: string; projectId?: string } {\n if (!value.startsWith(`${SOURCE_PROTOCOL}//`)) return { jobId: value }\n const url = new URL(value)\n const jobId = url.searchParams.get(\"id\")\n if (url.protocol !== SOURCE_PROTOCOL || url.hostname !== \"job\" || !jobId) {\n throw new Error(\"Invalid durable Scenario job reference\")\n }\n const projectId = url.searchParams.get(\"projectId\") || undefined\n return { jobId, ...(projectId ? { projectId } : {}) }\n}\n\nfunction assetRef(assetId: string, projectId?: string): string {\n const url = new URL(\"scenario://asset\")\n url.searchParams.set(\"id\", assetId)\n if (projectId) url.searchParams.set(\"projectId\", projectId)\n return url.href\n}\n\nfunction parseAssetRef(value: string): { assetId: string; projectId?: string } {\n const url = new URL(value)\n const assetId = url.searchParams.get(\"id\")\n if (url.protocol !== SOURCE_PROTOCOL || url.hostname !== \"asset\" || !assetId) {\n throw new Error(\"Invalid durable Scenario asset reference\")\n }\n const projectId = url.searchParams.get(\"projectId\") || undefined\n return { assetId, ...(projectId ? { projectId } : {}) }\n}\n\nfunction readJobId(value: unknown): string | null {\n if (!value || typeof value !== \"object\") return null\n const job = value as Record<string, unknown>\n const id = job.jobId ?? job.id\n return typeof id === \"string\" && id ? id : null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value)\n}\n\nfunction scenarioAssetIds(job: ScenarioJob): string[] {\n const ids = job.metadata?.assetIds\n return Array.isArray(ids)\n ? [...new Set(ids.filter((id): id is string => typeof id === \"string\" && id.length > 0))]\n : []\n}\n\nfunction assetDownloadUrl(asset: ScenarioAsset): string {\n return asset.originalFileUrl || asset.url\n}\n\nfunction assertPngAsset(asset: ScenarioAsset): void {\n if (asset.originalMimeType && asset.originalMimeType !== MediaType.PNG) {\n throw new Error(\n `Scenario asset ${asset.id} is ${asset.originalMimeType}; PixelKiln's Scenario MVP requires PNG output`,\n )\n }\n}\n\nfunction jobMetadata(job: ScenarioJob, options?: ScenarioOptions): ProviderMetadata {\n const billing = job.billing\n const billedMain = optionalFiniteNonnegative(billing?.cuCost, \"Scenario job returned invalid CU billing\")\n const billedAddons = Object.values(numericRecord(billing?.cuCostDetails))\n .reduce((sum, amount) => sum + amount, 0)\n return {\n ...(options\n ? {\n modelId: options.modelId,\n projectId: options.projectId ?? null,\n maxComputeUnits: options.maxComputeUnits,\n }\n : {}),\n apiJobId: job.jobId,\n billedComputeUnits: billedMain + billedAddons,\n billing: billing ?? null,\n }\n}\n\nfunction scenarioJobError(job: ScenarioJob): string {\n const raw = job.metadata?.error\n const detail = typeof raw === \"string\"\n ? raw\n : raw && typeof raw === \"object\" && typeof (raw as { message?: unknown }).message === \"string\"\n ? String((raw as { message: string }).message)\n : \"job did not complete\"\n return `Scenario job ${job.status}: ${detail.slice(0, 500)}`\n}\n\nfunction validProgress(progress: number | undefined): number | null {\n if (typeof progress !== \"number\" || !Number.isFinite(progress) || progress < 0 || progress > 1) {\n return null\n }\n return Math.round(progress * 100)\n}\n\nfunction finiteNonnegative(value: unknown, message: string): number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) throw new Error(message)\n return value\n}\n\nfunction optionalFiniteNonnegative(value: unknown, message: string): number {\n if (value == null) return 0\n return finiteNonnegative(value, message)\n}\n\nfunction numericRecord(value: unknown): Record<string, number> {\n if (value == null) return {}\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(\"Scenario returned invalid cost details\")\n }\n const out: Record<string, number> = {}\n for (const [key, amount] of Object.entries(value)) {\n out[key] = finiteNonnegative(amount, `Scenario returned invalid cost detail \"${key}\"`)\n }\n return out\n}\n\nfunction redactScenarioError(value: unknown, secrets: string[]): string {\n let detail: string\n if (typeof value === \"string\") detail = value\n else if (value && typeof value === \"object\") {\n const record = value as Record<string, unknown>\n const nested = record.error && typeof record.error === \"object\"\n ? (record.error as Record<string, unknown>).message\n : null\n detail = typeof record.message === \"string\"\n ? record.message\n : typeof nested === \"string\"\n ? nested\n : typeof record.detail === \"string\"\n ? record.detail\n : \"request failed\"\n } else detail = \"request failed\"\n for (const secret of secrets) {\n if (secret) detail = detail.split(secret).join(\"[redacted]\")\n }\n return detail.slice(0, 500)\n}\n","import type { Provider } from \"../provider.ts\"\nimport { ComfyUIProvider } from \"./comfyui.ts\"\nimport { PixelLabProvider } from \"./pixellab.ts\"\nimport { RetroDiffusionProvider } from \"./retrodiffusion.ts\"\nimport { ScenarioProvider } from \"./scenario.ts\"\n\nexport type ProviderMode = \"online\" | \"offline\" | \"downloads\"\n\n/** Construction metadata kept outside adapters so the CLI stays generic. */\nexport interface ProviderFactory {\n readonly id: string\n /** Environment variable expected for authenticated operations, if any. */\n readonly credentialEnv?: string\n /** All environment variables required by providers with compound credentials. */\n readonly credentialEnvs?: readonly string[]\n create(mode: ProviderMode): Provider\n}\n\nexport function providerCredentialEnvs(factory: ProviderFactory): readonly string[] {\n return factory.credentialEnvs ?? (factory.credentialEnv ? [factory.credentialEnv] : [])\n}\n\nconst factories = new Map<string, ProviderFactory>()\n\n/** Register a provider without allowing import order to replace an existing id. */\nexport function registerProvider(factory: ProviderFactory): void {\n const id = factory.id.trim()\n if (!id) throw new Error(\"Provider id cannot be empty\")\n if (factories.has(id)) throw new Error(`Provider \"${id}\" is already registered`)\n factories.set(id, factory)\n}\n\nexport function providerFactory(id: string): ProviderFactory {\n const factory = factories.get(id)\n if (!factory) {\n const available = [...factories.keys()].sort().join(\", \") || \"(none)\"\n throw new Error(`Unknown provider \"${id}\". Available providers: ${available}`)\n }\n return factory\n}\n\nexport function createProvider(id: string, mode: ProviderMode): Provider {\n return providerFactory(id).create(mode)\n}\n\nexport function availableProviders(): string[] {\n return [...factories.keys()].sort()\n}\n\nregisterProvider({\n id: \"pixellab\",\n credentialEnv: \"PIXELLAB_API_KEY\",\n create(mode) {\n if (mode === \"online\") return PixelLabProvider.fromEnv()\n if (mode === \"downloads\") return PixelLabProvider.forDownloads()\n return PixelLabProvider.forOffline()\n },\n})\n\nregisterProvider({\n id: \"retrodiffusion\",\n credentialEnv: \"RD_API_KEY\",\n create(mode) {\n if (mode === \"online\") return RetroDiffusionProvider.fromEnv()\n if (mode === \"downloads\") return RetroDiffusionProvider.forDownloads()\n return RetroDiffusionProvider.forOffline()\n },\n})\n\nregisterProvider({\n id: \"comfyui\",\n create(mode) {\n if (mode === \"online\") return ComfyUIProvider.fromEnv()\n if (mode === \"downloads\") return ComfyUIProvider.forDownloads()\n return ComfyUIProvider.forOffline()\n },\n})\n\nregisterProvider({\n id: \"scenario\",\n credentialEnvs: [\"SCENARIO_SDK_API_KEY\", \"SCENARIO_SDK_API_SECRET\"],\n create(mode) {\n if (mode === \"online\") return ScenarioProvider.fromEnv()\n if (mode === \"downloads\") return ScenarioProvider.forDownloads()\n return ScenarioProvider.forOffline()\n },\n})\n","import { readFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport type { ZodIssue } from \"zod\"\nimport {\n ManifestInputSchema,\n ManifestSchema,\n StyleSchema,\n candidateCount,\n countNumberedDescriptions,\n generationCost,\n tileVariationCount,\n tileFeatureOutputCount,\n tilesCost,\n type Manifest,\n type ResolvedSpec,\n type ResolvedStyleImage,\n type Style,\n type StyleInput,\n} from \"./types.ts\"\nimport { sha256, specHash } from \"./hash.ts\"\nimport { MediaType } from \"./media.ts\"\nimport { expectedOutputPath } from \"./outputs.ts\"\nimport { validateCostEstimate, type Provider } from \"./provider.ts\"\nimport { createProvider } from \"./providers/registry.ts\"\n\nexport interface LoadedManifest {\n manifest: Manifest\n /** Directory the manifest lives in. All relative paths resolve against it. */\n root: string\n path: string\n}\n\nexport async function loadManifest(manifestPath: string): Promise<LoadedManifest> {\n const abs = path.resolve(manifestPath)\n if (!existsSync(abs)) throw new Error(`No manifest at ${abs}`)\n const input = ManifestInputSchema.safeParse(JSON.parse(await readFile(abs, \"utf8\")))\n if (!input.success) {\n const issues = formatManifestIssues(input.error.issues)\n throw new Error(`Manifest at ${abs} is invalid:\\n${issues}`)\n }\n let styles: Record<string, Style>\n try {\n styles = resolveStyleInheritance(input.data.styles)\n } catch (error) {\n throw new Error(\n `Manifest at ${abs} is invalid:\\n ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n const parsed = ManifestSchema.safeParse({ ...input.data, styles })\n if (!parsed.success) {\n const issues = formatManifestIssues(parsed.error.issues)\n throw new Error(`Manifest at ${abs} is invalid:\\n${issues}`)\n }\n const styleIds = new Set(Object.keys(parsed.data.styles))\n const unknownReferences: string[] = []\n for (const [assetId, asset] of Object.entries(parsed.data.assets)) {\n for (const styleId of asset.styles) {\n if (!styleIds.has(styleId)) unknownReferences.push(`assets.${assetId}.styles: unknown style \"${styleId}\"`)\n }\n for (const styleId of Object.keys(asset.promptByStyle)) {\n if (!styleIds.has(styleId)) {\n unknownReferences.push(`assets.${assetId}.promptByStyle: unknown style \"${styleId}\"`)\n }\n }\n if (asset.revision) {\n if (!parsed.data.assets[asset.revision.from]) {\n unknownReferences.push(\n `assets.${assetId}.revision.from: unknown asset \"${asset.revision.from}\"`,\n )\n } else if (asset.revision.from === assetId) {\n unknownReferences.push(`assets.${assetId}.revision.from: an asset cannot revise itself`)\n }\n }\n }\n const visiting = new Set<string>()\n const visited = new Set<string>()\n const visitRevision = (assetId: string, chain: string[]) => {\n if (visited.has(assetId)) return\n if (visiting.has(assetId)) {\n const start = chain.indexOf(assetId)\n unknownReferences.push(\n `assets.${assetId}.revision.from: revision cycle ${[...chain.slice(start), assetId].join(\" -> \")}`,\n )\n return\n }\n visiting.add(assetId)\n const parent = parsed.data.assets[assetId]?.revision?.from\n if (parent && parent !== assetId && parsed.data.assets[parent]) {\n visitRevision(parent, [...chain, assetId])\n }\n visiting.delete(assetId)\n visited.add(assetId)\n }\n for (const assetId of Object.keys(parsed.data.assets)) visitRevision(assetId, [])\n if (unknownReferences.length) {\n throw new Error(`Manifest at ${abs} is invalid:\\n${unknownReferences.map((i) => ` ${i}`).join(\"\\n\")}`)\n }\n return { manifest: parsed.data, root: path.dirname(abs), path: abs }\n}\n\nfunction formatManifestIssues(issues: ZodIssue[]): string {\n return issues.flatMap((issue): string[] => {\n if (issue.code === \"invalid_union\") {\n return issue.unionErrors.flatMap((error) => formatManifestIssues(error.issues).split(\"\\n\"))\n }\n return [` ${issue.path.join(\".\")}: ${issue.message}`]\n }).join(\"\\n\")\n}\n\n/** Resolve child styles without carrying the inheritance marker into runtime state. */\nfunction resolveStyleInheritance(styles: Record<string, StyleInput>): Record<string, Style> {\n const resolved = new Map<string, Style>()\n\n const visit = (styleId: string, chain: string[]): Style => {\n const cached = resolved.get(styleId)\n if (cached) return cached\n const cycleStart = chain.indexOf(styleId)\n if (cycleStart >= 0) {\n throw new Error(\n `styles.${styleId}.extends: inheritance cycle ` +\n `${[...chain.slice(cycleStart), styleId].join(\" -> \")}`,\n )\n }\n const style = styles[styleId]\n if (!style) throw new Error(`styles.${styleId}: unknown style`)\n if (!(\"extends\" in style)) {\n resolved.set(styleId, style)\n return style\n }\n\n const parentId = style.extends\n if (!Object.hasOwn(styles, parentId)) {\n throw new Error(`styles.${styleId}.extends: unknown style \"${parentId}\"`)\n }\n const parent = visit(parentId, [...chain, styleId])\n const { extends: _parent, ...child } = style\n const merged = {\n ...parent,\n ...child,\n quality:\n child.quality == null\n ? parent.quality\n : { ...(parent.quality ?? {}), ...child.quality },\n providerOptions: mergeProviderOptions(parent.providerOptions, child.providerOptions),\n }\n const parsed = StyleSchema.safeParse(merged)\n if (!parsed.success) {\n const issues = parsed.error.issues\n .map((issue) => `styles.${styleId}.${issue.path.join(\".\")}: ${issue.message}`)\n .join(\"; \")\n throw new Error(issues)\n }\n resolved.set(styleId, parsed.data)\n return parsed.data\n }\n\n return Object.fromEntries(Object.keys(styles).map((styleId) => [styleId, visit(styleId, [])]))\n}\n\nfunction mergeProviderOptions(\n parent: Record<string, Record<string, unknown>>,\n child: Record<string, Record<string, unknown>> | undefined,\n): Record<string, Record<string, unknown>> {\n if (!child) return parent\n const merged = { ...parent }\n for (const [provider, options] of Object.entries(child)) {\n merged[provider] = { ...(parent[provider] ?? {}), ...options }\n }\n return merged\n}\n\n/**\n * Expands the manifest into one concrete spec per (style, asset) pair. This is\n * where a style becomes a namespace: adding a style re-derives the entire asset\n * set under a separate output root and separate lock keys, which is what makes\n * a whole-collection restyle a one-flag operation.\n */\nexport async function resolveSpecs(\n loaded: LoadedManifest,\n filter?: {\n styles?: string[]\n assets?: string[]\n /** Optional provider makes offline plan cost/candidate estimates adapter-owned. */\n provider?: Pick<\n Provider,\n | \"supports\"\n | \"supportsRevision\"\n | \"estimate\"\n | \"validate\"\n | \"resolveOptions\"\n | \"resolveInputs\"\n | \"id\"\n >\n },\n): Promise<ResolvedSpec[]> {\n const { manifest, root } = loaded\n // The explicit provider remains a whole-resolution override for existing\n // library callers and diagnostics. Normal manifest resolution constructs\n // one offline adapter per effective style provider.\n const providerOverride = filter?.provider\n const providers = new Map<string, Pick<\n Provider,\n | \"supports\"\n | \"supportsRevision\"\n | \"estimate\"\n | \"validate\"\n | \"resolveOptions\"\n | \"resolveInputs\"\n | \"id\"\n >>()\n const providerFor = (id: string) => {\n if (providerOverride) return providerOverride\n let provider = providers.get(id)\n if (!provider) {\n provider = createProvider(id, \"offline\")\n providers.set(id, provider)\n }\n return provider\n }\n const specs: ResolvedSpec[] = []\n\n const styleIds = Object.keys(manifest.styles).filter(\n (id) => !filter?.styles?.length || filter.styles.includes(id),\n )\n for (const unknownStyle of filter?.styles ?? []) {\n if (!manifest.styles[unknownStyle]) {\n throw new Error(\n `Unknown style \"${unknownStyle}\". Defined: ${Object.keys(manifest.styles).join(\", \") || \"(none)\"}`,\n )\n }\n }\n for (const unknownAsset of filter?.assets ?? []) {\n if (!manifest.assets[unknownAsset]) {\n throw new Error(`Unknown asset \"${unknownAsset}\".`)\n }\n }\n\n const requestedAssetIds = new Set(filter?.assets?.length\n ? filter.assets\n : Object.keys(manifest.assets))\n const resolutionAssetIds = new Set(requestedAssetIds)\n for (const assetId of [...requestedAssetIds]) {\n let current = manifest.assets[assetId]?.revision?.from\n while (current && !resolutionAssetIds.has(current)) {\n resolutionAssetIds.add(current)\n current = manifest.assets[current]?.revision?.from\n }\n }\n\n // Style images are hashed, not just named: editing a reference image must\n // invalidate every spec that depends on it.\n const styleImageCache = new Map<\n string,\n { base64: string; hash: string; width: number; height: number; format: \"png\" | \"jpeg\" }\n >()\n async function loadStyleImage(rel: string) {\n const abs = path.resolve(root, rel)\n let hit = styleImageCache.get(abs)\n if (!hit) {\n if (!existsSync(abs)) throw new Error(`Style image not found: ${abs}`)\n const buf = await readFile(abs)\n const metadata = imageMetadata(buf)\n if (!metadata) throw new Error(`Style image is not a readable PNG or JPEG: ${abs}`)\n if (metadata.width < 1 || metadata.height < 1) {\n throw new Error(`Style image has invalid dimensions: ${abs}`)\n }\n hit = { base64: buf.toString(\"base64\"), hash: sha256(buf), ...metadata }\n styleImageCache.set(abs, hit)\n }\n return hit\n }\n\n for (const styleId of styleIds) {\n const style = manifest.styles[styleId]!\n const activeProvider = providerFor(style.provider ?? manifest.provider)\n const rawProviderOptions = style.providerOptions[activeProvider.id] ?? {}\n const optionResolution = activeProvider.resolveOptions\n ? await activeProvider.resolveOptions(rawProviderOptions, { root, styleId })\n : { options: rawProviderOptions }\n const providerOptions = optionResolution.options\n const providerOptionIdentity = optionResolution.identity ?? providerOptions\n const styleImageHashes: string[] = []\n const styleImageDimensions: { width: number; height: number }[] = []\n for (const img of style.styleImages) {\n const loadedImage = await loadStyleImage(img.path)\n styleImageHashes.push(loadedImage.hash)\n styleImageDimensions.push(loadedImage)\n }\n\n const resolvedImages = style.styleImages.map((image) => {\n const hit = styleImageCache.get(path.resolve(root, image.path))!\n return { base64: hit.base64, width: hit.width, height: hit.height, format: hit.format }\n })\n const styleSpecs = new Map<string, ResolvedSpec>()\n const providerInputIdentities = new Map<string, unknown>()\n\n for (const [assetId, asset] of Object.entries(manifest.assets)) {\n if (!resolutionAssetIds.has(assetId)) continue\n if (asset.styles.length && !asset.styles.includes(styleId)) continue\n\n const generator = style.generator\n if (!activeProvider.supports(generator)) {\n throw new Error(`Provider \"${activeProvider.id}\" does not support generator \"${generator}\"`)\n }\n if (Object.keys(asset.providerInputs).length && !activeProvider.resolveInputs) {\n throw new Error(\n `Provider \"${activeProvider.id}\" does not support asset providerInputs ` +\n `(${styleId}/${assetId})`,\n )\n }\n const inputResolution = activeProvider.resolveInputs\n ? await activeProvider.resolveInputs(asset.providerInputs, {\n root,\n styleId,\n assetId,\n generator,\n providerOptions,\n })\n : { inputs: {} }\n const providerInputs = inputResolution.inputs\n const providerInputIdentity = inputResolution.identity ?? providerInputs\n providerInputIdentities.set(assetId, providerInputIdentity)\n let width: number\n let height: number\n let size: number\n\n if (generator === \"1dir\") {\n // Square only. When style images are in play the API derives the size\n // from the largest reference, so the manifest's `size` is advisory.\n size = styleImageDimensions.length\n ? Math.max(...styleImageDimensions.flatMap((img) => [img.width, img.height]))\n : (asset.size ?? style.size ?? 64)\n width = size\n height = size\n } else if (generator === \"tiles\") {\n // Style mode copies the reference geometry; otherwise the endpoint\n // uses tileSize. Asset-level map dimensions do not apply to tiles.\n width = styleImageDimensions.length\n ? Math.max(...styleImageDimensions.map((img) => img.width))\n : (style.tileSize ?? 32)\n height = styleImageDimensions.length\n ? Math.max(...styleImageDimensions.map((img) => img.height))\n : (style.tileSize ?? 32)\n size = Math.max(width, height)\n } else {\n width = asset.width ?? style.size ?? 64\n height = asset.height ?? style.size ?? 64\n size = Math.max(width, height)\n }\n\n // A per-style override replaces the subject wording, not the style\n // wrapping — prefix and suffix still apply.\n const subject = asset.promptByStyle[styleId] ?? asset.prompt\n const prompt = [style.promptPrefix, subject, style.promptSuffix]\n .map((p) => p.trim())\n .filter(Boolean)\n .join(\", \")\n\n const relFile = asset.file ?? path.join(asset.category ?? \"\", `${assetId}.png`)\n const outFile = path.resolve(root, style.outDir, relFile)\n const qualityOutFile = style.quality\n ? path.resolve(root, style.quality.outDir, pngPath(relFile))\n : undefined\n\n // One `tiles` call draws a whole set, so its price and its candidate\n // count both come off the set rather than off a single sprite.\n const tileSize = generator === \"tiles\" ? size : (style.tileSize ?? 32)\n const tileVariations =\n tileFeatureOutputCount(generator === \"tiles\" ? style.tileFeature : undefined) ??\n tileVariationCount(countNumberedDescriptions(prompt))\n\n const base = {\n styleId,\n assetId,\n provider: activeProvider.id,\n providerOptions,\n providerInputs,\n generator,\n prompt,\n width,\n height,\n size,\n view: style.view ?? (generator === \"1dir\" ? \"top-down\" : \"high top-down\"),\n styleImagePaths: style.styleImages.map((s) => s.path),\n outline: style.outline,\n shading: style.shading,\n detail: style.detail,\n seed: style.seed,\n palette: style.palette,\n noBackground: style.noBackground,\n tileSize: generator === \"tiles\" ? tileSize : undefined,\n tileType: generator === \"tiles\" ? style.tileType : undefined,\n tileView: generator === \"tiles\" ? style.tileView : undefined,\n tileFeature: generator === \"tiles\" ? style.tileFeature : undefined,\n outlineMode: generator === \"tiles\" ? style.outlineMode : undefined,\n cost:\n generator === \"tiles\"\n ? tilesCost(tileSize, tileVariations)\n : generationCost(width, height, generator),\n costUnit: \"generations\" as const,\n candidates:\n generator === \"tiles\"\n ? tileVariations\n : generator === \"1dir\"\n ? candidateCount(size)\n : 1,\n }\n\n const tags = [\n ...new Set([\n ...style.tags,\n ...asset.tags,\n `pixelkiln:${manifest.name}`,\n `asset:${assetId}`,\n `style:${styleId}`,\n ]),\n ]\n const resolved: ResolvedSpec = {\n ...base,\n root,\n outFile,\n ...(style.quality && qualityOutFile\n ? {\n quality: {\n outFile: qualityOutFile,\n palette: style.quality.palette,\n minGridConfidence: style.quality.minGridConfidence,\n ...(style.quality.minTransparency == null\n ? {}\n : { minTransparency: style.quality.minTransparency }),\n ...(style.quality.fixerRevision\n ? { fixerRevision: style.quality.fixerRevision }\n : {}),\n ...(style.quality.fixerPython\n ? { fixerPython: path.resolve(root, style.quality.fixerPython) }\n : {}),\n ...(style.quality.fps == null ? {} : { fps: style.quality.fps }),\n },\n }\n : {}),\n tags,\n source: asset.source,\n // Revision identity is attached after every dependency in this style\n // has a concrete output target. Finalization below computes the hash.\n specHash: \"\",\n }\n styleSpecs.set(assetId, resolved)\n }\n\n const finalized = new Set<string>()\n const finalize = async (assetId: string): Promise<ResolvedSpec> => {\n const resolved = styleSpecs.get(assetId)\n if (!resolved) {\n throw new Error(\n `Asset \"${assetId}\" is not available in style \"${styleId}\"; ` +\n \"revision parents must participate in the same style.\",\n )\n }\n if (finalized.has(assetId)) return resolved\n const asset = manifest.assets[assetId]!\n if (asset.revision) {\n if (!activeProvider.supportsRevision?.(asset.revision.mode)) {\n throw new Error(\n `Provider \"${activeProvider.id}\" does not support ${asset.revision.mode} revisions`,\n )\n }\n const sourceSpec = await finalize(asset.revision.from)\n const sourceFile = sourceSpec.quality?.outFile ??\n (sourceSpec.source ? path.resolve(root, sourceSpec.source) : sourceSpec.outFile)\n const sourceImage = await optionalRevisionImage(sourceFile, \"revision source\")\n const maskFile = asset.revision.mask\n ? path.resolve(root, asset.revision.mask)\n : undefined\n const maskImage = maskFile\n ? await optionalRevisionImage(maskFile, \"revision mask\", \"png\")\n : null\n if (\n sourceImage && maskImage &&\n (sourceImage.width !== maskImage.width || sourceImage.height !== maskImage.height)\n ) {\n throw new Error(\n `Revision mask for ${styleId}/${assetId} is ${maskImage.width}x${maskImage.height}; ` +\n `source ${asset.revision.from} is ${sourceImage.width}x${sourceImage.height}`,\n )\n }\n resolved.revision = {\n mode: asset.revision.mode,\n sourceAssetId: asset.revision.from,\n sourceFile,\n sourceSha256: sourceImage?.hash ?? null,\n sourceWidth: sourceImage?.width ?? null,\n sourceHeight: sourceImage?.height ?? null,\n sourceFormat: sourceImage?.format ?? null,\n sourceSpec,\n ...(maskFile\n ? {\n maskFile,\n maskSha256: maskImage?.hash ?? null,\n maskWidth: maskImage?.width ?? null,\n maskHeight: maskImage?.height ?? null,\n maskFormat: maskImage?.format ?? null,\n }\n : {}),\n ...(asset.revision.strength == null ? {} : { strength: asset.revision.strength }),\n }\n }\n resolved.specHash = specHash(\n resolved,\n styleImageHashes,\n providerOptionIdentity,\n providerInputIdentities.get(assetId),\n )\n activeProvider.validate?.(resolved, resolvedImages)\n const estimate = validateCostEstimate(activeProvider.id, activeProvider.estimate(resolved))\n resolved.cost = estimate.amount\n resolved.costUnit = estimate.unit\n resolved.candidates = estimate.candidates\n finalized.add(assetId)\n return resolved\n }\n\n for (const assetId of Object.keys(manifest.assets)) {\n if (!requestedAssetIds.has(assetId) || !styleSpecs.has(assetId)) continue\n specs.push(await finalize(assetId))\n }\n }\n\n const byOutput = new Map<string, string>()\n const claimOutput = (file: string, owner: string) => {\n const existing = byOutput.get(file)\n if (existing) {\n throw new Error(`Output collision: ${existing} and ${owner} both resolve to ${file}`)\n }\n byOutput.set(file, owner)\n }\n for (const spec of specs) {\n const key = `${spec.styleId}/${spec.assetId}`\n claimOutput(spec.outFile, key)\n if (spec.quality) {\n if (spec.generator === \"frames\") {\n const frameInputs = Object.values(spec.providerInputs ?? {}).find(Array.isArray)\n const count = frameInputs?.length ?? 0\n for (let index = 0; index < count; index++) {\n const role = `frame-${String(index).padStart(2, \"0\")}`\n claimOutput(\n expectedOutputPath(\n { ...spec, outFile: spec.quality.outFile },\n role,\n index,\n count,\n MediaType.PNG,\n ),\n `${key} quality ${role}`,\n )\n }\n } else {\n claimOutput(spec.quality.outFile, `${key} quality output`)\n }\n }\n }\n\n return specs\n}\n\nfunction pngPath(file: string): string {\n const extension = path.extname(file)\n return extension ? `${file.slice(0, -extension.length)}.png` : `${file}.png`\n}\n\nasync function optionalRevisionImage(\n file: string,\n label: string,\n requiredFormat?: \"png\" | \"jpeg\",\n): Promise<{ hash: string; width: number; height: number; format: \"png\" | \"jpeg\" } | null> {\n if (!existsSync(file)) return null\n const bytes = await readFile(file)\n const metadata = imageMetadata(bytes)\n if (!metadata) throw new Error(`${label} is not a readable PNG or JPEG: ${file}`)\n if (requiredFormat && metadata.format !== requiredFormat) {\n throw new Error(`${label} must be ${requiredFormat.toUpperCase()}: ${file}`)\n }\n return { hash: sha256(bytes), ...metadata }\n}\n\n/** Reference image bytes and measured dimensions, in manifest order. */\nexport async function resolveStyleImages(\n loaded: LoadedManifest,\n styleId: string,\n): Promise<ResolvedStyleImage[]> {\n const style = loaded.manifest.styles[styleId]\n if (!style) throw new Error(`Unknown style \"${styleId}\"`)\n const out: ResolvedStyleImage[] = []\n for (const img of style.styleImages) {\n const file = path.resolve(loaded.root, img.path)\n const buf = await readFile(file)\n const metadata = imageMetadata(buf)\n if (!metadata) throw new Error(`Style image is not a readable PNG or JPEG: ${file}`)\n if (metadata.width < 1 || metadata.height < 1) {\n throw new Error(`Style image has invalid dimensions: ${file}`)\n }\n out.push({ base64: buf.toString(\"base64\"), ...metadata })\n }\n return out\n}\n\n/** Retained for callers that only need the encoded bytes. */\nexport async function styleImagesBase64(loaded: LoadedManifest, styleId: string): Promise<string[]> {\n return (await resolveStyleImages(loaded, styleId)).map((img) => img.base64)\n}\n\n/** Reads dimensions without decoding pixel data. */\nexport function imageMetadata(\n buf: Buffer,\n): Pick<ResolvedStyleImage, \"width\" | \"height\" | \"format\"> | null {\n if (\n buf.length >= 24 &&\n buf.readUInt32BE(0) === 0x89504e47 &&\n buf.readUInt32BE(4) === 0x0d0a1a0a &&\n buf.toString(\"ascii\", 12, 16) === \"IHDR\"\n ) {\n return { width: buf.readUInt32BE(16), height: buf.readUInt32BE(20), format: \"png\" }\n }\n\n if (buf.length < 4 || buf[0] !== 0xff || buf[1] !== 0xd8) return null\n let offset = 2\n while (offset + 3 < buf.length) {\n if (buf[offset] !== 0xff) return null\n while (buf[offset] === 0xff) offset++\n const marker = buf[offset++]\n if (marker == null || marker === 0xd9 || marker === 0xda) break\n if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7)) continue\n if (offset + 2 > buf.length) return null\n const length = buf.readUInt16BE(offset)\n if (length < 2 || offset + length > buf.length) return null\n const isStartOfFrame =\n marker >= 0xc0 &&\n marker <= 0xcf &&\n ![0xc4, 0xc8, 0xcc].includes(marker)\n if (isStartOfFrame) {\n if (length < 7) return null\n return {\n width: buf.readUInt16BE(offset + 5),\n height: buf.readUInt16BE(offset + 3),\n format: \"jpeg\",\n }\n }\n offset += length\n }\n return null\n}\n","import path from \"node:path\"\nimport { upsert } from \"./lock.ts\"\nimport { mediaExtension, type MediaType } from \"./media.ts\"\nimport { lockKey, type Lock, type LockEntry, type LockOutput, type ResolvedSpec } from \"./types.ts\"\n\n/** One lockfile output with the identity consumers should expose publicly. */\nexport interface ResolvedOutput extends LockOutput {\n assetId: string\n /** Stable within a style's atlas or report. Single-output assets keep their old id. */\n id: string\n index: number\n absolutePath: string\n}\n\n/** Store generated paths relative to the manifest so committed locks survive a clone/move. */\nexport function portableOutputPath(file: string, manifestDir: string): string {\n const root = path.resolve(manifestDir)\n const absolute = path.isAbsolute(file) ? path.normalize(file) : path.resolve(root, file)\n const relative = path.relative(root, absolute)\n // Different Windows drives cannot be expressed as a relative path. This is\n // the one case where retaining an absolute path is more honest than writing\n // a value that resolves somewhere else.\n const value = path.isAbsolute(relative) ? absolute : relative\n return value.split(path.sep).join(\"/\")\n}\n\n/** Resolve a portable lock path against the manifest, never the process cwd. */\nexport function resolveOutputPath(recordedPath: string, manifestDir: string): string {\n if (path.isAbsolute(recordedPath)) return path.normalize(recordedPath)\n // A lock committed by Windows before paths became portable cannot be opened\n // directly on POSIX. `normalizeLockOutputPaths` rebases it from the spec.\n if (path.win32.isAbsolute(recordedPath)) return recordedPath\n return path.resolve(manifestDir, recordedPath.split(/[\\\\/]/).join(path.sep))\n}\n\n/** Deterministic current destination for one provider output. */\nexport function expectedOutputPath(\n spec: ResolvedSpec,\n role: string | undefined,\n index: number,\n total: number,\n mediaType?: MediaType,\n): string {\n const originalExt = path.extname(spec.outFile)\n const ext = mediaType ? mediaExtension(mediaType) : (originalExt || \".png\")\n const stem = originalExt ? spec.outFile.slice(0, -originalExt.length) : spec.outFile\n if (total === 1) return `${stem}${ext}`\n const safeRole = (role ?? fallbackOutputRole(index)).replace(/[^a-zA-Z0-9_-]+/g, \"-\")\n return `${stem}-${safeRole}${ext}`\n}\n\n/** Resolve one recorded output from the current manifest-owned destination. */\nexport function currentOutputPath(\n output: Pick<LockOutput, \"path\" | \"role\" | \"mediaType\">,\n spec: ResolvedSpec,\n index: number,\n total: number,\n): string {\n // The lock records where bytes were written; the manifest owns where they\n // belong now. Always deriving from the current spec both rebases a clone and\n // prevents a hand-edited lock path from redirecting restore into an unrelated\n // project file. Output roles preserve structural-set identity.\n return expectedOutputPath(spec, output.role, index, total, output.mediaType)\n}\n\n/** Resolve an entry member using the complete source-set order when available. */\nexport function currentEntryOutputPath(\n entry: LockEntry,\n spec: ResolvedSpec,\n index: number,\n): string {\n const output = entry.outputs[index]!\n const sourceIndex = output.role\n ? (entry.sourceUrls ?? []).findIndex((source) => source.role === output.role)\n : -1\n const position = sourceIndex >= 0 ? sourceIndex : index\n const total = Math.max(entry.outputs.length, entry.sourceUrls?.length ?? 0)\n return currentOutputPath(output, spec, position, total)\n}\n\n/**\n * Rebase legacy absolute output paths onto this checkout and canonicalize all\n * selected entries in memory. Persistence remains the caller's decision.\n */\nexport function normalizeLockOutputPaths(lock: Lock, specs: ResolvedSpec[]): number {\n const byKey = new Map(specs.map((spec) => [lockKey(spec.styleId, spec.assetId), spec]))\n let changed = 0\n for (const [key, entry] of Object.entries(lock.entries)) {\n const spec = byKey.get(key)\n if (!spec) continue\n let entryChanged = false\n const outputs = entry.outputs.map((output, index) => {\n const absolute = currentEntryOutputPath(entry, spec, index)\n const portable = portableOutputPath(absolute, spec.root)\n if (portable === output.path) return output\n changed++\n entryChanged = true\n return { ...output, path: portable }\n })\n if (entryChanged) upsert(lock, key, { outputs })\n }\n return changed\n}\n\n/** The fallback role used when a provider returns several unnamed outputs. */\nexport function fallbackOutputRole(index: number): string {\n return `output-${String(index).padStart(2, \"0\")}`\n}\n\n/**\n * Gives every output a stable, collision-resistant consumer id.\n *\n * A conventional one-file asset remains `grass`, preserving existing atlas\n * lookups. A structural set becomes `grass/tile-00`, `grass/tile-01`, … so no\n * downstream command has to silently pretend its first file is the whole set.\n */\nexport function outputId(\n assetId: string,\n output: Pick<LockOutput, \"role\">,\n index: number,\n total: number,\n): string {\n if (total === 1) return assetId\n return `${assetId}/${output.role ?? fallbackOutputRole(index)}`\n}\n\n/** Resolve every output recorded for one manifest asset, preserving lock order. */\nexport function resolveEntryOutputs(\n entry: LockEntry,\n assetId: string,\n manifestDir: string,\n): ResolvedOutput[] {\n return entry.outputs.map((output, index) => ({\n ...output,\n assetId,\n id: outputId(assetId, output, index, entry.outputs.length),\n index,\n absolutePath: resolveOutputPath(output.path, manifestDir),\n }))\n}\n\n/** Resolve an entry using its current spec, including cross-checkout v2 migration. */\nexport function resolveSpecEntryOutputs(\n entry: LockEntry,\n spec: ResolvedSpec,\n): ResolvedOutput[] {\n return entry.outputs.map((output, index) => ({\n ...output,\n assetId: spec.assetId,\n id: outputId(spec.assetId, output, index, entry.outputs.length),\n index,\n absolutePath: currentEntryOutputPath(entry, spec, index),\n }))\n}\n\n/** Resolve all outputs for a style in deterministic asset-id order. */\nexport function resolveStyleOutputs(\n lock: Lock,\n styleId: string,\n manifestDir: string,\n): ResolvedOutput[] {\n const prefix = `${styleId}/`\n return Object.entries(lock.entries)\n .filter(([key]) => key.startsWith(prefix))\n .sort(([a], [b]) => a.localeCompare(b))\n .flatMap(([key, entry]) =>\n resolveEntryOutputs(entry, key.slice(prefix.length), manifestDir),\n )\n}\n\nexport type OutputSelection =\n | { ok: true; output: LockOutput }\n | { ok: false; reason: string }\n\n/**\n * Select the one output needed by a single-cell consumer such as `mount`.\n * Multi-output sets are deliberately ambiguous unless the manifest names a\n * role; choosing index zero is silent data loss disguised as convenience.\n */\nexport function selectEntryOutput(entry: LockEntry, role?: string): OutputSelection {\n if (role) {\n const output = entry.outputs.find((candidate) => candidate.role === role)\n return output\n ? { ok: true, output }\n : { ok: false, reason: `output role \"${role}\" is not recorded` }\n }\n if (entry.outputs.length === 0) return { ok: false, reason: \"no output recorded in the lockfile\" }\n if (entry.outputs.length === 1) return { ok: true, output: entry.outputs[0]! }\n\n const primary = entry.outputs.filter((output) => !output.role)\n if (primary.length === 1) return { ok: true, output: primary[0]! }\n return {\n ok: false,\n reason: `${entry.outputs.length} outputs are recorded; set \\`outputRole\\` to choose one`,\n }\n}\n\n/** Lock outputs for a resolved spec, or its conventional path before adoption. */\nexport function resolveSpecOutputs(\n spec: ResolvedSpec,\n lock: Lock | undefined,\n manifestDir: string,\n): ResolvedOutput[] {\n const entry = lock?.entries[lockKey(spec.styleId, spec.assetId)]\n if (entry?.outputs.length) return resolveSpecEntryOutputs(entry, spec)\n return [{\n assetId: spec.assetId,\n id: spec.assetId,\n index: 0,\n path: spec.outFile,\n absolutePath: path.resolve(spec.outFile),\n sha256: \"\",\n }]\n}\n","import { readFile, writeFile, rename, mkdir, rmdir, rm, stat } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { parseLock, type Lock, type LockEntry } from \"./types.ts\"\nimport type { CostUnit } from \"./provider.ts\"\n\n/**\n * The lockfile is the record that maps a spec to the provider work that\n * satisfies it and the file on disk that came from it. It is written after\n * every state transition — including immediately after submitting, before the\n * job is awaited — so an interrupted run never loses track of paid-for work.\n */\nexport async function loadLock(lockPath: string): Promise<Lock> {\n if (!existsSync(lockPath)) return { version: 2, entries: {} }\n try {\n return parseLock(JSON.parse(await readFile(lockPath, \"utf8\")))\n } catch (err) {\n throw new Error(\n `Lockfile at ${lockPath} is malformed:\\n${err instanceof Error ? err.message : String(err)}`,\n )\n }\n}\n\n/**\n * Serializes saves per path.\n *\n * Concurrent stages (parallel downloads in `fetch`) each save after their own\n * upsert. Without this they race on the shared `<path>.tmp`: one worker's\n * rename moves the file out from under another's, which fails with ENOENT and\n * loses that write. Queuing keeps the atomic write-then-rename intact and\n * guarantees the last save reflects the latest in-memory state.\n */\nconst saveQueues = new Map<string, Promise<void>>()\nconst dirtyPatches = new WeakMap<Lock, Map<string, Partial<LockEntry>>>()\nconst dirtyDeletes = new WeakMap<Lock, Set<string>>()\n\n/** Atomic write — a crash mid-save must not leave a truncated lockfile. */\nexport function saveLock(lockPath: string, lock: Lock): Promise<void> {\n const queueKey = path.resolve(lockPath)\n const previous = saveQueues.get(queueKey) ?? Promise.resolve()\n const next = previous\n .catch(() => {}) // one failed save must not poison every later one\n .then(() => writeLockNow(lockPath, lock))\n saveQueues.set(queueKey, next)\n // Drop the queue entry once drained so long-lived processes don't retain it.\n const cleanup = () => {\n if (saveQueues.get(queueKey) === next) saveQueues.delete(queueKey)\n }\n // Using `finally()` here would create a second rejected promise when a save\n // fails. If nobody observes that derived promise Node reports an unhandled\n // rejection even when the caller correctly handles `next`.\n void next.then(cleanup, cleanup)\n return next\n}\n\nasync function writeLockNow(lockPath: string, lock: Lock): Promise<void> {\n await mkdir(path.dirname(path.resolve(lockPath)), { recursive: true })\n const release = await acquireFileLock(lockPath)\n try {\n await writeLockWhileHeld(lockPath, lock)\n } finally {\n await release()\n }\n}\n\nasync function writeLockWhileHeld(file: string, lock: Lock): Promise<void> {\n let disk: Lock = { version: 2, entries: {} }\n if (existsSync(file)) {\n try {\n disk = parseLock(JSON.parse(await readFile(file, \"utf8\")))\n } catch (err) {\n throw new Error(\n `Refusing to overwrite malformed lockfile at ${file}: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n\n const dirty = dirtyPatches.get(lock) ?? new Map<string, Partial<LockEntry>>()\n const snapshot = new Map<string, Partial<LockEntry>>()\n for (const [key, patch] of dirty) snapshot.set(key, { ...patch })\n\n const merged: Lock[\"entries\"] = { ...disk.entries }\n for (const [key, patch] of snapshot) {\n const local = lock.entries[key]\n if (!local) continue\n merged[key] = merged[key] ? ({ ...merged[key], ...patch } as LockEntry) : local\n }\n // Preserve entries inserted directly by library callers. Production code\n // uses `upsert`, which additionally gives us field-level merge precision.\n for (const [key, entry] of Object.entries(lock.entries)) {\n if (!merged[key]) merged[key] = entry\n }\n\n // Removals are intents, recorded by `remove`, and are applied last. Merging\n // starts from the disk view so a concurrent writer's entries survive, which\n // means a key deleted only from `lock.entries` is read straight back off\n // disk and silently resurrected. Applying deletions after both merge passes\n // is what makes a removal actually stick.\n const deletes = dirtyDeletes.get(lock)\n const deleteSnapshot = deletes ? new Set(deletes) : new Set<string>()\n for (const key of deleteSnapshot) delete merged[key]\n\n const sorted: Lock[\"entries\"] = {}\n for (const key of Object.keys(merged).sort()) {\n sorted[key] = merged[key]!\n }\n const tmp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`\n try {\n await writeFile(tmp, JSON.stringify({ version: 2, entries: sorted }, null, 2) + \"\\n\")\n await rename(tmp, file)\n } finally {\n await rm(tmp, { force: true })\n }\n\n // Clear only fields included in this snapshot. Mutations made while the\n // write awaited I/O remain dirty and are reapplied to the merged disk view.\n const currentDirty = dirtyPatches.get(lock)\n if (currentDirty) {\n for (const [key, patch] of snapshot) {\n const current = currentDirty.get(key)\n if (!current) continue\n for (const [field, value] of Object.entries(patch)) {\n if (Object.is(current[field as keyof LockEntry], value)) {\n delete current[field as keyof LockEntry]\n }\n }\n if (Object.keys(current).length === 0) currentDirty.delete(key)\n }\n }\n\n const stillDirty = dirtyDeletes.get(lock)\n if (stillDirty) {\n for (const key of deleteSnapshot) stillDirty.delete(key)\n if (stillDirty.size === 0) dirtyDeletes.delete(lock)\n }\n\n const localAfterWrite = lock.entries\n lock.entries = { ...merged }\n for (const [key, patch] of currentDirty ?? []) {\n const base = lock.entries[key] ?? localAfterWrite[key]\n if (base) lock.entries[key] = { ...base, ...patch } as LockEntry\n }\n}\n\nexport function upsert(lock: Lock, key: string, patch: Partial<LockEntry>): LockEntry {\n // Re-adding a key cancels any pending removal, or the save would delete the\n // entry that was just written.\n dirtyDeletes.get(lock)?.delete(key)\n const existing = lock.entries[key]\n const next = { ...existing, ...patch } as LockEntry\n lock.entries[key] = next\n let dirty = dirtyPatches.get(lock)\n if (!dirty) {\n dirty = new Map()\n dirtyPatches.set(lock, dirty)\n }\n dirty.set(key, { ...(dirty.get(key) ?? {}), ...patch })\n return next\n}\n\n/**\n * Drop a lock entry, and record the removal so the next save honours it.\n *\n * Deleting from `lock.entries` alone does nothing: `writeLockWhileHeld` merges\n * onto whatever is on disk, so the entry is read back and restored. Callers\n * that need an entry gone must come through here. Returns false when the key\n * was not present, so a caller can tell a no-op from a removal.\n */\nexport function remove(lock: Lock, key: string): boolean {\n if (!lock.entries[key]) return false\n delete lock.entries[key]\n const patches = dirtyPatches.get(lock)\n if (patches) {\n patches.delete(key)\n if (patches.size === 0) dirtyPatches.delete(lock)\n }\n let deletes = dirtyDeletes.get(lock)\n if (!deletes) {\n deletes = new Set()\n dirtyDeletes.set(lock, deletes)\n }\n deletes.add(key)\n return true\n}\n\nconst FILE_LOCK_TIMEOUT_MS = 10_000\nconst STALE_FILE_LOCK_MS = 2 * 60 * 1000\n\nasync function acquireFileLock(file: string): Promise<() => Promise<void>> {\n const lockDir = `${file}.lock`\n const deadline = Date.now() + FILE_LOCK_TIMEOUT_MS\n for (;;) {\n try {\n await mkdir(lockDir)\n return async () => {\n await rmdir(lockDir).catch(() => {})\n }\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code\n if (code !== \"EEXIST\") throw err\n try {\n const age = Date.now() - (await stat(lockDir)).mtimeMs\n if (age > STALE_FILE_LOCK_MS) {\n await rmdir(lockDir)\n continue\n }\n } catch (lockErr) {\n if ((lockErr as NodeJS.ErrnoException).code === \"ENOENT\") continue\n }\n if (Date.now() >= deadline) {\n throw new Error(`Timed out waiting for lockfile writer ${lockDir}`)\n }\n await new Promise((resolve) => setTimeout(resolve, 25 + Math.floor(Math.random() * 25)))\n }\n }\n}\n\n/** Recorded successful-submission estimates, kept separate by provider unit. */\nexport function spendByUnit(lock: Lock): Record<CostUnit, number> {\n const totals: Record<CostUnit, number> = { generations: 0, usd: 0, free: 0 }\n for (const entry of Object.values(lock.entries)) {\n const unit = entry.costUnit ?? \"generations\"\n totals[unit] = (totals[unit] ?? 0) + (entry.cost ?? 0)\n }\n return totals\n}\n\n/** @deprecated Prefer spendByUnit; summing unlike provider units is unsafe. */\nexport function totalSpend(lock: Lock, unit: CostUnit = \"generations\"): number {\n return spendByUnit(lock)[unit] ?? 0\n}\n","import { readFileSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { decodePng, encodeRgbaPng } from \"../png.ts\"\nimport type { Lock } from \"../types.ts\"\nimport { resolveEntryOutputs, resolveOutputPath, selectEntryOutput } from \"../outputs.ts\"\nimport { sha256 } from \"../hash.ts\"\n\nexport interface PackedSource {\n id: string\n /** Absolute source path. Artifact manifests make it relative to themselves. */\n path: string\n /** Null when the source could not be read. */\n sha256: string | null\n /** False when the source was present but could not be decoded or selected. */\n included: boolean\n}\n\nexport interface PackedFrame {\n /** Asset id, so a consumer can look a sprite up by name rather than index. */\n id: string\n x: number\n y: number\n width: number\n height: number\n}\n\nexport interface PackedSheet {\n png: Buffer\n atlas: {\n style: string\n sheet: { width: number; height: number }\n /** Uniform cell the grid was laid out on. Frames may be smaller. */\n cell: { width: number; height: number }\n columns: number\n frames: PackedFrame[]\n }\n /** Assets skipped because their file was missing or unreadable. */\n skipped: { id: string; reason: string }[]\n /** Inputs and their exact bytes, for deterministic derived-artifact provenance. */\n sources: PackedSource[]\n}\n\n/**\n * Composites one style's sprites into a single sheet plus a frame atlas.\n *\n * A grid rather than a bin-packer. Every sprite in a style shares a generator\n * and a size, so rectangles are near-uniform and the gain from tight packing\n * is a few percent of area — not worth the loss of a stable, predictable\n * layout. A grid also means a frame's position is derivable from its index,\n * which matters when someone is reading the sheet by eye to debug it.\n *\n * The cell is the largest sprite in the set. Assets can override width/height\n * individually, so assuming uniformity would silently clip the odd one out.\n * Smaller sprites are placed at the cell's top-left and their real dimensions\n * recorded, rather than being centred: centring would bake half-pixel offsets\n * into odd-sized differences, and a consumer that ignores the atlas and slices\n * on the cell grid still gets a correct — if padded — sprite.\n */\nexport interface SpriteInput {\n /** The name this sprite is looked up by in the atlas. */\n id: string\n /** Absolute path to the PNG. */\n path: string\n}\n\n/**\n * Validates and resolves the JSON contract behind `pack --inputs`.\n *\n * A plain function rather than inline in the CLI so it is testable without\n * spawning the binary: `main()` in cli.ts runs at module load and is not\n * exported, so anything left inline there has no seam a test can reach. This\n * is also the only place that needs to know the file is JSON at all — once it\n * returns, everything downstream just deals in `SpriteInput[]`.\n *\n * `entry.path` resolves relative to `inputsFilePath`'s directory, not the\n * process's cwd, so a caller can write the JSON into a scratch directory\n * without rewriting every entry to be absolute. An already-absolute\n * `entry.path` passes through unchanged, since `path.resolve` discards\n * earlier segments once it hits one.\n */\nexport function resolvePackInputs(raw: unknown, inputsFilePath: string): SpriteInput[] {\n if (!Array.isArray(raw) || !raw.length) {\n throw new Error(\"--inputs must be a non-empty JSON array of { id, path }\")\n }\n const baseDir = path.dirname(path.resolve(inputsFilePath))\n return raw.map((entry, i) => {\n const e = entry as { id?: unknown; path?: unknown }\n if (typeof e.id !== \"string\" || typeof e.path !== \"string\") {\n throw new Error(`--inputs[${i}] needs string \"id\" and \"path\"`)\n }\n return { id: e.id, path: path.resolve(baseDir, e.path) }\n })\n}\n\n/**\n * The packing primitive: an explicit list of sprites in, one sheet out.\n *\n * Separate from `packStyle` because the lockfile is not the only way to decide\n * what belongs on a sheet. A consumer may draw from several manifests, or key\n * frames by its own vocabulary rather than by pixelkiln asset ids — heybud's\n * review-form icons do both. Keeping the pixel work here and the \"which files,\n * called what\" decision at the call site avoids teaching this module about\n * anyone else's naming.\n */\nexport function packSprites(\n inputs: SpriteInput[],\n options: { columns?: number; order?: \"id\" | \"input\" } = {},\n): PackedSheet {\n if (!inputs.length) throw new Error(\"packSprites: no sprites given\")\n\n // Two inputs sharing an id would silently produce two frames under the same\n // key, and a consumer doing `frames.find(f => f.id === x)` gets whichever\n // came first with no signal that the other was dropped. Caught here, before\n // any file I/O, rather than left for the next caller to discover the hard\n // way — heybud's own sync script has to dedupe upstream today for exactly\n // this reason (its archetype sources deliberately overlap).\n const seen = new Set<string>()\n const dupes = new Set<string>()\n for (const input of inputs) {\n if (seen.has(input.id)) dupes.add(input.id)\n seen.add(input.id)\n }\n if (dupes.size) {\n throw new Error(`packSprites: duplicate sprite id(s): ${[...dupes].join(\", \")}`)\n }\n\n // Ordinary sprite atlases sort by id so they are byte-identical across\n // runs. Structural sets opt into provider order because their index is part\n // of the format, not presentation.\n const ordered = options.order === \"input\"\n ? [...inputs]\n : [...inputs].sort((a, b) => a.id.localeCompare(b.id))\n\n const sprites: { id: string; width: number; height: number; pixels: Buffer }[] = []\n const skipped: { id: string; reason: string }[] = []\n const sources: PackedSource[] = []\n\n for (const input of ordered) {\n let sourceHash: string | null = null\n try {\n const bytes = readFileSync(input.path)\n sourceHash = sha256(bytes)\n const png = decodePng(bytes)\n sprites.push({ id: input.id, width: png.width, height: png.height, pixels: png.pixels })\n sources.push({ ...input, sha256: sourceHash, included: true })\n } catch (err) {\n skipped.push({ id: input.id, reason: err instanceof Error ? err.message : String(err) })\n sources.push({ ...input, sha256: sourceHash, included: false })\n }\n }\n\n if (!sprites.length) {\n throw new Error(`packSprites: nothing readable — ${skipped.length} skipped.`)\n }\n\n const cellW = Math.max(...sprites.map((s) => s.width))\n const cellH = Math.max(...sprites.map((s) => s.height))\n const columns = options.columns ?? Math.ceil(Math.sqrt(sprites.length))\n const rows = Math.ceil(sprites.length / columns)\n\n const sheetW = columns * cellW\n const sheetH = rows * cellH\n // Zero-filled means fully transparent, which is what the gaps should be.\n const rgba = Buffer.alloc(sheetW * sheetH * 4)\n const frames: PackedFrame[] = []\n\n sprites.forEach((sprite, i) => {\n const ox = (i % columns) * cellW\n const oy = Math.floor(i / columns) * cellH\n for (let y = 0; y < sprite.height; y++) {\n const src = y * sprite.width * 4\n const dst = ((oy + y) * sheetW + ox) * 4\n sprite.pixels.copy(rgba, dst, src, src + sprite.width * 4)\n }\n frames.push({ id: sprite.id, x: ox, y: oy, width: sprite.width, height: sprite.height })\n })\n\n return {\n png: encodeRgbaPng(sheetW, sheetH, rgba),\n atlas: {\n style: \"\",\n sheet: { width: sheetW, height: sheetH },\n cell: { width: cellW, height: cellH },\n columns,\n frames,\n },\n skipped,\n sources,\n }\n}\n\nexport function packStyle(\n lock: Lock,\n styleId: string,\n manifestDir: string,\n options: {\n columns?: number\n outputRoles?: string[]\n primaryOnly?: boolean\n /** Approved manifest quality outputs keyed by asset id or role-qualified frame id. */\n sourceOverrides?: Record<string, string>\n } = {},\n): PackedSheet {\n if (options.sourceOverrides) {\n if (options.outputRoles?.length) {\n throw new Error(\"Quality-profile packing does not accept --output-role; profiles own final output selection.\")\n }\n const inputs = Object.entries(options.sourceOverrides).map(([id, source]) => ({\n id,\n path: path.resolve(source),\n }))\n if (!inputs.length) throw new Error(`No approved quality outputs for style \"${styleId}\".`)\n const packed = packSprites(inputs, options)\n return { ...packed, atlas: { ...packed.atlas, style: styleId } }\n }\n\n // Lock keys are `<styleId>/<assetId>`.\n const prefix = `${styleId}/`\n const entries = Object.entries(lock.entries).filter(([key]) => key.startsWith(prefix))\n\n if (!entries.length) {\n throw new Error(\n `No locked assets for style \"${styleId}\". Run \\`pixelkiln gen --style ${styleId}\\` first.`,\n )\n }\n\n const inputs: SpriteInput[] = []\n const noOutput: { id: string; reason: string }[] = []\n\n for (const [key, entry] of entries) {\n const id = key.slice(prefix.length)\n const outputs = resolveEntryOutputs(entry, id, manifestDir)\n let selected = outputs\n if (options.outputRoles?.length) {\n selected = outputs.filter(\n (output) => output.role && options.outputRoles!.includes(output.role),\n )\n } else if (options.primaryOnly) {\n const selection = selectEntryOutput(entry)\n selected = selection.ok\n ? outputs.filter((output) => output.path === selection.output.path)\n : []\n }\n if (!selected.length) {\n const reason = options.outputRoles?.length\n ? `no output matches role(s): ${options.outputRoles.join(\", \")}`\n : options.primaryOnly && outputs.length > 1\n ? \"no unambiguous primary output; use --output-role\"\n : \"no output recorded in the lockfile\"\n noOutput.push({ id, reason })\n continue\n }\n for (const output of selected) inputs.push({ id: output.id, path: output.absolutePath })\n }\n\n if (!inputs.length) {\n throw new Error(`No readable sprites for style \"${styleId}\" — ${noOutput.length} skipped.`)\n }\n\n const packed = packSprites(inputs, options)\n return {\n ...packed,\n atlas: { ...packed.atlas, style: styleId },\n skipped: [...noOutput, ...packed.skipped],\n }\n}\n\nexport interface MountPlacement extends SpriteInput {\n /** Grid cell this sprite owns, as [column, row]. */\n cell: [number, number]\n}\n\nexport interface MountedSheet {\n png: Buffer\n atlas: {\n style: string\n sheet: { width: number; height: number }\n cell: { width: number; height: number }\n frames: PackedFrame[]\n }\n skipped: { id: string; reason: string }[]\n /** Inputs and their exact bytes, for deterministic derived-artifact provenance. */\n sources: PackedSource[]\n /** True when an existing sheet was composited into rather than replaced. */\n overBase: boolean\n}\n\n/**\n * Places sprites at *declared* grid cells, optionally into an existing sheet.\n *\n * The sibling of `packSprites`, for the case its layout rules cannot serve.\n * `packSprites` derives position from index and sorts by asset id so the sheet\n * is byte-stable — excellent when pixelkiln owns the whole sheet, and fatal\n * when it does not. A consumer whose atlas coordinates are already load-bearing\n * (a tile engine naming tiles by cell, a scene file storing cell indices in\n * saved data) cannot accept a layout that moves when an asset is added or\n * renamed: every existing reference would silently point at different art.\n *\n * So here the caller declares the cell and pixelkiln honours it. Two\n * consequences worth stating:\n *\n * - **Only declared cells are touched.** With a `base` sheet, every other\n * pixel survives byte-for-byte, so a hand-authored sheet can be part\n * generated and part drawn without the generated half claiming the file.\n * - **A cell is replaced, not blended.** The sprite owns its cell, so the\n * cell is cleared first. Compositing instead would make a regenerated\n * tile show through to whatever it replaced, and the residue would be\n * invisible until it shipped.\n *\n * Sprites larger than the cell are a declaration error, not something to crop\n * silently — cropping would produce a sheet that looks right in isolation and\n * is wrong at every seam.\n */\nexport function mountSprites(\n placements: MountPlacement[],\n options: { cellWidth: number; cellHeight: number; basePng?: Buffer },\n): MountedSheet {\n if (!placements.length) throw new Error(\"mountSprites: no sprites given\")\n const { cellWidth, cellHeight } = options\n if (cellWidth <= 0 || cellHeight <= 0) {\n throw new Error(\"mountSprites: cell dimensions must be positive\")\n }\n\n const byCell = new Map<string, string>()\n for (const p of placements) {\n const key = `${p.cell[0]},${p.cell[1]}`\n const owner = byCell.get(key)\n if (owner) {\n throw new Error(\n `mountSprites: \"${p.id}\" and \"${owner}\" both claim cell ${key} — ` +\n `a cell has exactly one owner`,\n )\n }\n byCell.set(key, p.id)\n }\n\n const loaded: { p: MountPlacement; width: number; height: number; pixels: Buffer }[] = []\n const skipped: { id: string; reason: string }[] = []\n const sources: PackedSource[] = []\n for (const p of placements) {\n let sourceHash: string | null = null\n try {\n const bytes = readFileSync(p.path)\n sourceHash = sha256(bytes)\n const png = decodePng(bytes)\n if (png.width > cellWidth || png.height > cellHeight) {\n throw new Error(\n `is ${png.width}x${png.height}, larger than the ${cellWidth}x${cellHeight} cell`,\n )\n }\n loaded.push({ p, width: png.width, height: png.height, pixels: png.pixels })\n sources.push({ id: p.id, path: p.path, sha256: sourceHash, included: true })\n } catch (err) {\n skipped.push({ id: p.id, reason: err instanceof Error ? err.message : String(err) })\n sources.push({ id: p.id, path: p.path, sha256: sourceHash, included: false })\n }\n }\n if (!loaded.length) {\n throw new Error(`mountSprites: nothing readable — ${skipped.length} skipped.`)\n }\n\n // The sheet must cover the base if there is one, and every declared cell\n // either way — a cell past the base's edge grows it rather than failing,\n // so adding a row of tiles does not need the base redrawn first.\n const maxCol = Math.max(...loaded.map((l) => l.p.cell[0]))\n const maxRow = Math.max(...loaded.map((l) => l.p.cell[1]))\n const base = options.basePng ? decodePng(options.basePng) : null\n const sheetW = Math.max((maxCol + 1) * cellWidth, base?.width ?? 0)\n const sheetH = Math.max((maxRow + 1) * cellHeight, base?.height ?? 0)\n\n const rgba = Buffer.alloc(sheetW * sheetH * 4)\n if (base) {\n for (let y = 0; y < base.height; y++) {\n const src = y * base.width * 4\n base.pixels.copy(rgba, y * sheetW * 4, src, src + base.width * 4)\n }\n }\n\n const frames: PackedFrame[] = []\n for (const { p, width, height, pixels } of loaded) {\n const ox = p.cell[0] * cellWidth\n const oy = p.cell[1] * cellHeight\n // Clear the whole cell before writing: the sprite owns it, and leaving the\n // base showing around a smaller sprite is the \"invisible until it ships\"\n // failure this function exists to avoid.\n for (let y = 0; y < cellHeight; y++) {\n rgba.fill(0, ((oy + y) * sheetW + ox) * 4, ((oy + y) * sheetW + ox + cellWidth) * 4)\n }\n for (let y = 0; y < height; y++) {\n const src = y * width * 4\n pixels.copy(rgba, ((oy + y) * sheetW + ox) * 4, src, src + width * 4)\n }\n frames.push({ id: p.id, x: ox, y: oy, width, height })\n }\n\n frames.sort((a, b) => a.y - b.y || a.x - b.x)\n return {\n png: encodeRgbaPng(sheetW, sheetH, rgba),\n atlas: {\n style: \"\",\n sheet: { width: sheetW, height: sheetH },\n cell: { width: cellWidth, height: cellHeight },\n frames,\n },\n skipped,\n sources,\n overBase: base !== null,\n }\n}\n\n/**\n * `mountSprites` driven by the lockfile and the manifest's `mount` block.\n *\n * The manifest is the source of cells rather than the lockfile: a cell is a\n * declaration about where art belongs, not a record of what was generated, and\n * it has to be readable and editable before anything has been generated at all.\n */\nexport function mountStyle(\n lock: Lock,\n styleId: string,\n manifestDir: string,\n mount: { base?: string; cellWidth: number; cellHeight: number },\n cells: Record<string, [number, number]>,\n sources: Record<string, string> = {},\n outputRoles: Record<string, string> = {},\n): MountedSheet {\n // Driven by the declared cells, not by the lockfile. The cell is what says\n // \"this belongs on the sheet\"; whether pixelkiln generated the pixels is a\n // separate question, and `source` assets answer it with a file on disk.\n const ids = Object.keys(cells)\n if (!ids.length) {\n throw new Error(\n `No assets in style \"${styleId}\" declare a \\`cell\\`. Add one to each asset ` +\n `that belongs on the sheet.`,\n )\n }\n\n const placements: MountPlacement[] = []\n const skipped: { id: string; reason: string }[] = []\n for (const id of ids) {\n const cell = cells[id]!\n const source = sources[id]\n if (source) {\n placements.push({ id, path: path.resolve(manifestDir, source), cell })\n continue\n }\n const entry = lock.entries[`${styleId}/${id}`]\n if (!entry) {\n skipped.push({\n id,\n reason: `not generated in style \"${styleId}\", and no \\`source\\` declared`,\n })\n continue\n }\n const selection = selectEntryOutput(entry, outputRoles[id])\n if (!selection.ok) {\n skipped.push({ id, reason: selection.reason })\n continue\n }\n placements.push({ id, path: resolveOutputPath(selection.output.path, manifestDir), cell })\n }\n\n if (!placements.length) {\n const detail = skipped.length\n ? ` (${skipped.map((item) => `${item.id}: ${item.reason}`).join(\"; \")})`\n : \"\"\n throw new Error(\n `Nothing to mount for style \"${styleId}\": ${ids.length} asset(s) declare a ` +\n `cell, but none has generated output or a \\`source\\`. Run ` +\n `\\`pixelkiln gen --style ${styleId}\\`, or point each at a file.${detail}`,\n )\n }\n\n const basePng = mount.base ? readFileSync(path.resolve(manifestDir, mount.base)) : undefined\n const mounted = mountSprites(placements, {\n cellWidth: mount.cellWidth,\n cellHeight: mount.cellHeight,\n basePng,\n })\n return {\n ...mounted,\n sources: mount.base\n ? [{\n id: \"$base\",\n path: path.resolve(manifestDir, mount.base),\n sha256: sha256(basePng!),\n included: true,\n }, ...mounted.sources]\n : mounted.sources,\n atlas: { ...mounted.atlas, style: styleId },\n skipped: [...skipped, ...mounted.skipped],\n }\n}\n","import { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { sha256File } from \"../hash.ts\"\nimport { currentEntryOutputPath } from \"../outputs.ts\"\nimport { lockKey, type Lock, type LockEntry, type ResolvedSpec } from \"../types.ts\"\nimport type { CostUnit } from \"../provider.ts\"\nimport { inspectQualityProfile, type QualityProfileInspection } from \"./quality-profile.ts\"\nimport { inspectRevisionReadiness } from \"./revision.ts\"\n\nexport type PlanState =\n | \"ok\" // spec unchanged, file present and matching — nothing to do\n | \"missing\" // no lock entry and no file — genuinely needs generating\n | \"untracked\" // file exists but has no lock entry; the art is fine, provenance is not known\n | \"stale\" // prompt/style/size changed since the file was made\n | \"orphaned\" // the bytes that should be on disk are gone or altered\n | \"in-flight\" // submitted, not yet downloaded\n | \"recoverable\" // generation succeeded; download can be retried without spending\n | \"blocked\" // a declared revision input is missing, stale, or not approved\n | \"failed\"\n\n/**\n * True if any recorded output no longer hashes to what was written.\n *\n * Checked across every output, not just the primary: a character's engine\n * resource being hand-edited matters as much as its spritesheets changing.\n */\nasync function anyOutputModified(entry: LockEntry, spec: ResolvedSpec): Promise<boolean> {\n for (let index = 0; index < entry.outputs.length; index++) {\n const output = entry.outputs[index]!\n if (\n (await sha256File(currentEntryOutputPath(entry, spec, index))) !== output.sha256\n ) return true\n }\n return false\n}\n\nexport interface PlanItem {\n spec: ResolvedSpec\n key: string\n state: PlanState\n reason: string\n /** Derived-art state. It never changes provider cost or generation actionability. */\n quality?: QualityProfileInspection\n}\n\nexport interface Plan {\n items: PlanItem[]\n /** Items that would incur provider cost if the plan were executed. */\n actionable: PlanItem[]\n /** Provider-scoped totals. Unlike units and accounts are never combined. */\n groups: PlanGroup[]\n /** Compatibility projection for a single provider group; null for mixed plans. */\n cost: number | null\n /** Compatibility projection for a single provider group; null for mixed plans. */\n costUnit: CostUnit | null\n candidates: number\n}\n\nexport interface PlanGroup {\n provider: string\n costUnit: CostUnit\n cost: number\n candidates: number\n actionable: PlanItem[]\n}\n\nexport type ResumeCommand = \"poll\" | \"pick\" | \"fetch\"\n\nexport interface ResumeAction {\n command: ResumeCommand\n keys: string[]\n}\n\n/** The zero-cost command that advances one settled lock state. */\nexport function resumeCommandForStatus(\n status: LockEntry[\"status\"],\n): ResumeCommand | null {\n if (status === \"pending\" || status === \"processing\") return \"poll\"\n if (status === \"review\") return \"pick\"\n if (status === \"selected\" || status === \"download-failed\") return \"fetch\"\n return null\n}\n\n/** Group current selected specs by the command that can resume them safely. */\nexport function resumeActions(specs: ResolvedSpec[], lock: Lock): ResumeAction[] {\n const grouped = new Map<ResumeCommand, string[]>()\n for (const spec of specs) {\n const key = lockKey(spec.styleId, spec.assetId)\n const entry = lock.entries[key]\n if (!entry || entry.specHash !== spec.specHash) continue\n if (entry.submissionComplete === false) continue\n const command = resumeCommandForStatus(entry.status)\n if (!command) continue\n if (command === \"poll\" && !entry.jobId) continue\n if (command === \"pick\" && !entry.reviewObjectId) continue\n grouped.set(command, [...(grouped.get(command) ?? []), key])\n }\n return ([\"poll\", \"pick\", \"fetch\"] as const).flatMap((command) => {\n const keys = grouped.get(command)\n return keys?.length ? [{ command, keys }] : []\n })\n}\n\n/**\n * Diffs the manifest against the lockfile and the files on disk. Nothing here\n * touches the network, so it is safe to run constantly — it is the cheap\n * \"what would this cost me?\" question that should precede every real run.\n */\nexport async function buildPlan(\n specs: ResolvedSpec[],\n lock: Lock,\n opts: { force?: boolean } = {},\n): Promise<Plan> {\n const items: PlanItem[] = []\n\n for (const spec of specs) {\n const key = lockKey(spec.styleId, spec.assetId)\n const entry = lock.entries[key]\n\n let state: PlanState\n let reason: string\n\n const revision = await inspectRevisionReadiness(spec, lock)\n if (revision && !revision.ready) {\n state = \"blocked\"\n reason = revision.reason\n } else if (opts.force) {\n state = \"missing\"\n reason = \"--force\"\n } else if (!entry && spec.source) {\n // An asset with a `source` is placed from committed art by `mount`, and\n // AssetSchema.source says it needs no lock entry at all. Treating it as\n // `missing` puts art pixelkiln did not make and will never generate into\n // the actionable list, and bills a generation cost for each one.\n if (existsSync(path.resolve(spec.root, spec.source))) {\n state = \"ok\"\n reason = `placed from ${spec.source}; not generated`\n } else {\n state = \"orphaned\"\n reason = `declared source is missing: ${spec.source}`\n }\n } else if (!entry) {\n // Distinguish \"no art\" from \"art exists but unmatched upstream\". Calling\n // the latter `missing` invites regenerating perfectly good files — which\n // is exactly what happens to assets that were retouched by hand after\n // download, since their bytes no longer match any remote object.\n if (existsSync(spec.outFile)) {\n state = \"untracked\"\n reason = \"file on disk, no provenance recorded\"\n } else {\n state = \"missing\"\n reason = \"not in lockfile\"\n }\n } else if (entry.specHash !== spec.specHash) {\n state = \"stale\"\n reason = \"prompt, size, or style changed\"\n } else if (entry.status === \"download-failed\") {\n state = \"recoverable\"\n const force = entry.error?.includes(\"pass --force\") ? \" --force\" : \"\"\n reason =\n `${entry.error ?? \"download failed\"}; run pixelkiln fetch${force} ` +\n \"(no generation cost)\"\n } else if (entry.status === \"failed\") {\n state = \"failed\"\n reason = entry.jobId && entry.submissionComplete === false\n ? `${entry.error ?? \"submission interrupted\"}; saved checkpoint will resume`\n : entry.error ?? \"previous attempt failed\"\n } else if (entry.status === \"selected\") {\n state = \"recoverable\"\n reason = \"provider output is selected; run pixelkiln fetch (no generation cost)\"\n } else if (\n (entry.status === \"pending\" || entry.status === \"processing\") &&\n entry.jobId &&\n entry.submissionComplete === false\n ) {\n state = \"failed\"\n reason = \"submission stopped after a saved checkpoint; rerun pixelkiln submit to resume\"\n } else if (entry.status === \"pending\" || entry.status === \"processing\") {\n state = \"in-flight\"\n reason = entry.jobId\n ? \"awaiting processing; run pixelkiln poll\"\n : \"submission state has no job id; run pixelkiln doctor before retrying\"\n } else if (entry.status === \"review\") {\n state = \"in-flight\"\n reason = entry.reviewObjectId\n ? \"awaiting review; run pixelkiln pick\"\n : \"review state has no review object id; run pixelkiln doctor\"\n } else if (entry.status !== \"downloaded\") {\n state = \"in-flight\"\n reason = `awaiting ${entry.status}`\n } else if (\n entry.outputs.length === 0 ||\n entry.outputs.some((_output, index) =>\n !existsSync(currentEntryOutputPath(entry, spec, index)))\n ) {\n state = \"orphaned\"\n reason =\n entry.outputs.length === 0\n ? \"no recorded output files\"\n : `missing on disk: ${entry.outputs\n .filter((_output, index) =>\n !existsSync(currentEntryOutputPath(entry, spec, index)))\n .map((o) => o.role ?? \"asset\")\n .join(\", \")}`\n } else if (await anyOutputModified(entry, spec)) {\n // The file was edited by hand. That is a legitimate thing to do, so this\n // is reported rather than silently overwritten.\n state = \"orphaned\"\n reason = \"output modified since download\"\n } else {\n state = \"ok\"\n reason = \"up to date\"\n }\n\n const quality = await inspectQualityProfile(spec, lock)\n items.push({ spec, key, state, reason, ...(quality ? { quality } : {}) })\n }\n\n // \"orphaned\" entries may be re-downloadable from a persisted object without\n // paying again; only genuinely new work is counted toward cost.\n const actionable = items.filter((i) => i.state === \"missing\" || i.state === \"stale\" || i.state === \"failed\")\n const groupsByProvider = new Map<string, PlanGroup>()\n for (const item of actionable) {\n const provider = item.spec.provider\n const costUnit = item.spec.costUnit ?? \"generations\"\n const group = groupsByProvider.get(provider)\n if (group && group.costUnit !== costUnit) {\n throw new Error(\n `Provider \"${provider}\" returned mixed cost units (${group.costUnit}, ${costUnit})`,\n )\n }\n if (group) {\n group.actionable.push(item)\n group.cost += item.spec.cost\n group.candidates += item.spec.candidates\n } else {\n groupsByProvider.set(provider, {\n provider,\n costUnit,\n cost: item.spec.cost,\n candidates: item.spec.candidates,\n actionable: [item],\n })\n }\n }\n const groups = [...groupsByProvider.values()].sort((a, b) => a.provider.localeCompare(b.provider))\n const fallbackUnits = new Set(specs.map((spec) => spec.costUnit))\n const single = groups.length === 1 ? groups[0]! : null\n\n return {\n items,\n actionable,\n groups,\n cost: single?.cost ?? (groups.length ? null : 0),\n costUnit: single?.costUnit ?? (groups.length || fallbackUnits.size > 1\n ? null\n : fallbackUnits.values().next().value ?? (specs.length ? \"generations\" : \"free\")),\n candidates: actionable.reduce((sum, i) => sum + i.spec.candidates, 0),\n }\n}\n\nexport function summarize(plan: Plan): Record<PlanState, number> {\n const counts = {\n ok: 0, missing: 0, untracked: 0, stale: 0, orphaned: 0, \"in-flight\": 0,\n recoverable: 0, blocked: 0, failed: 0,\n } as Record<PlanState, number>\n for (const item of plan.items) counts[item.state]++\n return counts\n}\n","import { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { sha256File } from \"../hash.ts\"\nimport { MediaType } from \"../media.ts\"\nimport { currentEntryOutputPath } from \"../outputs.ts\"\nimport { lockKey, type Lock, type ResolvedSpec } from \"../types.ts\"\nimport {\n PIXEL_ART_FIXER_REVISION,\n checkQualityRecord,\n normalizeRefinementPalette,\n qualityFrameOutputPath,\n qualityRecordPath,\n refineAsset,\n refineFrameSet,\n} from \"./refine.ts\"\n\nexport type QualityProfileState =\n | \"blocked\"\n | \"needs-refinement\"\n | \"needs-approval\"\n | \"approved\"\n\nexport interface QualityProfileInspection {\n key: string\n state: QualityProfileState\n reason: string\n source: string | null\n sources?: string[]\n output: string\n outputs?: string[]\n record: string\n}\n\nexport interface RefineQualityProfilesOptions {\n fixerPython?: string\n force?: boolean\n /** @internal Alternate fixer command used by compatibility tests. */\n fixerCommand?: string\n /** @internal Prefix arguments for the alternate fixer command. */\n fixerArgsPrefix?: string[]\n}\n\nexport interface RefineQualityProfilesResult {\n processed: number\n skipped: number\n failed: number\n items: QualityProfileInspection[]\n}\n\ninterface QualitySource {\n items: Array<{ role: string; path: string }> | null\n reason?: string\n}\n\nasync function qualitySource(spec: ResolvedSpec, lock: Lock): Promise<QualitySource> {\n if (spec.source) {\n if (spec.generator === \"frames\") {\n return { items: null, reason: \"frame-set quality requires ordered downloaded provider outputs\" }\n }\n const source = path.resolve(spec.root, spec.source)\n return existsSync(source)\n ? { items: [{ role: \"source\", path: source }] }\n : { items: null, reason: `declared source is missing: ${spec.source}` }\n }\n\n const entry = lock.entries[lockKey(spec.styleId, spec.assetId)]\n if (!entry) return { items: null, reason: \"raw provider output is not in the lockfile\" }\n if (entry.specHash !== spec.specHash) {\n return { items: null, reason: \"raw provider output does not match the current generation spec\" }\n }\n if (entry.status !== \"downloaded\") {\n return { items: null, reason: `raw provider output is ${entry.status}, not downloaded` }\n }\n const frameSet = spec.generator === \"frames\"\n if ((!frameSet && entry.outputs.length !== 1) || (frameSet && entry.outputs.length < 2)) {\n return {\n items: null,\n reason: frameSet\n ? `frame-set quality requires at least two PNG outputs; lock entry has ${entry.outputs.length}`\n : `quality profiles require one PNG output; lock entry has ${entry.outputs.length}`,\n }\n }\n const roles = new Set<string>()\n const items: Array<{ role: string; path: string }> = []\n for (const [index, output] of entry.outputs.entries()) {\n if (output.mediaType && output.mediaType !== MediaType.PNG) {\n return { items: null, reason: `quality profiles require PNG input; lock entry is ${output.mediaType}` }\n }\n const role = frameSet ? output.role : \"source\"\n if (frameSet && (!role || roles.has(role))) {\n return { items: null, reason: \"frame-set quality requires a unique role for every ordered output\" }\n }\n if (role) roles.add(role)\n const source = currentEntryOutputPath(entry, spec, index)\n if (!existsSync(source)) return { items: null, reason: `raw provider output is missing: ${source}` }\n if ((await sha256File(source)) !== output.sha256) {\n return { items: null, reason: \"raw provider output was modified after download\" }\n }\n items.push({ role: role!, path: source })\n }\n return { items }\n}\n\n/** Inspect one configured quality output without changing files or contacting a provider. */\nexport async function inspectQualityProfile(\n spec: ResolvedSpec,\n lock: Lock,\n): Promise<QualityProfileInspection | null> {\n if (!spec.quality) return null\n const key = lockKey(spec.styleId, spec.assetId)\n const output = spec.quality.outFile\n const record = qualityRecordPath(output)\n const source = await qualitySource(spec, lock)\n if (!source.items) {\n return { key, state: \"blocked\", reason: source.reason!, source: null, output, record }\n }\n const sourcePaths = source.items.map((item) => item.path)\n const expectedOutputs = spec.generator === \"frames\"\n ? source.items.map((item, index) => qualityFrameOutputPath(output, item.role, index))\n : [output]\n if (!existsSync(record)) {\n return {\n key,\n state: \"needs-refinement\",\n reason: \"no refinement record\",\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n }\n\n try {\n const check = await checkQualityRecord(record)\n const expectedPalette = normalizeRefinementPalette(spec.quality.palette)\n const expectedRevision = spec.quality.fixerRevision ?? PIXEL_ART_FIXER_REVISION\n const expectedTransparency = spec.quality.minTransparency ?? null\n const expectedFrameSet = spec.generator === \"frames\"\n ? { fps: spec.quality.fps ?? 12, count: source.items.length, roles: source.items.map((item) => item.role) }\n : null\n const contractChanged =\n JSON.stringify(check.sources.map((item) => path.resolve(item))) !==\n JSON.stringify(sourcePaths.map((item) => path.resolve(item))) ||\n JSON.stringify(check.outputs.map((item) => path.resolve(item))) !==\n JSON.stringify(expectedOutputs.map((item) => path.resolve(item))) ||\n JSON.stringify(check.options.palette.colors) !== JSON.stringify(expectedPalette) ||\n check.options.nativeGrid.revision !== expectedRevision ||\n check.options.audit.thresholds.minGridConfidence !== spec.quality.minGridConfidence ||\n check.options.audit.thresholds.minTransparency !== expectedTransparency ||\n (expectedFrameSet\n ? !check.options.frameSet ||\n check.options.frameSet.fps !== expectedFrameSet.fps ||\n check.options.frameSet.count !== expectedFrameSet.count ||\n JSON.stringify(check.options.frameSet.roles) !== JSON.stringify(expectedFrameSet.roles)\n : check.options.frameSet !== undefined)\n\n if (contractChanged) {\n return {\n key,\n state: \"needs-refinement\",\n reason: \"quality profile changed\",\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n }\n if (!check.current || !check.auditSafe) {\n return {\n key,\n state: \"needs-refinement\",\n reason: check.reasons.filter((reason) => reason !== \"human 1× review is pending\").join(\"; \") ||\n \"refinement record is stale\",\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n }\n if (!check.approved) {\n return {\n key,\n state: \"needs-approval\",\n reason: \"automated checks passed; human 1× review is pending\",\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n }\n return {\n key,\n state: \"approved\",\n reason: \"refined output and human approval are current\",\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n } catch (error) {\n return {\n key,\n state: \"needs-refinement\",\n reason: `invalid refinement record: ${error instanceof Error ? error.message : String(error)}`,\n source: sourcePaths[0]!,\n sources: sourcePaths,\n output,\n outputs: expectedOutputs,\n record,\n }\n }\n}\n\n/** Refine every configured, selected asset while preserving current approvals. */\nexport async function refineQualityProfiles(\n specs: ResolvedSpec[],\n lock: Lock,\n options: RefineQualityProfilesOptions = {},\n): Promise<RefineQualityProfilesResult> {\n const configured = specs.filter((spec) => spec.quality)\n if (!configured.length) {\n throw new Error(\"No selected style has a quality profile.\")\n }\n\n const result: RefineQualityProfilesResult = { processed: 0, skipped: 0, failed: 0, items: [] }\n for (const spec of configured) {\n const inspection = (await inspectQualityProfile(spec, lock))!\n if (!options.force && (inspection.state === \"approved\" || inspection.state === \"needs-approval\")) {\n result.skipped++\n result.items.push(inspection)\n continue\n }\n if (inspection.state === \"blocked\") {\n result.failed++\n result.items.push(inspection)\n continue\n }\n try {\n const common = {\n output: inspection.output,\n palette: spec.quality!.palette,\n minGridConfidence: spec.quality!.minGridConfidence,\n ...(spec.quality!.minTransparency == null\n ? {}\n : { minTransparency: spec.quality!.minTransparency }),\n fixerRevision: spec.quality!.fixerRevision ?? PIXEL_ART_FIXER_REVISION,\n // A one-off CLI/library override wins; otherwise each style can carry\n // the stable project-local interpreter that provides its pinned fixer.\n fixerPython: options.fixerPython ?? spec.quality!.fixerPython,\n fixerCommand: options.fixerCommand,\n fixerArgsPrefix: options.fixerArgsPrefix,\n force: options.force,\n }\n if (spec.generator === \"frames\") {\n const frameSources = await qualitySource(spec, lock)\n if (!frameSources.items) throw new Error(frameSources.reason)\n await refineFrameSet({\n ...common,\n sources: frameSources.items,\n fps: spec.quality!.fps ?? 12,\n })\n } else {\n await refineAsset({ ...common, source: inspection.source! })\n }\n result.processed++\n result.items.push((await inspectQualityProfile(spec, lock))!)\n } catch (error) {\n result.failed++\n result.items.push({\n ...inspection,\n state: \"needs-refinement\",\n reason: error instanceof Error ? error.message : String(error),\n })\n }\n }\n return result\n}\n\n/** Return approved derived files for a packaging command, or fail closed. */\nexport async function requireApprovedQualitySources(\n specs: ResolvedSpec[],\n lock: Lock,\n assetIds?: ReadonlySet<string>,\n outputRoles?: Readonly<Record<string, string>>,\n): Promise<Record<string, string> | undefined> {\n const configured = specs.filter(\n (spec) => spec.quality && (!assetIds || assetIds.has(spec.assetId)),\n )\n if (!configured.length) return undefined\n\n const sources: Record<string, string> = {}\n const rejected: QualityProfileInspection[] = []\n for (const spec of configured) {\n const inspection = (await inspectQualityProfile(spec, lock))!\n if (inspection.state === \"approved\") {\n if (spec.generator === \"frames\") {\n const check = await checkQualityRecord(inspection.record)\n const roles = check.options.frameSet!.roles\n if (outputRoles) {\n const selectedRole = outputRoles[spec.assetId]\n if (!selectedRole) {\n throw new Error(\n `Mounting quality-approved frame set ${inspection.key} requires asset.outputRole.`,\n )\n }\n const index = roles.indexOf(selectedRole)\n if (index < 0) {\n throw new Error(\n `Frame set ${inspection.key} has no approved output role \"${selectedRole}\".`,\n )\n }\n sources[spec.assetId] = check.outputs[index]!\n } else {\n for (const [index, output] of check.outputs.entries()) {\n sources[`${spec.assetId}/${roles[index]}`] = output\n }\n }\n } else {\n sources[spec.assetId] = inspection.output\n }\n } else rejected.push(inspection)\n }\n if (rejected.length) {\n const detail = rejected\n .slice(0, 5)\n .map((item) => `${item.key}: ${item.state} (${item.reason})`)\n .join(\"; \")\n throw new Error(\n `Packaging requires current, human-approved quality output: ${detail}. ` +\n \"Run `pixelkiln refine`, review each PNG, then run `pixelkiln refine approve --from <record> --reviewer <name>`.\",\n )\n }\n return sources\n}\n","import path from \"node:path\"\nimport { execFile } from \"node:child_process\"\nimport { mkdtemp, readFile, rm } from \"node:fs/promises\"\nimport { tmpdir } from \"node:os\"\nimport { promisify } from \"node:util\"\nimport {\n readArtifactBundleManifest,\n verifyArtifactBundle,\n writeManagedArtifactBundle,\n type ArtifactBundleManifest,\n type ArtifactSource,\n} from \"../artifacts.ts\"\nimport { sha256File } from \"../hash.ts\"\nimport {\n decodePng,\n encodeRgbaPng,\n parseHex,\n transparencyRatio,\n type DecodedPng,\n} from \"../png.ts\"\nimport type { GridConfidence } from \"../types.ts\"\nimport { colorDistance } from \"./audit.ts\"\n\nconst execFileAsync = promisify(execFile)\n\nconst PIXEL_ART_FIXER_MIN_SIDE = 16\nconst PIXEL_ART_FIXER_MAX_PIXELS = 4_000_000\n\nexport const PIXEL_ART_FIXER_URL = \"https://github.com/Retro-Diffusion/pixel-art-fixer\"\nexport const PIXEL_ART_FIXER_REVISION = \"ef376e57e1c272633ca2dbf5f29ec3fcf6596465\"\n\nexport interface PixelArtFixerDetection {\n stepX: number\n stepY: number\n phaseX: number\n phaseY: number\n columns: number\n rows: number\n consensus: string\n confidence: GridConfidence\n}\n\nexport interface RefineAudit {\n width: number\n height: number\n colorCount: number\n paletteConformant: boolean\n transparency: number\n thresholds: {\n maxColors: number\n minTransparency: number | null\n minGridConfidence: GridConfidence\n }\n safe: boolean\n reasons: string[]\n}\n\nexport interface PendingQualityReview {\n status: \"pending\"\n}\n\nexport interface ApprovedQualityReview {\n status: \"approved\"\n reviewer: string\n approvedAt: string\n checklist: {\n nativeScale: true\n crispEdges: true\n subjectReadable: true\n paletteSeparation: true\n alphaAndSeams: true\n }\n note?: string\n}\n\nexport interface RefineRecordOptions {\n schema: \"pixelkiln-quality\"\n version: 1\n nativeGrid: {\n tool: \"pixel-art-fixer\"\n url: typeof PIXEL_ART_FIXER_URL\n revision: string\n protocol: \"python-api-v1\" | \"python-core-v1\" | \"python-cli-v1\"\n confidence: GridConfidence\n consensus: string\n stepX: number\n stepY: number\n /** Detector phase in source pixels. Older v1 single-image records omit it. */\n phaseX?: number\n phaseY?: number\n sourceWidth: number\n sourceHeight: number\n nativeWidth: number\n nativeHeight: number\n }\n palette: {\n colors: string[]\n dither: \"none\"\n distance: \"redmean\"\n }\n audit: RefineAudit\n review: PendingQualityReview | ApprovedQualityReview\n /** Present when one approval covers an ordered, jointly verified frame set. */\n frameSet?: {\n fps: number\n count: number\n roles: string[]\n frames: Array<{\n role: string\n sourceWidth: number\n sourceHeight: number\n detection: PixelArtFixerDetection\n audit: RefineAudit\n }>\n }\n}\n\nexport interface RefineOptions {\n source: string\n output: string\n palette: string[]\n /** Python containing `pixelfixer`. Defaults to the environment override or `python3`. */\n fixerPython?: string\n /** @internal Alternate Pixel Art Fixer console command used by compatibility tests. */\n fixerCommand?: string\n /** @internal Prefix arguments for the alternate console command. */\n fixerArgsPrefix?: string[]\n fixerRevision?: string\n minGridConfidence?: GridConfidence\n minTransparency?: number\n force?: boolean\n}\n\nexport interface RefineResult {\n source: string\n output: string\n record: string\n detection: PixelArtFixerDetection\n palette: string[]\n audit: RefineAudit\n}\n\nexport interface RefineFrameSetOptions {\n sources: Array<{ role: string; path: string }>\n /** Virtual .png stem used to derive numbered outputs and the shared record. */\n output: string\n fps: number\n palette: string[]\n fixerPython?: string\n fixerCommand?: string\n fixerArgsPrefix?: string[]\n fixerRevision?: string\n minGridConfidence?: GridConfidence\n minTransparency?: number\n force?: boolean\n}\n\nexport interface RefineFrameSetResult {\n sources: string[]\n outputs: string[]\n record: string\n frames: Array<{\n role: string\n sourceWidth: number\n sourceHeight: number\n detection: PixelArtFixerDetection\n audit: RefineAudit\n }>\n palette: string[]\n audit: RefineAudit\n}\n\nexport interface QualityCheck {\n safe: boolean\n current: boolean\n approved: boolean\n auditSafe: boolean\n record: string\n source: string\n output: string\n sources: string[]\n outputs: string[]\n options: RefineRecordOptions\n reasons: string[]\n}\n\nexport interface ApproveQualityOptions {\n reviewer: string\n note?: string\n /** Deterministic clock hook for callers that need reproducible tests. */\n approvedAt?: Date\n}\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nexport function qualityRecordPath(output: string): string {\n if (!/\\.png$/i.test(output)) throw new Error(\"Refined output must be a .png file.\")\n return output.replace(/\\.png$/i, \".pixelkiln.json\")\n}\n\nfunction confidenceFor(consensus: string): GridConfidence {\n if (consensus.startsWith(\"fast:\")) return \"high\"\n if (\n consensus === \"arbitrated\" ||\n consensus === \"forced\" ||\n (consensus.startsWith(\"fastmode:\") && consensus.includes(\"+\"))\n ) return \"medium\"\n return \"low\"\n}\n\nconst confidenceRank: Record<GridConfidence, number> = { low: 0, medium: 1, high: 2 }\n\nfunction requireConfidence(value: string): GridConfidence {\n if (value === \"low\" || value === \"medium\" || value === \"high\") return value\n throw new Error(`Unknown grid confidence \"${value}\"; expected low, medium, or high.`)\n}\n\nfunction firstJsonObject(text: string): unknown {\n const start = text.indexOf(\"{\")\n if (start < 0) throw new Error(\"Pixel Art Fixer did not print detection JSON.\")\n let depth = 0\n let string = false\n let escaped = false\n for (let i = start; i < text.length; i++) {\n const char = text[i]!\n if (string) {\n if (escaped) escaped = false\n else if (char === \"\\\\\") escaped = true\n else if (char === '\"') string = false\n continue\n }\n if (char === '\"') string = true\n else if (char === \"{\") depth++\n else if (char === \"}\" && --depth === 0) {\n try {\n return JSON.parse(text.slice(start, i + 1))\n } catch (error) {\n throw new Error(`Pixel Art Fixer printed invalid detection JSON: ${message(error)}`)\n }\n }\n }\n throw new Error(\"Pixel Art Fixer printed incomplete detection JSON.\")\n}\n\nconst PYTHON_FIXER_BRIDGE = [\n \"import json, sys\",\n \"from PIL import Image\",\n \"from pixelfixer.api import _load\",\n \"from pixelfixer.core import detect\",\n \"from pixelfixer.reconstruct import two_stage_pack\",\n \"rgba = _load(open(sys.argv[1], 'rb').read())\",\n \"result = detect(rgba, mode='full')\",\n \"Image.fromarray(two_stage_pack(rgba, result['cols'], result['rows'])).save(sys.argv[2], 'PNG')\",\n \"print(json.dumps({key: result[key] for key in ('cols', 'rows', 'step_x', 'step_y', 'phase_x', 'phase_y', 'consensus')}))\",\n].join(\"; \")\n\nfunction parseDetection(raw: unknown): PixelArtFixerDetection {\n if (!raw || typeof raw !== \"object\") throw new Error(\"Pixel Art Fixer returned no detection result.\")\n const value = raw as Record<string, unknown>\n const stepX = Number(value.step_x)\n const stepY = Number(value.step_y)\n const phaseX = Number(value.phase_x)\n const phaseY = Number(value.phase_y)\n const columns = Number(value.cols)\n const rows = Number(value.rows)\n const consensus = value.consensus\n if (\n !Number.isFinite(stepX) || stepX <= 0 ||\n !Number.isFinite(stepY) || stepY <= 0 ||\n !Number.isFinite(phaseX) || phaseX < 0 || phaseX > stepX ||\n !Number.isFinite(phaseY) || phaseY < 0 || phaseY > stepY ||\n !Number.isInteger(columns) || columns < 1 ||\n !Number.isInteger(rows) || rows < 1 ||\n typeof consensus !== \"string\" || !consensus\n ) {\n throw new Error(\"Pixel Art Fixer returned an invalid grid detection result.\")\n }\n return {\n stepX,\n stepY,\n phaseX,\n phaseY,\n columns,\n rows,\n consensus,\n confidence: confidenceFor(consensus),\n }\n}\n\nfunction normalizePalette(values: string[]): Array<{ hex: string; r: number; g: number; b: number }> {\n const colors = new Map<string, { hex: string; r: number; g: number; b: number }>()\n for (const value of values) {\n const rgb = parseHex(value)\n const hex = `#${rgb.r.toString(16).padStart(2, \"0\")}${rgb.g.toString(16).padStart(2, \"0\")}${rgb.b.toString(16).padStart(2, \"0\")}`\n colors.set(hex, { hex, ...rgb })\n }\n if (colors.size < 2 || colors.size > 256) {\n throw new Error(`A refinement palette must contain 2–256 unique colors; got ${colors.size}.`)\n }\n return [...colors.values()]\n}\n\n/** Canonical lowercase palette identity shared by manifest quality profiles. */\nexport function normalizeRefinementPalette(values: string[]): string[] {\n return normalizePalette(values).map((color) => color.hex)\n}\n\n/** Map every visible pixel to the nearest explicit color, without dithering. */\nexport function quantizeToPalette(png: DecodedPng, palette: string[]): DecodedPng {\n const colors = normalizePalette(palette)\n const pixels = Buffer.from(png.pixels)\n for (let i = 0; i < pixels.length; i += 4) {\n const alpha = pixels[i + 3]!\n if (alpha === 0) {\n pixels[i] = 0\n pixels[i + 1] = 0\n pixels[i + 2] = 0\n continue\n }\n const pixel = { r: pixels[i]!, g: pixels[i + 1]!, b: pixels[i + 2]! }\n let nearest = colors[0]!\n let distance = colorDistance(pixel, nearest)\n for (let j = 1; j < colors.length; j++) {\n const candidate = colors[j]!\n const candidateDistance = colorDistance(pixel, candidate)\n if (candidateDistance < distance) {\n nearest = candidate\n distance = candidateDistance\n }\n }\n pixels[i] = nearest.r\n pixels[i + 1] = nearest.g\n pixels[i + 2] = nearest.b\n }\n return { width: png.width, height: png.height, pixels }\n}\n\nfunction colorCount(png: DecodedPng): number {\n const colors = new Set<number>()\n for (let i = 0; i < png.pixels.length; i += 4) {\n if (png.pixels[i + 3]! < 128) continue\n colors.add((png.pixels[i]! << 16) | (png.pixels[i + 1]! << 8) | png.pixels[i + 2]!)\n }\n return colors.size\n}\n\nfunction unexpectedPaletteColors(png: DecodedPng, palette: string[]): number {\n const allowed = new Set(palette.map((hex) => {\n const color = parseHex(hex)\n return (color.r << 16) | (color.g << 8) | color.b\n }))\n const unexpected = new Set<number>()\n for (let i = 0; i < png.pixels.length; i += 4) {\n if (png.pixels[i + 3] === 0) continue\n const color = (png.pixels[i]! << 16) | (png.pixels[i + 1]! << 8) | png.pixels[i + 2]!\n if (!allowed.has(color)) unexpected.add(color)\n }\n return unexpected.size\n}\n\nfunction auditRefinement(\n png: DecodedPng,\n detection: PixelArtFixerDetection,\n palette: string[],\n minTransparency: number | undefined,\n minGridConfidence: GridConfidence,\n): RefineAudit {\n const colors = colorCount(png)\n const unexpectedColors = unexpectedPaletteColors(png, palette)\n const transparency = transparencyRatio(png)\n const reasons: string[] = []\n if (png.width !== detection.columns || png.height !== detection.rows) {\n reasons.push(\n `native output is ${png.width}x${png.height}, expected detected grid ` +\n `${detection.columns}x${detection.rows}`,\n )\n }\n if (colors > palette.length) reasons.push(`opaque color count ${colors} exceeds ${palette.length}`)\n if (unexpectedColors) reasons.push(`${unexpectedColors} visible color(s) are outside the final palette`)\n if (minTransparency !== undefined && transparency < minTransparency) {\n reasons.push(\n `transparency ${(transparency * 100).toFixed(1)}% is below ` +\n `${(minTransparency * 100).toFixed(1)}%`,\n )\n }\n if (confidenceRank[detection.confidence] < confidenceRank[minGridConfidence]) {\n reasons.push(\n `grid confidence ${detection.confidence} is below required ${minGridConfidence} ` +\n `(${detection.consensus})`,\n )\n }\n return {\n width: png.width,\n height: png.height,\n colorCount: colors,\n paletteConformant: unexpectedColors === 0,\n transparency,\n thresholds: {\n maxColors: palette.length,\n minTransparency: minTransparency ?? null,\n minGridConfidence,\n },\n safe: reasons.length === 0,\n reasons,\n }\n}\n\nfunction isGridConfidence(value: unknown): value is GridConfidence {\n return value === \"low\" || value === \"medium\" || value === \"high\"\n}\n\nfunction isDetection(value: unknown): value is PixelArtFixerDetection {\n if (!value || typeof value !== \"object\") return false\n const detection = value as Partial<PixelArtFixerDetection>\n return (\n Number.isFinite(detection.stepX) && detection.stepX! > 0 &&\n Number.isFinite(detection.stepY) && detection.stepY! > 0 &&\n Number.isFinite(detection.phaseX) && detection.phaseX! >= 0 &&\n detection.phaseX! <= detection.stepX! &&\n Number.isFinite(detection.phaseY) && detection.phaseY! >= 0 &&\n detection.phaseY! <= detection.stepY! &&\n Number.isInteger(detection.columns) && detection.columns! > 0 &&\n Number.isInteger(detection.rows) && detection.rows! > 0 &&\n typeof detection.consensus === \"string\" && !!detection.consensus &&\n isGridConfidence(detection.confidence)\n )\n}\n\nfunction isAudit(value: unknown): value is RefineAudit {\n if (!value || typeof value !== \"object\") return false\n const audit = value as Partial<RefineAudit>\n return (\n Number.isInteger(audit.width) && audit.width! > 0 &&\n Number.isInteger(audit.height) && audit.height! > 0 &&\n Number.isInteger(audit.colorCount) && audit.colorCount! >= 0 &&\n typeof audit.paletteConformant === \"boolean\" &&\n Number.isFinite(audit.transparency) && audit.transparency! >= 0 && audit.transparency! <= 1 &&\n !!audit.thresholds &&\n Number.isInteger(audit.thresholds.maxColors) && audit.thresholds.maxColors > 0 &&\n (audit.thresholds.minTransparency === null ||\n (Number.isFinite(audit.thresholds.minTransparency) &&\n audit.thresholds.minTransparency >= 0 && audit.thresholds.minTransparency <= 1)) &&\n isGridConfidence(audit.thresholds.minGridConfidence) &&\n typeof audit.safe === \"boolean\" &&\n Array.isArray(audit.reasons) && audit.reasons.every((reason) => typeof reason === \"string\")\n )\n}\n\nfunction validFrameSet(value: unknown): value is NonNullable<RefineRecordOptions[\"frameSet\"]> {\n if (!value || typeof value !== \"object\") return false\n const frameSet = value as NonNullable<RefineRecordOptions[\"frameSet\"]>\n return (\n Number.isInteger(frameSet.fps) && frameSet.fps >= 1 && frameSet.fps <= 60 &&\n Number.isInteger(frameSet.count) && frameSet.count >= 2 && frameSet.count <= 64 &&\n Array.isArray(frameSet.roles) && frameSet.roles.length === frameSet.count &&\n new Set(frameSet.roles).size === frameSet.roles.length &&\n frameSet.roles.every((role) => typeof role === \"string\" && !!role) &&\n Array.isArray(frameSet.frames) && frameSet.frames.length === frameSet.count &&\n frameSet.frames.every((frame, index) =>\n frame.role === frameSet.roles[index] &&\n Number.isInteger(frame.sourceWidth) && frame.sourceWidth > 0 &&\n Number.isInteger(frame.sourceHeight) && frame.sourceHeight > 0 &&\n isDetection(frame.detection) && isAudit(frame.audit),\n )\n )\n}\n\nfunction parseRecordOptions(manifest: ArtifactBundleManifest, record: string): RefineRecordOptions {\n if (manifest.kind !== \"refine\") throw new Error(`${record} is not a PixelKiln refinement record.`)\n const raw = manifest.options\n if (!raw || typeof raw !== \"object\") throw new Error(`${record} has invalid quality metadata.`)\n const options = raw as Partial<RefineRecordOptions>\n const grid = options.nativeGrid\n const palette = options.palette\n const audit = options.audit\n const review = options.review\n if (\n options.schema !== \"pixelkiln-quality\" || options.version !== 1 ||\n !grid || grid.tool !== \"pixel-art-fixer\" || grid.url !== PIXEL_ART_FIXER_URL ||\n typeof grid.revision !== \"string\" || !grid.revision ||\n (grid.protocol !== \"python-api-v1\" && grid.protocol !== \"python-core-v1\" &&\n grid.protocol !== \"python-cli-v1\") ||\n !isGridConfidence(grid.confidence) || typeof grid.consensus !== \"string\" ||\n !Number.isFinite(grid.stepX) || !Number.isFinite(grid.stepY) ||\n ((grid.phaseX !== undefined || grid.phaseY !== undefined || options.frameSet !== undefined) &&\n (!Number.isFinite(grid.phaseX) || !Number.isFinite(grid.phaseY))) ||\n !Number.isInteger(grid.sourceWidth) || !Number.isInteger(grid.sourceHeight) ||\n !Number.isInteger(grid.nativeWidth) || !Number.isInteger(grid.nativeHeight) ||\n !palette || !Array.isArray(palette.colors) || palette.colors.length < 2 ||\n !palette.colors.every((color) => typeof color === \"string\") ||\n palette.dither !== \"none\" || palette.distance !== \"redmean\" ||\n !isAudit(audit) ||\n !review || (review.status !== \"pending\" && review.status !== \"approved\") ||\n (options.frameSet !== undefined && !validFrameSet(options.frameSet))\n ) {\n throw new Error(`${record} has invalid quality metadata.`)\n }\n return options as RefineRecordOptions\n}\n\nfunction safeFrameRole(role: string, index: number): string {\n const safe = role.trim().replace(/[^a-zA-Z0-9_-]+/g, \"-\").replace(/^-+|-+$/g, \"\")\n return safe || `frame-${String(index).padStart(2, \"0\")}`\n}\n\n/** Derive a stable frame PNG beside a quality profile's virtual output stem. */\nexport function qualityFrameOutputPath(output: string, role: string, index: number): string {\n if (!/\\.png$/i.test(output)) throw new Error(\"Refined frame-set output must use a .png stem.\")\n return output.replace(/\\.png$/i, `-${safeFrameRole(role, index)}.png`)\n}\n\nfunction sameFrameGrid(\n first: RefineFrameSetResult[\"frames\"][number],\n next: RefineFrameSetResult[\"frames\"][number],\n): boolean {\n const phaseMatches = (a: number, b: number, step: number) => {\n const distance = Math.abs(a - b) % step\n return Math.min(distance, step - distance) <= 0.01\n }\n return (\n next.detection.stepX === first.detection.stepX &&\n next.detection.stepY === first.detection.stepY &&\n next.detection.columns === first.detection.columns &&\n next.detection.rows === first.detection.rows &&\n phaseMatches(next.detection.phaseX, first.detection.phaseX, first.detection.stepX) &&\n phaseMatches(next.detection.phaseY, first.detection.phaseY, first.detection.stepY) &&\n next.audit.width === first.audit.width &&\n next.audit.height === first.audit.height &&\n next.sourceWidth === first.sourceWidth &&\n next.sourceHeight === first.sourceHeight\n )\n}\n\n/** Recover an image's native grid, enforce its final palette, and write an auditable bundle. */\nexport async function refineAsset(options: RefineOptions): Promise<RefineResult> {\n const source = path.resolve(options.source)\n const output = path.resolve(options.output)\n if (source === output) throw new Error(\"Refinement source and output must be different files.\")\n const record = path.resolve(qualityRecordPath(output))\n const palette = normalizePalette(options.palette).map((color) => color.hex)\n const minGridConfidence = requireConfidence(options.minGridConfidence ?? \"high\")\n if (\n options.minTransparency !== undefined &&\n (!Number.isFinite(options.minTransparency) || options.minTransparency < 0 || options.minTransparency > 1)\n ) throw new Error(\"minTransparency must be between 0 and 1.\")\n\n let sourcePng: DecodedPng\n try {\n sourcePng = decodePng(await readFile(source))\n } catch (error) {\n throw new Error(`Cannot read refinement source ${source}: ${message(error)}`, { cause: error })\n }\n\n const compatibilityCommand = options.fixerCommand\n if (!compatibilityCommand) {\n if (\n sourcePng.width < PIXEL_ART_FIXER_MIN_SIDE ||\n sourcePng.height < PIXEL_ART_FIXER_MIN_SIDE\n ) {\n throw new Error(\n `Pixel Art Fixer requires each source side to be at least ` +\n `${PIXEL_ART_FIXER_MIN_SIDE}px; got ${sourcePng.width}x${sourcePng.height}.`,\n )\n }\n if (sourcePng.width * sourcePng.height > PIXEL_ART_FIXER_MAX_PIXELS) {\n throw new Error(\n `Pixel Art Fixer accepts at most ${PIXEL_ART_FIXER_MAX_PIXELS.toLocaleString(\"en-US\")} ` +\n `source pixels; got ${sourcePng.width}x${sourcePng.height}.`,\n )\n }\n }\n\n const temp = await mkdtemp(path.join(tmpdir(), \"pixelkiln-refine-\"))\n const recovered = path.join(temp, \"native.png\")\n const fixerCommand = compatibilityCommand ?? options.fixerPython ??\n process.env.PIXELKILN_PIXEL_FIXER_PYTHON ?? \"python3\"\n const args = compatibilityCommand\n ? [...(options.fixerArgsPrefix ?? []), source, \"--extract\", recovered]\n : [\"-c\", PYTHON_FIXER_BRIDGE, source, recovered]\n try {\n let stdout: string\n try {\n const result = await execFileAsync(fixerCommand, args, {\n encoding: \"utf8\",\n maxBuffer: 4 * 1024 * 1024,\n timeout: 10 * 60 * 1000,\n })\n stdout = result.stdout\n } catch (error) {\n const code = typeof error === \"object\" && error !== null && \"code\" in error\n ? String(error.code)\n : \"\"\n const install =\n `Install the pinned Python package from ${PIXEL_ART_FIXER_URL} at ` +\n `${options.fixerRevision ?? PIXEL_ART_FIXER_REVISION}, or pass --fixer-python.`\n throw new Error(\n code === \"ENOENT\"\n ? `Pixel Art Fixer command not found: ${fixerCommand}. ${install}`\n : `Pixel Art Fixer failed: ${message(error)}. ${install}`,\n { cause: error },\n )\n }\n const detection = parseDetection(firstJsonObject(stdout))\n const native = decodePng(await readFile(recovered))\n const quantized = quantizeToPalette(native, palette)\n const png = encodeRgbaPng(quantized.width, quantized.height, quantized.pixels)\n const audit = auditRefinement(\n quantized,\n detection,\n palette,\n options.minTransparency,\n minGridConfidence,\n )\n if (!audit.safe) {\n throw new Error(`Refinement failed its quality audit: ${audit.reasons.join(\"; \")}`)\n }\n\n const provenanceSource: ArtifactSource = {\n id: \"source\",\n path: source,\n sha256: await sha256File(source),\n included: true,\n }\n const recordOptions: RefineRecordOptions = {\n schema: \"pixelkiln-quality\",\n version: 1,\n nativeGrid: {\n tool: \"pixel-art-fixer\",\n url: PIXEL_ART_FIXER_URL,\n revision: options.fixerRevision ?? PIXEL_ART_FIXER_REVISION,\n protocol: compatibilityCommand ? \"python-cli-v1\" : \"python-core-v1\",\n confidence: detection.confidence,\n consensus: detection.consensus,\n stepX: detection.stepX,\n stepY: detection.stepY,\n phaseX: detection.phaseX,\n phaseY: detection.phaseY,\n sourceWidth: sourcePng.width,\n sourceHeight: sourcePng.height,\n nativeWidth: quantized.width,\n nativeHeight: quantized.height,\n },\n palette: { colors: palette, dither: \"none\", distance: \"redmean\" },\n audit,\n review: { status: \"pending\" },\n }\n await writeManagedArtifactBundle(\n record,\n [{ path: output, data: png }],\n { kind: \"refine\", sources: [provenanceSource], options: recordOptions },\n { force: options.force },\n )\n return { source, output, record, detection, palette, audit }\n } finally {\n await rm(temp, { recursive: true, force: true })\n }\n}\n\n/** Refine ordered still frames as one palette-locked, atomically reviewed artifact. */\nexport async function refineFrameSet(options: RefineFrameSetOptions): Promise<RefineFrameSetResult> {\n if (!Number.isInteger(options.fps) || options.fps < 1 || options.fps > 60) {\n throw new Error(\"Frame-set fps must be an integer between 1 and 60.\")\n }\n if (options.sources.length < 2 || options.sources.length > 64) {\n throw new Error(`A frame set must contain 2–64 ordered sources; got ${options.sources.length}.`)\n }\n const roles = options.sources.map((source) => source.role)\n if (roles.some((role) => !role.trim()) || new Set(roles).size !== roles.length) {\n throw new Error(\"Frame-set roles must be non-empty and unique.\")\n }\n\n const output = path.resolve(options.output)\n const record = path.resolve(qualityRecordPath(output))\n const palette = normalizeRefinementPalette(options.palette)\n const finalOutputs = options.sources.map((source, index) =>\n qualityFrameOutputPath(output, source.role, index))\n if (new Set(finalOutputs).size !== finalOutputs.length) {\n throw new Error(\"Frame-set roles resolve to duplicate output filenames.\")\n }\n const sourceSet = new Set(options.sources.map((source) => path.resolve(source.path)))\n if (finalOutputs.some((file) => sourceSet.has(file))) {\n throw new Error(\"Frame-set refinement sources and outputs must be different files.\")\n }\n const temp = await mkdtemp(path.join(tmpdir(), \"pixelkiln-refine-frames-\"))\n try {\n const frames: RefineFrameSetResult[\"frames\"] = []\n const outputs: Array<{ path: string; data: Buffer }> = []\n const provenanceSources: ArtifactSource[] = []\n const sourcePaths: string[] = []\n let firstOptions: RefineRecordOptions | null = null\n\n for (const [index, sourceEntry] of options.sources.entries()) {\n const source = path.resolve(sourceEntry.path)\n const temporaryOutput = path.join(temp, `${String(index).padStart(2, \"0\")}.png`)\n const refined = await refineAsset({\n source,\n output: temporaryOutput,\n palette,\n fixerPython: options.fixerPython,\n fixerCommand: options.fixerCommand,\n fixerArgsPrefix: options.fixerArgsPrefix,\n fixerRevision: options.fixerRevision,\n minGridConfidence: options.minGridConfidence,\n minTransparency: options.minTransparency,\n force: true,\n })\n const temporaryRecord = await readArtifactBundleManifest(refined.record)\n const frameOptions = parseRecordOptions(temporaryRecord, refined.record)\n firstOptions ??= frameOptions\n frames.push({\n role: sourceEntry.role,\n sourceWidth: frameOptions.nativeGrid.sourceWidth,\n sourceHeight: frameOptions.nativeGrid.sourceHeight,\n detection: refined.detection,\n audit: refined.audit,\n })\n sourcePaths.push(source)\n provenanceSources.push({\n id: sourceEntry.role,\n path: source,\n sha256: await sha256File(source),\n included: true,\n })\n outputs.push({\n path: finalOutputs[index]!,\n data: await readFile(temporaryOutput),\n })\n }\n\n const first = frames[0]!\n const mismatch = frames.find((frame) => !sameFrameGrid(first, frame))\n if (mismatch) {\n throw new Error(\n `Frame-set native grid mismatch: ${first.role} detected ` +\n `${first.detection.columns}x${first.detection.rows} at ` +\n `${first.detection.stepX}x${first.detection.stepY}, phase ` +\n `${first.detection.phaseX},${first.detection.phaseY}; but ${mismatch.role} detected ` +\n `${mismatch.detection.columns}x${mismatch.detection.rows} at ` +\n `${mismatch.detection.stepX}x${mismatch.detection.stepY}, phase ` +\n `${mismatch.detection.phaseX},${mismatch.detection.phaseY}.`,\n )\n }\n\n const reasons = frames.flatMap((frame) =>\n frame.audit.reasons.map((reason) => `${frame.role}: ${reason}`),\n )\n const audit: RefineAudit = {\n width: first.audit.width,\n height: first.audit.height,\n colorCount: Math.max(...frames.map((frame) => frame.audit.colorCount)),\n paletteConformant: frames.every((frame) => frame.audit.paletteConformant),\n transparency: Math.min(...frames.map((frame) => frame.audit.transparency)),\n thresholds: first.audit.thresholds,\n safe: frames.every((frame) => frame.audit.safe) && reasons.length === 0,\n reasons,\n }\n const baseOptions = firstOptions!\n const recordOptions: RefineRecordOptions = {\n ...baseOptions,\n audit,\n review: { status: \"pending\" },\n frameSet: {\n fps: options.fps,\n count: frames.length,\n roles,\n frames,\n },\n }\n await writeManagedArtifactBundle(\n record,\n outputs,\n { kind: \"refine\", sources: provenanceSources, options: recordOptions },\n { force: options.force },\n )\n return {\n sources: sourcePaths,\n outputs: outputs.map((item) => path.resolve(item.path)),\n record,\n frames,\n palette,\n audit,\n }\n } finally {\n await rm(temp, { recursive: true, force: true })\n }\n}\n\n/** Verify bytes, policy, audit, and human approval without rebuilding the image. */\nexport async function checkQualityRecord(recordPath: string): Promise<QualityCheck> {\n const record = path.resolve(recordPath)\n const manifest = await readArtifactBundleManifest(record)\n const options = parseRecordOptions(manifest, record)\n const verification = await verifyArtifactBundle(record)\n const sources = manifest.sources.map((source) => path.resolve(path.dirname(record), source.path))\n const outputs = manifest.outputs.map((output) => path.resolve(path.dirname(record), output.path))\n const source = sources[0] ?? \"\"\n const output = outputs[0] ?? \"\"\n const expectedCount = options.frameSet?.count ?? 1\n const reasons: string[] = []\n if (!verification.fingerprintValid) reasons.push(\"quality record fingerprint changed\")\n for (const source of verification.changedSources) reasons.push(`source changed: ${source}`)\n for (const changed of verification.changedOutputs) reasons.push(`output changed: ${changed}`)\n if (manifest.sources.length !== expectedCount) {\n reasons.push(`quality record must contain exactly ${expectedCount} source(s)`)\n }\n if (manifest.outputs.length !== expectedCount) {\n reasons.push(`quality record must contain exactly ${expectedCount} output(s)`)\n }\n if (!options.audit.safe) reasons.push(...options.audit.reasons.map((reason) => `audit: ${reason}`))\n if (options.review.status !== \"approved\") reasons.push(\"human 1× review is pending\")\n return {\n safe: reasons.length === 0,\n current: verification.current,\n approved: options.review.status === \"approved\",\n auditSafe: options.audit.safe,\n record,\n source,\n output,\n sources,\n outputs,\n options,\n reasons,\n }\n}\n\n/** Attach a human 1× review to an unchanged, audit-safe refinement bundle. */\nexport async function approveQualityRecord(\n recordPath: string,\n approval: ApproveQualityOptions,\n): Promise<QualityCheck> {\n const reviewer = approval.reviewer.trim()\n if (!reviewer) throw new Error(\"A human reviewer name is required.\")\n const record = path.resolve(recordPath)\n const manifest = await readArtifactBundleManifest(record)\n const options = parseRecordOptions(manifest, record)\n const verification = await verifyArtifactBundle(record)\n if (!verification.current) {\n const changes = [\n ...verification.changedSources.map((source) => `source ${source}`),\n ...verification.changedOutputs.map((output) => `output ${output}`),\n ...(!verification.fingerprintValid ? [\"quality metadata\"] : []),\n ]\n throw new Error(`Cannot approve a stale refinement; changed: ${changes.join(\", \")}. Run refine again.`)\n }\n if (!options.audit.safe) {\n throw new Error(`Cannot approve a failed quality audit: ${options.audit.reasons.join(\"; \")}`)\n }\n const expectedCount = options.frameSet?.count ?? 1\n if (manifest.sources.length !== expectedCount || manifest.outputs.length !== expectedCount) {\n throw new Error(\n `A refinement record must contain exactly ${expectedCount} source(s) and output(s).`,\n )\n }\n\n const root = path.dirname(record)\n const outputs = await Promise.all(manifest.outputs.map(async (entry) => {\n const outputPath = path.resolve(root, entry.path)\n return { path: outputPath, data: await readFile(outputPath) }\n }))\n const sources: ArtifactSource[] = manifest.sources.map((source) => ({\n ...source,\n path: path.resolve(root, source.path),\n }))\n const approved: RefineRecordOptions = {\n ...options,\n review: {\n status: \"approved\",\n reviewer,\n approvedAt: (approval.approvedAt ?? new Date()).toISOString(),\n checklist: {\n nativeScale: true,\n crispEdges: true,\n subjectReadable: true,\n paletteSeparation: true,\n alphaAndSeams: true,\n },\n ...(approval.note?.trim() ? { note: approval.note.trim() } : {}),\n },\n }\n await writeManagedArtifactBundle(\n record,\n outputs,\n { kind: \"refine\", sources, options: approved },\n )\n return checkQualityRecord(record)\n}\n","import path from \"node:path\"\nimport { createHash, randomUUID } from \"node:crypto\"\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\"\n\nexport interface ArtifactFile {\n path: string\n data: string | Uint8Array\n}\n\nexport interface ArtifactBundleResult {\n changed: string[]\n unchanged: string[]\n}\n\nexport interface ArtifactBundleOptions {\n /** @internal Failure-injection hook used to verify staging cleanup. */\n beforeStage?: (destination: string, index: number) => void | Promise<void>\n /** @internal Failure-injection hook used to verify rollback behavior. */\n beforePromote?: (destination: string, index: number) => void | Promise<void>\n /** @internal Durable transaction journal used by the managed writer. */\n recoveryFile?: string\n /** @internal Failure-injection hook used to simulate a crash after commit. */\n afterCommit?: () => void | Promise<void>\n}\n\nexport interface ManagedArtifactBundleOptions extends ArtifactBundleOptions {\n /** Explicitly replace unowned or manually modified destinations. */\n force?: boolean\n}\n\nexport interface ArtifactSource {\n id: string\n path: string\n sha256: string | null\n included: boolean\n}\n\nexport interface ArtifactProvenance {\n kind: \"pack\" | \"mount\" | \"tileset\" | \"refine\"\n sources: ArtifactSource[]\n /** Every non-source input that can change the derived bytes. */\n options: unknown\n}\n\nexport interface ArtifactBundleManifest {\n format: \"pixelkiln-artifact-bundle\"\n version: 1\n kind: ArtifactProvenance[\"kind\"]\n fingerprint: string\n sources: ArtifactSource[]\n options: unknown\n outputs: Array<{ path: string; sha256: string }>\n}\n\nexport interface ArtifactVerification {\n current: boolean\n fingerprintValid: boolean\n changedSources: string[]\n changedOutputs: string[]\n}\n\ninterface PreparedArtifact {\n destination: string\n data: Buffer\n existed: boolean\n stage?: string\n backup?: string\n backedUp: boolean\n promoted: boolean\n}\n\ninterface ArtifactTransaction {\n format: \"pixelkiln-artifact-transaction\"\n version: 1\n pid: number\n createdAt: string\n entries: Array<{\n destination: string\n stage: string\n backup?: string\n sha256: string\n }>\n}\n\nconst activeTransactions = new Set<string>()\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction digest(data: string | Uint8Array): string {\n return createHash(\"sha256\").update(data).digest(\"hex\")\n}\n\nfunction portableRelative(from: string, to: string): string {\n return path.relative(from, path.resolve(to)).split(path.sep).join(\"/\") || \".\"\n}\n\nfunction canonical(value: unknown): unknown {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) throw new Error(\"Artifact provenance numbers must be finite.\")\n return value\n }\n if (Array.isArray(value)) return value.map(canonical)\n if (typeof value === \"object\") {\n const sorted: Record<string, unknown> = {}\n for (const key of Object.keys(value).sort()) {\n const item = (value as Record<string, unknown>)[key]\n if (item !== undefined) sorted[key] = canonical(item)\n }\n return sorted\n }\n throw new Error(`Artifact provenance cannot contain ${typeof value} values.`)\n}\n\nfunction fingerprint(provenance: Pick<ArtifactBundleManifest, \"kind\" | \"sources\" | \"options\" | \"outputs\">): string {\n return digest(JSON.stringify(canonical({\n kind: provenance.kind,\n sources: provenance.sources,\n options: provenance.options,\n outputs: provenance.outputs,\n })))\n}\n\nfunction parseArtifactManifest(absolute: string, data: string): ArtifactBundleManifest {\n let raw: Partial<ArtifactBundleManifest>\n try {\n raw = JSON.parse(data) as Partial<ArtifactBundleManifest>\n } catch (error) {\n throw new Error(`${absolute} is not valid JSON: ${message(error)}`, { cause: error })\n }\n if (\n raw.format !== \"pixelkiln-artifact-bundle\" ||\n raw.version !== 1 ||\n (raw.kind !== \"pack\" && raw.kind !== \"mount\" && raw.kind !== \"tileset\" && raw.kind !== \"refine\") ||\n typeof raw.fingerprint !== \"string\" ||\n raw.options === undefined ||\n !Array.isArray(raw.sources) ||\n !Array.isArray(raw.outputs)\n ) {\n throw new Error(`${absolute} is not a PixelKiln artifact bundle manifest.`)\n }\n for (const source of raw.sources) {\n if (\n !source ||\n typeof source.id !== \"string\" ||\n typeof source.path !== \"string\" ||\n (source.sha256 !== null && typeof source.sha256 !== \"string\") ||\n typeof source.included !== \"boolean\"\n ) {\n throw new Error(`${absolute} contains an invalid artifact source.`)\n }\n }\n for (const output of raw.outputs) {\n if (!output || typeof output.path !== \"string\" || typeof output.sha256 !== \"string\") {\n throw new Error(`${absolute} contains an invalid artifact output.`)\n }\n }\n return raw as ArtifactBundleManifest\n}\n\n/** Read and validate a companion manifest without resolving its portable paths. */\nexport async function readArtifactBundleManifest(\n manifestPath: string,\n): Promise<ArtifactBundleManifest> {\n const absolute = path.resolve(manifestPath)\n return parseArtifactManifest(absolute, await readFile(absolute, \"utf8\"))\n}\n\nasync function readOptional(file: string): Promise<Buffer | null> {\n try {\n return await readFile(file)\n } catch (error) {\n if (isCode(error, \"ENOENT\")) return null\n throw error\n }\n}\n\nfunction transactionMarker(journal: string): string {\n return `${journal}.committed`\n}\n\nfunction processIsAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid < 1) return false\n try {\n process.kill(pid, 0)\n return true\n } catch (error) {\n return !isCode(error, \"ESRCH\")\n }\n}\n\nfunction validTemporaryPath(\n candidate: string,\n destination: string,\n type: \"stage\" | \"backup\",\n): boolean {\n return (\n path.dirname(candidate) === path.dirname(destination) &&\n path.basename(candidate).startsWith(\n `.${path.basename(destination)}.pixelkiln-${type}-`,\n )\n )\n}\n\nfunction parseTransaction(journal: string, data: string): ArtifactTransaction {\n let raw: Partial<ArtifactTransaction>\n try {\n raw = JSON.parse(data) as Partial<ArtifactTransaction>\n } catch (error) {\n throw new Error(`${journal} is not valid transaction JSON: ${message(error)}`, { cause: error })\n }\n if (\n raw.format !== \"pixelkiln-artifact-transaction\" ||\n raw.version !== 1 ||\n !Number.isInteger(raw.pid) ||\n typeof raw.createdAt !== \"string\" ||\n !Array.isArray(raw.entries) ||\n !raw.entries.length\n ) {\n throw new Error(`${journal} is not a PixelKiln artifact transaction.`)\n }\n return raw as ArtifactTransaction\n}\n\nasync function removeTransactionFiles(journal: string): Promise<void> {\n // Journal first: a marker without a journal means the destinations were\n // already committed and cleanup may safely be considered complete.\n await rm(journal, { force: true })\n await rm(transactionMarker(journal), { force: true })\n}\n\nasync function recoverArtifactTransaction(\n recoveryFile: string,\n allowedDestinations: Set<string>,\n): Promise<void> {\n const journal = path.resolve(recoveryFile)\n const bytes = await readOptional(journal)\n if (!bytes) {\n await rm(transactionMarker(journal), { force: true })\n return\n }\n\n if (activeTransactions.has(journal)) {\n throw new Error(`Another artifact write in this process is already using ${journal}.`)\n }\n const transaction = parseTransaction(journal, bytes.toString(\"utf8\"))\n if (transaction.pid !== process.pid && processIsAlive(transaction.pid)) {\n throw new Error(\n `Artifact transaction ${journal} is still owned by live process ${transaction.pid}; ` +\n `refusing concurrent recovery.`,\n )\n }\n\n for (const entry of transaction.entries) {\n if (\n typeof entry.destination !== \"string\" ||\n typeof entry.stage !== \"string\" ||\n typeof entry.sha256 !== \"string\" ||\n (entry.backup !== undefined && typeof entry.backup !== \"string\") ||\n !allowedDestinations.has(path.resolve(entry.destination)) ||\n !validTemporaryPath(entry.stage, entry.destination, \"stage\") ||\n (entry.backup !== undefined && !validTemporaryPath(entry.backup, entry.destination, \"backup\"))\n ) {\n throw new Error(\n `Refusing unsafe artifact recovery from ${journal}; its destinations or temporary ` +\n `paths do not match the current bundle.`,\n )\n }\n }\n\n const committed = (await readOptional(transactionMarker(journal))) !== null\n const errors: string[] = []\n if (committed) {\n for (const entry of transaction.entries) {\n if (entry.backup) await remove(entry.backup, errors)\n await remove(entry.stage, errors)\n }\n } else {\n for (const entry of [...transaction.entries].reverse()) {\n const backup = entry.backup ? await readOptional(entry.backup) : null\n const destination = await readOptional(entry.destination)\n if (backup) {\n if (destination && digest(destination) !== entry.sha256) {\n errors.push(\n `destination changed during interrupted recovery: ${entry.destination}; ` +\n `previous file remains at ${entry.backup}`,\n )\n continue\n }\n await remove(entry.destination, errors)\n try {\n await rename(entry.backup!, entry.destination)\n } catch (error) {\n errors.push(\n `could not restore ${entry.destination}; previous file remains at ` +\n `${entry.backup}: ${message(error)}`,\n )\n }\n } else if (destination && digest(destination) === entry.sha256) {\n await remove(entry.destination, errors)\n }\n await remove(entry.stage, errors)\n }\n }\n\n if (errors.length) {\n throw new Error(\n `Artifact transaction recovery needs attention; journal retained at ${journal}: ` +\n errors.join(\"; \"),\n )\n }\n await removeTransactionFiles(journal)\n}\n\n/** Build the deterministic companion metadata written beside a derived bundle. */\nexport function createArtifactBundleManifest(\n manifestPath: string,\n outputs: ArtifactFile[],\n provenance: ArtifactProvenance,\n): ArtifactBundleManifest {\n const root = path.dirname(path.resolve(manifestPath))\n const sources = provenance.sources.map((source) => ({\n ...source,\n path: portableRelative(root, source.path),\n }))\n const normalized = {\n kind: provenance.kind,\n sources,\n options: canonical(provenance.options),\n }\n const manifestOutputs = outputs.map((output) => ({\n path: portableRelative(root, output.path),\n sha256: digest(output.data),\n }))\n return {\n format: \"pixelkiln-artifact-bundle\",\n version: 1,\n ...normalized,\n fingerprint: fingerprint({ ...normalized, outputs: manifestOutputs }),\n outputs: manifestOutputs,\n }\n}\n\n/** Add deterministic provenance metadata to a related set of generated files. */\nexport function withArtifactManifest(\n manifestPath: string,\n outputs: ArtifactFile[],\n provenance: ArtifactProvenance,\n): ArtifactFile[] {\n const manifest = createArtifactBundleManifest(manifestPath, outputs, provenance)\n return [\n ...outputs,\n { path: manifestPath, data: JSON.stringify(manifest, null, 2) + \"\\n\" },\n ]\n}\n\n/**\n * Persist a generated bundle while protecting files not demonstrably owned by\n * its existing companion manifest. Byte-identical legacy files are adopted\n * without rewriting; `force` is required to take over anything else.\n */\nexport async function writeManagedArtifactBundle(\n manifestPath: string,\n outputs: ArtifactFile[],\n provenance: ArtifactProvenance,\n options: ManagedArtifactBundleOptions = {},\n): Promise<ArtifactBundleResult> {\n const absoluteManifest = path.resolve(manifestPath)\n const recoveryFile = `${absoluteManifest}.transaction`\n const allowedDestinations = new Set([\n absoluteManifest,\n ...outputs.map((output) => path.resolve(output.path)),\n ])\n await recoverArtifactTransaction(recoveryFile, allowedDestinations)\n const existingManifestBytes = await readOptional(absoluteManifest)\n let previous: ArtifactBundleManifest | null = null\n\n if (existingManifestBytes && !options.force) {\n try {\n previous = parseArtifactManifest(absoluteManifest, existingManifestBytes.toString(\"utf8\"))\n const valid = previous.fingerprint === fingerprint(previous)\n if (!valid) throw new Error(\"its integrity fingerprint does not match\")\n } catch (error) {\n throw new Error(\n `Refusing to replace unrecognized or modified provenance at ${absoluteManifest}: ` +\n `${message(error)}. Pass { force: true } (CLI: --force) to take ownership ` +\n `of this artifact bundle.`,\n { cause: error },\n )\n }\n }\n\n if (!options.force) {\n const root = path.dirname(absoluteManifest)\n const recorded = new Map(\n previous?.outputs.map((output) => [path.resolve(root, output.path), output.sha256]) ?? [],\n )\n const conflicts: string[] = []\n for (const output of outputs) {\n const destination = path.resolve(output.path)\n const current = await readOptional(destination)\n if (!current || digest(current) === digest(output.data)) continue\n const expected = recorded.get(destination)\n if (!expected || digest(current) !== expected) conflicts.push(destination)\n }\n if (conflicts.length) {\n throw new Error(\n `Refusing to overwrite modified or unowned artifact file(s):\\n` +\n conflicts.map((file) => ` ${file}`).join(\"\\n\") +\n `\\nPass { force: true } (CLI: --force) to take ownership and replace ` +\n `the complete bundle.`,\n )\n }\n }\n\n const { force: _force, ...bundleOptions } = options\n return writeArtifactBundle(\n withArtifactManifest(absoluteManifest, outputs, provenance),\n { ...bundleOptions, recoveryFile },\n )\n}\n\n/** Verify stored provenance and source/output hashes without rebuilding output. */\nexport async function verifyArtifactBundle(manifestPath: string): Promise<ArtifactVerification> {\n const absolute = path.resolve(manifestPath)\n const raw = await readArtifactBundleManifest(absolute)\n\n const root = path.dirname(absolute)\n const changedSources: string[] = []\n const changedOutputs: string[] = []\n for (const source of raw.sources) {\n let actual: string | null = null\n try {\n actual = digest(await readFile(path.resolve(root, source.path)))\n } catch (error) {\n if (!isCode(error, \"ENOENT\")) throw error\n }\n if (actual !== source.sha256) changedSources.push(source.id)\n }\n for (const output of raw.outputs) {\n try {\n if (digest(await readFile(path.resolve(root, output.path))) !== output.sha256) {\n changedOutputs.push(output.path)\n }\n } catch (error) {\n if (!isCode(error, \"ENOENT\")) throw error\n changedOutputs.push(output.path)\n }\n }\n\n const fingerprintValid = raw.fingerprint === fingerprint({\n kind: raw.kind,\n sources: raw.sources,\n options: raw.options,\n outputs: raw.outputs,\n })\n return {\n current: fingerprintValid && !changedSources.length && !changedOutputs.length,\n fingerprintValid,\n changedSources,\n changedOutputs,\n }\n}\n\nfunction isCode(error: unknown, code: string): boolean {\n return typeof error === \"object\" && error !== null && \"code\" in error && error.code === code\n}\n\nasync function remove(file: string, errors?: string[]): Promise<void> {\n try {\n await rm(file, { force: true })\n } catch (error) {\n errors?.push(`could not remove ${file}: ${message(error)}`)\n }\n}\n\nasync function rollback(prepared: PreparedArtifact[]): Promise<string[]> {\n const errors: string[] = []\n\n // Remove newly-promoted members before putting their previous versions back.\n for (const artifact of [...prepared].reverse()) {\n if (artifact.promoted) await remove(artifact.destination, errors)\n }\n\n for (const artifact of [...prepared].reverse()) {\n if (!artifact.backup || !artifact.backedUp) continue\n try {\n await rename(artifact.backup, artifact.destination)\n artifact.backedUp = false\n } catch (error) {\n errors.push(\n `could not restore ${artifact.destination}; previous file remains at ` +\n `${artifact.backup}: ${message(error)}`,\n )\n }\n }\n\n for (const artifact of prepared) {\n if (artifact.stage) await remove(artifact.stage, errors)\n }\n return errors\n}\n\n/**\n * Write a related set of generated files without leaving a partial bundle\n * after an ordinary write failure.\n *\n * All changed members are staged before any destination is replaced. If an\n * ordinary filesystem error interrupts promotion, prior files are restored.\n * Byte-identical members are not rewritten.\n */\nexport async function writeArtifactBundle(\n files: ArtifactFile[],\n options: ArtifactBundleOptions = {},\n): Promise<ArtifactBundleResult> {\n if (!files.length) throw new Error(\"An artifact bundle must contain at least one file.\")\n\n const normalized = files.map((file) => {\n if (!file.path.trim()) throw new Error(\"Artifact paths cannot be empty.\")\n return { destination: path.resolve(file.path), data: Buffer.from(file.data) }\n })\n const destinations = new Set<string>()\n for (const artifact of normalized) {\n if (destinations.has(artifact.destination)) {\n throw new Error(`Artifact bundle contains duplicate destination: ${artifact.destination}`)\n }\n destinations.add(artifact.destination)\n }\n if (options.recoveryFile) {\n await recoverArtifactTransaction(options.recoveryFile, destinations)\n }\n\n const changed: PreparedArtifact[] = []\n const unchanged: string[] = []\n for (const artifact of normalized) {\n try {\n const current = await readFile(artifact.destination)\n if (current.equals(artifact.data)) {\n unchanged.push(artifact.destination)\n } else {\n changed.push({ ...artifact, existed: true, backedUp: false, promoted: false })\n }\n } catch (error) {\n if (!isCode(error, \"ENOENT\")) throw error\n changed.push({ ...artifact, existed: false, backedUp: false, promoted: false })\n }\n }\n\n if (!changed.length) return { changed: [], unchanged }\n\n const token = randomUUID()\n for (const [index, artifact] of changed.entries()) {\n const basename = path.basename(artifact.destination)\n artifact.stage = path.join(\n path.dirname(artifact.destination),\n `.${basename}.pixelkiln-stage-${token}-${index}`,\n )\n if (artifact.existed) {\n artifact.backup = path.join(\n path.dirname(artifact.destination),\n `.${basename}.pixelkiln-backup-${token}-${index}`,\n )\n }\n }\n\n const journal = options.recoveryFile ? path.resolve(options.recoveryFile) : null\n if (journal) {\n await mkdir(path.dirname(journal), { recursive: true })\n const transaction: ArtifactTransaction = {\n format: \"pixelkiln-artifact-transaction\",\n version: 1,\n pid: process.pid,\n createdAt: new Date().toISOString(),\n entries: changed.map((artifact) => ({\n destination: artifact.destination,\n stage: artifact.stage!,\n ...(artifact.backup ? { backup: artifact.backup } : {}),\n sha256: digest(artifact.data),\n })),\n }\n try {\n await writeFile(journal, JSON.stringify(transaction, null, 2) + \"\\n\", { flag: \"wx\" })\n activeTransactions.add(journal)\n } catch (error) {\n throw new Error(\n `Could not start durable artifact transaction at ${journal}: ${message(error)}`,\n { cause: error },\n )\n }\n }\n\n try {\n for (const [index, artifact] of changed.entries()) {\n await mkdir(path.dirname(artifact.destination), { recursive: true })\n await options.beforeStage?.(artifact.destination, index)\n await writeFile(artifact.stage!, artifact.data, { flag: \"wx\" })\n }\n } catch (error) {\n const cleanupErrors = await rollback(changed)\n if (journal && !cleanupErrors.length) await removeTransactionFiles(journal)\n if (journal) activeTransactions.delete(journal)\n const suffix = cleanupErrors.length ? ` Cleanup also failed: ${cleanupErrors.join(\"; \")}` : \"\"\n throw new Error(`Could not stage artifact bundle: ${message(error)}.${suffix}`, { cause: error })\n }\n\n let durableCommit = false\n try {\n // Move every prior member aside first. Once promotion begins, rollback has\n // a complete snapshot even when several destinations are being replaced.\n for (const artifact of changed) {\n if (!artifact.existed) continue\n await rename(artifact.destination, artifact.backup!)\n artifact.backedUp = true\n }\n\n for (const [index, artifact] of changed.entries()) {\n await options.beforePromote?.(artifact.destination, index)\n await rename(artifact.stage!, artifact.destination)\n artifact.stage = undefined\n artifact.promoted = true\n }\n if (journal) {\n await writeFile(transactionMarker(journal), `${token}\\n`, { flag: \"wx\" })\n durableCommit = true\n await options.afterCommit?.()\n }\n } catch (error) {\n if (durableCommit) {\n if (journal) activeTransactions.delete(journal)\n throw new Error(\n `Artifact bundle was committed, but final cleanup was interrupted: ${message(error)}. ` +\n `The next write will finish cleanup from ${journal}.`,\n { cause: error },\n )\n }\n const rollbackErrors = await rollback(changed)\n if (journal && !rollbackErrors.length) await removeTransactionFiles(journal)\n if (journal) activeTransactions.delete(journal)\n const suffix = rollbackErrors.length\n ? ` Rollback needs attention: ${rollbackErrors.join(\"; \")}`\n : \" Previous bundle restored.\"\n throw new Error(`Could not promote artifact bundle: ${message(error)}.${suffix}`, { cause: error })\n }\n\n const cleanupErrors: string[] = []\n for (const artifact of changed) {\n if (artifact.backup) await remove(artifact.backup, cleanupErrors)\n }\n if (cleanupErrors.length) {\n if (journal) activeTransactions.delete(journal)\n throw new Error(\n `Artifact bundle was written, but old backup cleanup failed: ${cleanupErrors.join(\"; \")}`,\n )\n }\n if (journal) {\n try {\n await removeTransactionFiles(journal)\n } finally {\n activeTransactions.delete(journal)\n }\n }\n\n return {\n changed: changed.map((artifact) => artifact.destination),\n unchanged,\n }\n}\n","import { readFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { decodePng, extractPalette, transparencyRatio, type PaletteEntry } from \"../png.ts\"\nimport type { LoadedManifest } from \"../manifest.ts\"\nimport type { Lock, ResolvedSpec } from \"../types.ts\"\nimport { resolveSpecOutputs } from \"../outputs.ts\"\n\n/**\n * Perceptual-ish distance between two colours, 0-255ish.\n *\n * \"Redmean\" — a cheap weighting that tracks human perception far better than\n * raw RGB euclidean and needs no colour-space conversion or dependency. Good\n * enough to rank outliers, which is all this is for; it is not colourimetry.\n */\nexport function colorDistance(\n a: { r: number; g: number; b: number },\n b: { r: number; g: number; b: number },\n): number {\n const rmean = (a.r + b.r) / 2\n const dr = a.r - b.r\n const dg = a.g - b.g\n const db = a.b - b.b\n return Math.sqrt(\n (((512 + rmean) * dr * dr) / 256) + 4 * dg * dg + (((767 - rmean) * db * db) / 256),\n )\n}\n\n/**\n * How far an asset's palette sits from a reference palette.\n *\n * For each colour in the asset, weighted by how much of the image it covers,\n * take the distance to its nearest reference colour. An asset built entirely\n * from on-style colours scores ~0; one introducing a foreign hue scores high\n * in proportion to how much of the image that hue occupies.\n */\nexport function paletteDistance(asset: PaletteEntry[], reference: PaletteEntry[]): number {\n if (!asset.length || !reference.length) return 0\n let total = 0\n let weight = 0\n for (const color of asset) {\n let nearest = Infinity\n for (const ref of reference) nearest = Math.min(nearest, colorDistance(color, ref))\n total += nearest * color.weight\n weight += color.weight\n }\n return weight === 0 ? 0 : total / weight\n}\n\n/** Merge many palettes into one, summing weights for repeated colours. */\nexport function mergePalettes(palettes: PaletteEntry[][], topN = 24): PaletteEntry[] {\n const totals = new Map<string, PaletteEntry>()\n for (const palette of palettes) {\n for (const color of palette) {\n const key = `${color.r},${color.g},${color.b}`\n const existing = totals.get(key)\n if (existing) existing.weight += color.weight\n else totals.set(key, { ...color })\n }\n }\n const merged = [...totals.values()].sort((a, b) => b.weight - a.weight).slice(0, topN)\n const sum = merged.reduce((s, c) => s + c.weight, 0) || 1\n return merged.map((c) => ({ ...c, weight: c.weight / sum }))\n}\n\nexport interface AssetAudit {\n assetId: string\n /** Present when this is one member of a structural multi-output asset. */\n outputRole?: string\n /** Stable report/atlas identity: assetId for one output, assetId/role for many. */\n id: string\n file: string\n width: number\n height: number\n /** Distance from the style's reference palette. Higher is more off-style. */\n paletteDistance: number\n /** Share of the canvas that is transparent. Very low suggests a baked background. */\n transparency: number\n /** Distinct opaque colours. Very high suggests photo-like rendering, not pixel art. */\n colorCount: number\n palette: PaletteEntry[]\n}\n\nexport interface StyleAudit {\n styleId: string\n /** True when the reference came from the style's own styleImages. */\n referenceFromStyleImages: boolean\n reference: PaletteEntry[]\n assets: AssetAudit[]\n missing: string[]\n unreadable: string[]\n}\n\nexport interface AuditThresholds {\n /** Absolute palette-distance ceiling. Omit to rely on relative outliers. */\n maxDistance?: number\n /** Minimum transparent share of the canvas, from 0 to 1. */\n minTransparency?: number\n /** Maximum number of distinct opaque colors. */\n maxColors?: number\n /** Relative outlier cutoff. Defaults to 1.5 standard deviations. */\n sigma?: number\n}\n\nexport interface AuditViolation {\n id: string\n reasons: string[]\n}\n\nexport interface AuditEvaluation {\n safe: boolean\n thresholds: Required<Pick<AuditThresholds, \"sigma\">> & Omit<AuditThresholds, \"sigma\">\n outliers: string[]\n violations: AuditViolation[]\n missing: string[]\n unreadable: string[]\n}\n\n/**\n * Measures how consistently a style's assets actually hold together.\n *\n * This exists to answer \"is this variant working?\" with a number instead of an\n * eyeball. Measured on a real neon trial, prose alone carried the style on\n * subjects with no strong inherent colour but was ignored on ones that had\n * some — a chocolate bar stayed brown, a camera stayed grey. Those are exactly\n * the assets this ranks to the top, before another 57 are generated to match.\n *\n * Reference palette comes from the style's `styleImages` when set, since those\n * are the declared intent. Otherwise the assets are compared against their own\n * collective palette, which still surfaces outliers but cannot tell you the\n * whole set has drifted together.\n */\nexport async function auditStyle(\n loaded: LoadedManifest,\n specs: ResolvedSpec[],\n styleId: string,\n lock?: Lock,\n): Promise<StyleAudit> {\n const style = loaded.manifest.styles[styleId]\n if (!style) throw new Error(`Unknown style \"${styleId}\"`)\n\n const mine = specs.filter((s) => s.styleId === styleId)\n const assets: AssetAudit[] = []\n const missing: string[] = []\n const unreadable: string[] = []\n\n for (const spec of mine) {\n for (const output of resolveSpecOutputs(spec, lock, loaded.root)) {\n if (!existsSync(output.absolutePath)) {\n missing.push(output.id)\n continue\n }\n try {\n const png = decodePng(await readFile(output.absolutePath))\n const palette = extractPalette(png, 12)\n assets.push({\n assetId: spec.assetId,\n ...(output.role ? { outputRole: output.role } : {}),\n id: output.id,\n file: output.absolutePath,\n width: png.width,\n height: png.height,\n paletteDistance: 0, // filled once the reference is known\n transparency: transparencyRatio(png),\n colorCount: countColors(png),\n palette,\n })\n } catch (err) {\n unreadable.push(`${output.id}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n }\n\n // Prefer the declared intent over the set's own average.\n let reference: PaletteEntry[] = []\n let referenceFromStyleImages = false\n const refPalettes: PaletteEntry[][] = []\n for (const img of style.styleImages) {\n const abs = path.resolve(loaded.root, img.path)\n if (!existsSync(abs)) continue\n try {\n refPalettes.push(extractPalette(decodePng(await readFile(abs)), 12))\n } catch {\n // A malformed reference should not sink the audit.\n }\n }\n if (refPalettes.length) {\n reference = mergePalettes(refPalettes)\n referenceFromStyleImages = true\n for (const asset of assets) {\n asset.paletteDistance = paletteDistance(asset.palette, reference)\n }\n } else {\n // Reported reference is the whole set, but each asset is scored against\n // the set MINUS itself. Including an asset in its own reference lets it\n // match perfectly, which would make the most divergent asset — the one\n // worth finding — score zero.\n reference = mergePalettes(assets.map((a) => a.palette))\n for (const asset of assets) {\n const others = assets.filter((a) => a !== asset).map((a) => a.palette)\n asset.paletteDistance = others.length\n ? paletteDistance(asset.palette, mergePalettes(others))\n : 0\n }\n }\n assets.sort((a, b) => b.paletteDistance - a.paletteDistance)\n\n return { styleId, referenceFromStyleImages, reference, assets, missing, unreadable }\n}\n\nfunction countColors(png: { pixels: Buffer }): number {\n const seen = new Set<number>()\n for (let i = 0; i < png.pixels.length; i += 4) {\n if (png.pixels[i + 3]! < 128) continue\n seen.add((png.pixels[i]! << 16) | (png.pixels[i + 1]! << 8) | png.pixels[i + 2]!)\n }\n return seen.size\n}\n\n/** Assets more than `sigma` standard deviations off the mean distance. */\nexport function outliers(audit: StyleAudit, sigma = 1.5): AssetAudit[] {\n const n = audit.assets.length\n if (n < 3) return []\n const mean = audit.assets.reduce((s, a) => s + a.paletteDistance, 0) / n\n const variance = audit.assets.reduce((s, a) => s + (a.paletteDistance - mean) ** 2, 0) / n\n const sd = Math.sqrt(variance)\n if (sd === 0) return []\n return audit.assets.filter((a) => a.paletteDistance > mean + sigma * sd)\n}\n\n/** Turn an audit into a stable CI decision without hiding the underlying measurements. */\nexport function evaluateAudit(\n audit: StyleAudit,\n thresholds: AuditThresholds = {},\n): AuditEvaluation {\n const resolved = { ...thresholds, sigma: thresholds.sigma ?? 1.5 }\n const relative = outliers(audit, resolved.sigma)\n const relativeIds = new Set(relative.map((asset) => asset.id))\n const violations: AuditViolation[] = []\n\n for (const asset of audit.assets) {\n const reasons: string[] = []\n if (relativeIds.has(asset.id)) {\n reasons.push(`palette outlier beyond ${resolved.sigma} standard deviations`)\n }\n if (resolved.maxDistance !== undefined && asset.paletteDistance > resolved.maxDistance) {\n reasons.push(\n `palette distance ${asset.paletteDistance.toFixed(1)} exceeds ${resolved.maxDistance}`,\n )\n }\n if (\n resolved.minTransparency !== undefined &&\n asset.transparency < resolved.minTransparency\n ) {\n reasons.push(\n `transparency ${(asset.transparency * 100).toFixed(1)}% is below ` +\n `${(resolved.minTransparency * 100).toFixed(1)}%`,\n )\n }\n if (resolved.maxColors !== undefined && asset.colorCount > resolved.maxColors) {\n reasons.push(`color count ${asset.colorCount} exceeds ${resolved.maxColors}`)\n }\n if (reasons.length) violations.push({ id: asset.id, reasons })\n }\n\n return {\n safe: violations.length === 0 && audit.missing.length === 0 && audit.unreadable.length === 0,\n thresholds: resolved,\n outliers: [...relativeIds],\n violations,\n missing: [...audit.missing],\n unreadable: [...audit.unreadable],\n }\n}\n\nexport function hex(c: { r: number; g: number; b: number }): string {\n return `#${[c.r, c.g, c.b].map((v) => v.toString(16).padStart(2, \"0\")).join(\"\")}`\n}\n","import { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { sha256File } from \"../hash.ts\"\nimport { currentEntryOutputPath } from \"../outputs.ts\"\nimport { lockKey, type Lock, type ResolvedSpec } from \"../types.ts\"\nimport { inspectQualityProfile } from \"./quality-profile.ts\"\n\nexport interface RevisionReadiness {\n ready: boolean\n reason: string\n}\n\n/**\n * Prove that a revision points at the current bytes of a current parent.\n *\n * This runs during planning and again immediately before submission. The\n * second check closes the gap where a source or mask changes after a plan was\n * printed but before a paid provider request begins.\n */\nexport async function inspectRevisionReadiness(\n spec: ResolvedSpec,\n lock: Lock,\n): Promise<RevisionReadiness | null> {\n if (!spec.revision) return null\n return inspectRevision(spec, lock, new Set())\n}\n\nasync function inspectRevision(\n spec: ResolvedSpec,\n lock: Lock,\n seen: Set<string>,\n): Promise<RevisionReadiness> {\n const revision = spec.revision\n if (!revision) return { ready: true, reason: \"asset has no revision inputs\" }\n const dependency = await inspectParent(revision.sourceSpec, lock, seen)\n if (!dependency.ready) {\n return {\n ready: false,\n reason: `revision source ${spec.styleId}/${revision.sourceAssetId} is not ready: ${dependency.reason}`,\n }\n }\n\n if (!revision.sourceSha256 || !existsSync(revision.sourceFile)) {\n return { ready: false, reason: `revision source is missing: ${revision.sourceFile}` }\n }\n if ((await sha256File(revision.sourceFile)) !== revision.sourceSha256) {\n return { ready: false, reason: \"revision source changed after the manifest was resolved\" }\n }\n\n if (revision.maskFile) {\n if (!revision.maskSha256 || !existsSync(revision.maskFile)) {\n return { ready: false, reason: `revision mask is missing: ${revision.maskFile}` }\n }\n if ((await sha256File(revision.maskFile)) !== revision.maskSha256) {\n return { ready: false, reason: \"revision mask changed after the manifest was resolved\" }\n }\n }\n\n return { ready: true, reason: \"revision inputs are current\" }\n}\n\nexport async function requireRevisionReady(spec: ResolvedSpec, lock: Lock): Promise<void> {\n const inspection = await inspectRevisionReadiness(spec, lock)\n if (inspection && !inspection.ready) throw new Error(inspection.reason)\n}\n\nasync function inspectParent(\n spec: ResolvedSpec,\n lock: Lock,\n seen: Set<string>,\n): Promise<RevisionReadiness> {\n const key = lockKey(spec.styleId, spec.assetId)\n if (seen.has(key)) return { ready: false, reason: `revision dependency cycle at ${key}` }\n const nextSeen = new Set(seen)\n nextSeen.add(key)\n\n if (spec.revision) {\n const inputs = await inspectRevision(spec, lock, nextSeen)\n if (!inputs.ready) return inputs\n }\n\n if (spec.quality) {\n const quality = await inspectQualityProfile(spec, lock)\n return quality?.state === \"approved\"\n ? { ready: true, reason: \"approved quality output is current\" }\n : {\n ready: false,\n reason: `quality output is ${quality?.state ?? \"missing\"}` +\n (quality?.reason ? ` (${quality.reason})` : \"\"),\n }\n }\n\n if (spec.source) {\n const source = path.resolve(spec.root, spec.source)\n return existsSync(source)\n ? { ready: true, reason: \"declared source is present\" }\n : { ready: false, reason: `declared source is missing: ${spec.source}` }\n }\n\n const entry = lock.entries[key]\n if (!entry) return { ready: false, reason: \"parent is not in the lockfile\" }\n if (entry.specHash !== spec.specHash) {\n return { ready: false, reason: \"parent generation spec is stale\" }\n }\n if (entry.status !== \"downloaded\") {\n return { ready: false, reason: `parent is ${entry.status}, not downloaded` }\n }\n if (!entry.outputs.length) return { ready: false, reason: \"parent has no recorded output\" }\n for (let index = 0; index < entry.outputs.length; index++) {\n const output = entry.outputs[index]!\n const file = currentEntryOutputPath(entry, spec, index)\n if (!existsSync(file)) return { ready: false, reason: `parent output is missing: ${file}` }\n if ((await sha256File(file)) !== output.sha256) {\n return { ready: false, reason: `parent output was modified: ${file}` }\n }\n }\n return { ready: true, reason: \"parent output is current\" }\n}\n","import {\n DEFAULT_RATE_LIMIT,\n formatCost,\n validateCostEstimate,\n type CostUnit,\n type Provider,\n} from \"../provider.ts\"\nimport { saveLock, upsert } from \"../lock.ts\"\nimport { resolveStyleImages, type LoadedManifest } from \"../manifest.ts\"\nimport type { Lock, ResolvedSpec, ResolvedStyleImage } from \"../types.ts\"\nimport type { PlanItem } from \"./plan.ts\"\nimport { requireRevisionReady } from \"./revision.ts\"\n\n/**\n * Two distinct limits, easy to conflate:\n * - submissions must be spaced apart (a rate, global across the account)\n * - background jobs in flight (a count)\n *\n * Both are the provider's own constraint (PixelLab: >2s apart; Tier 1=8,\n * Tier 2=10, Tier 3=20 in flight) surfaced through `provider.rateLimit()`,\n * not a number this pipeline layer should know on its own — a second\n * provider with different limits must not silently inherit PixelLab's.\n *\n * Submission is fast and job execution is slow, so the correct shape is a\n * serial submit loop with a global spacing gate, which pauses when too many\n * jobs are still running. Parallel workers each sleeping `spacing` would give a\n * global rate of workers/spacing and quietly breach the first limit.\n */\nconst IN_FLIGHT_POLL_MS = 5000\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))\n\nexport interface SubmitOptions {\n maxInFlight?: number\n spacingMs?: number\n /** How often to re-check occupied background-job slots. */\n slotPollMs?: number\n /** Stop waiting for an unreadable/stuck slot instead of hanging forever. */\n slotTimeoutMs?: number\n /** Refuse to submit if the run would exceed this much, in the provider's unit. */\n budget?: number\n onProgress?: (msg: string) => void\n}\n\nexport interface SubmitResult {\n submitted: number\n failed: number\n /** Successful-submission estimates in `unit`. */\n spent: number\n unit: CostUnit\n}\n\nexport async function submit(\n provider: Provider,\n loaded: LoadedManifest,\n items: PlanItem[],\n lock: Lock,\n lockPath: string,\n opts: SubmitOptions = {},\n): Promise<SubmitResult> {\n const limits = provider.rateLimit?.() ?? DEFAULT_RATE_LIMIT\n const maxInFlight = opts.maxInFlight ?? limits.maxInFlight\n const spacing = opts.spacingMs ?? limits.spacingMs\n const slotPollMs = opts.slotPollMs ?? IN_FLIGHT_POLL_MS\n const slotTimeoutMs = opts.slotTimeoutMs ?? 15 * 60 * 1000\n const log = opts.onProgress ?? (() => {})\n\n const estimates = new Map(items.map((item) => [\n item.key,\n validateCostEstimate(provider.id, provider.estimate(item.spec)),\n ]))\n const units = new Set([...estimates.values()].map((estimate) => estimate.unit))\n if (units.size > 1) {\n throw new Error(`Provider \"${provider.id}\" returned mixed cost units for one submission batch`)\n }\n const unit = units.values().next().value ?? \"free\"\n\n if (opts.budget != null) {\n const cost = [...estimates.values()].reduce((sum, estimate) => sum + estimate.amount, 0)\n if (cost > opts.budget) {\n throw new Error(\n `This run would spend ${formatCost(unit, cost)} but the budget is ` +\n `${formatCost(unit, opts.budget)}. ` +\n `Narrow it with --only/--style, or raise --budget.`,\n )\n }\n }\n\n const styleImages = new Map<string, ResolvedStyleImage[]>()\n for (const styleId of new Set(items.map((i) => i.spec.styleId))) {\n styleImages.set(styleId, await resolveStyleImages(loaded, styleId))\n }\n\n let submitted = 0\n let failed = 0\n let spent = 0\n let lastSubmitAt = 0\n\n /** Jobs submitted this run not yet observed as settled, with their generator. */\n const inFlight = new Map<string, ResolvedSpec>()\n let lastSlotError: string | null = null\n\n async function pruneInFlight(): Promise<void> {\n for (const [id, spec] of [...inFlight]) {\n try {\n const state = await provider.poll(id, spec.generator, { spec, tileFeature: spec.tileFeature })\n if (state.status !== \"processing\") inFlight.delete(id)\n lastSlotError = null\n } catch (err) {\n // A transient provider/network error is not evidence that a paid job\n // settled. Keep the slot occupied so we never exceed the upstream cap.\n lastSlotError = err instanceof Error ? err.message : String(err)\n }\n }\n }\n\n async function waitForSlot(): Promise<void> {\n const started = Date.now()\n while (inFlight.size >= maxInFlight) {\n if (Date.now() - started >= slotTimeoutMs) {\n throw new Error(\n `Timed out waiting for a generation slot` +\n (lastSlotError ? `; last poll error: ${lastSlotError}` : \"\"),\n )\n }\n await sleep(slotPollMs)\n await pruneInFlight()\n }\n }\n\n for (const { spec, key } of items) {\n const estimate = estimates.get(key)!\n await waitForSlot()\n\n const since = Date.now() - lastSubmitAt\n if (since < spacing) await sleep(spacing - since)\n\n // Planning already checked this dependency, but inputs can change while a\n // long batch waits for a provider slot. Recheck at the spending boundary.\n await requireRevisionReady(spec, lock)\n\n const previousEntry = lock.entries[key]\n const resumesCheckpoint = Boolean(\n previousEntry?.specHash === spec.specHash &&\n previousEntry.provider === provider.id &&\n previousEntry.generator === spec.generator &&\n previousEntry.submissionComplete === false &&\n previousEntry.jobId,\n )\n const previousJobId = resumesCheckpoint ? previousEntry!.jobId! : undefined\n const previousMetadata = resumesCheckpoint\n ? previousEntry!.providerMetadata[provider.id]\n : undefined\n const supersededOutputs = previousEntry?.outputs.length\n ? previousEntry.outputs\n : previousEntry?.supersededOutputs ?? []\n\n // Record intent before spending, so an interrupted run stays diagnosable.\n upsert(lock, key, {\n styleId: spec.styleId,\n assetId: spec.assetId,\n specHash: spec.specHash,\n generator: spec.generator,\n tileFeature: spec.tileFeature ?? null,\n prompt: spec.prompt,\n width: spec.width,\n height: spec.height,\n revision: spec.revision\n ? {\n mode: spec.revision.mode,\n sourceAssetId: spec.revision.sourceAssetId,\n sourceSha256: spec.revision.sourceSha256!,\n ...(spec.revision.maskSha256 ? { maskSha256: spec.revision.maskSha256 } : {}),\n ...(spec.revision.strength == null ? {} : { strength: spec.revision.strength }),\n }\n : null,\n status: \"pending\",\n jobId: previousJobId ?? null,\n ...(previousJobId ? { submissionComplete: false } : { submissionComplete: undefined }),\n objectId: null,\n reviewObjectId: null,\n candidateIndex: null,\n error: null,\n outputs: [],\n // Keep the old ownership proof while new bytes are pending. Fetch may\n // replace that file only while its hash still matches this record.\n supersededOutputs,\n providerMetadata: resumesCheckpoint ? previousEntry!.providerMetadata : {},\n sourceUrl: null,\n sourceUrls: [],\n submittedAt: resumesCheckpoint\n ? previousEntry!.submittedAt\n : new Date().toISOString(),\n cost: estimate.amount,\n costUnit: estimate.unit,\n // Persist routing before the request starts. If the process stops while\n // the provider is accepting work, a resumed run must not fall back to\n // PixelLab (the legacy lock default) for another provider's entry.\n provider: provider.id,\n downloadedAt: null,\n })\n await saveLock(lockPath, lock)\n\n lastSubmitAt = Date.now()\n try {\n // The adapter decides whether references are meaningful for this\n // generator. Keeping that policy here used to silently discard valid\n // references for non-PixelLab still providers.\n const refs = styleImages.get(spec.styleId) ?? []\n const { jobId, metadata } = await provider.submit(spec, refs, {\n ...(previousJobId ? { previousJobId } : {}),\n ...(previousMetadata ? { previousMetadata } : {}),\n checkpoint: async (checkpoint) => {\n if (!checkpoint.jobId) throw new Error(\"Provider checkpoint returned an empty job id\")\n const entry = lock.entries[key]!\n upsert(lock, key, {\n jobId: checkpoint.jobId,\n submissionComplete: checkpoint.complete,\n reviewObjectId:\n checkpoint.complete &&\n (spec.generator === \"frames\" || (estimate.candidates > 1 && !spec.tileFeature))\n ? checkpoint.jobId\n : null,\n status: checkpoint.complete ? \"processing\" : \"pending\",\n error: null,\n providerMetadata: checkpoint.metadata\n ? {\n ...entry.providerMetadata,\n [provider.id]: {\n ...entry.providerMetadata[provider.id],\n ...checkpoint.metadata,\n },\n }\n : entry.providerMetadata,\n })\n await saveLock(lockPath, lock)\n },\n })\n upsert(lock, key, {\n jobId,\n submissionComplete: true,\n // A multi-candidate generator routes through review; record the parent\n // so `pick` knows where to look.\n reviewObjectId:\n spec.generator === \"frames\" || (estimate.candidates > 1 && !spec.tileFeature)\n ? jobId\n : null,\n status: \"processing\",\n providerMetadata: metadata\n ? { ...lock.entries[key]!.providerMetadata, [provider.id]: metadata }\n : lock.entries[key]!.providerMetadata,\n })\n inFlight.set(jobId, spec)\n submitted++\n spent += estimate.amount\n log(\n ` ${key} → ${jobId} (${spec.width}x${spec.height}` +\n (estimate.candidates > 1\n ? `, ${estimate.candidates} ${spec.tileFeature ? \"outputs\" : \"candidates\"}`\n : \"\") +\n `, ${estimate.amount})`,\n )\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n const entry = lock.entries[key]!\n if (entry.jobId && entry.submissionComplete === true) {\n // A completed checkpoint is authoritative even if the adapter is\n // interrupted before returning the same job id to this stack frame.\n upsert(lock, key, { status: \"processing\", error: null })\n inFlight.set(entry.jobId, spec)\n submitted++\n spent += estimate.amount\n log(` ${key} → ${entry.jobId} (recovered from completed checkpoint)`)\n } else {\n failed++\n // A request with no checkpoint was rejected before any remote identity\n // was accepted. Partial submissions keep their estimate and every id.\n upsert(lock, key, {\n status: \"failed\",\n error: message,\n cost: entry.jobId ? estimate.amount : 0,\n })\n log(` FAILED ${key}: ${message}`)\n }\n }\n await saveLock(lockPath, lock)\n }\n\n return { submitted, failed, spent, unit }\n}\n","import { saveLock, upsert } from \"../lock.ts\"\nimport type { Provider } from \"../provider.ts\"\nimport type { Lock } from \"../types.ts\"\nimport { lockKey, type ResolvedSpec } from \"../types.ts\"\n\nconst sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))\n\nexport interface PollOptions {\n intervalMs?: number\n timeoutMs?: number\n onProgress?: (msg: string) => void\n specs?: ResolvedSpec[]\n}\n\nexport interface PollResult {\n review: number\n completed: number\n failed: number\n stillRunning: number\n}\n\n/**\n * Advances every unfinished lock entry to its settled state.\n *\n * Safe to run repeatedly and safe to interrupt — all state lives in the\n * lockfile, so a re-run picks up exactly where the last one stopped. Provider\n * quirks (a job record that expires before its image does, review-status\n * candidate lists) are the provider's problem, not this loop's.\n */\nexport async function poll(\n provider: Provider,\n lock: Lock,\n lockPath: string,\n opts: PollOptions = {},\n): Promise<PollResult> {\n const interval = opts.intervalMs ?? 5000\n const timeout = opts.timeoutMs ?? 15 * 60 * 1000\n const log = opts.onProgress ?? (() => {})\n const started = Date.now()\n const specByKey = new Map((opts.specs ?? []).map((s) => [lockKey(s.styleId, s.assetId), s]))\n const selectedKeys = opts.specs ? new Set(specByKey.keys()) : null\n\n const result: PollResult = { review: 0, completed: 0, failed: 0, stillRunning: 0 }\n\n const incompleteSubmissions = Object.entries(lock.entries).filter(\n ([key, entry]) =>\n entry.provider === provider.id &&\n (!selectedKeys || selectedKeys.has(key)) &&\n entry.jobId &&\n entry.submissionComplete === false &&\n (entry.status === \"pending\" || entry.status === \"processing\"),\n )\n for (const [key] of incompleteSubmissions) {\n log(` incomplete submission ${key}; rerun \\`pixelkiln submit\\` to resume`)\n }\n result.stillRunning = incompleteSubmissions.length\n\n const pending = () =>\n Object.entries(lock.entries).filter(\n ([key, e]) =>\n e.provider === provider.id &&\n (!selectedKeys || selectedKeys.has(key)) &&\n e.jobId &&\n e.submissionComplete !== false &&\n (e.status === \"pending\" || e.status === \"processing\"),\n )\n\n while (pending().length > 0) {\n if (Date.now() - started > timeout) {\n result.stillRunning += pending().length\n log(` timed out with ${result.stillRunning} job(s) still running — re-run \\`poll\\` to resume`)\n break\n }\n\n for (const [key, entry] of pending()) {\n try {\n const currentSpec = specByKey.get(key)\n const state = await provider.poll(entry.jobId!, entry.generator, {\n tileFeature: entry.tileFeature ?? currentSpec?.tileFeature,\n spec: currentSpec,\n })\n if (state.status === \"review\" || state.status === \"review-set\") {\n upsert(lock, key, {\n status: \"review\",\n reviewObjectId: entry.jobId,\n providerMetadata: state.metadata\n ? {\n ...entry.providerMetadata,\n [provider.id]: {\n ...entry.providerMetadata[provider.id],\n ...state.metadata,\n },\n }\n : entry.providerMetadata,\n })\n result.review++\n log(\n state.status === \"review-set\"\n ? ` review ${key} (${state.frameUrls.length} ordered frames)`\n : ` review ${key} (${state.candidateUrls.length} candidates)`,\n )\n } else if (state.status === \"ready\") {\n const sourceUrls = state.sources?.length\n ? state.sources\n : state.sourceUrl\n ? [{ url: state.sourceUrl }]\n : []\n upsert(lock, key, {\n status: \"selected\",\n objectId: state.objectId,\n sourceUrl: sourceUrls[0]?.url ?? null,\n sourceUrls,\n providerMetadata: state.metadata\n ? {\n ...entry.providerMetadata,\n [provider.id]: {\n ...entry.providerMetadata[provider.id],\n ...state.metadata,\n },\n }\n : entry.providerMetadata,\n error: null,\n })\n result.completed++\n log(` ready ${key}`)\n } else if (state.status === \"failed\") {\n upsert(lock, key, { status: \"failed\", error: state.error })\n result.failed++\n log(` FAILED ${key}: ${state.error}`)\n }\n } catch (err) {\n log(` error polling ${key}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n\n await saveLock(lockPath, lock)\n if (pending().length > 0) await sleep(interval)\n }\n\n await saveLock(lockPath, lock)\n return result\n}\n","import { existsSync } from \"node:fs\"\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport type { Provider } from \"../provider.ts\"\nimport { sha256, sha256File } from \"../hash.ts\"\nimport { saveLock, upsert } from \"../lock.ts\"\nimport {\n expectedOutputPath,\n currentOutputPath,\n normalizeLockOutputPaths,\n portableOutputPath,\n resolveOutputPath,\n} from \"../outputs.ts\"\nimport { lockKey, type Lock, type LockOutput, type ResolvedSpec } from \"../types.ts\"\nimport {\n cacheFileName,\n detectMediaType,\n MediaType,\n validateMedia,\n type MediaType as MediaKind,\n} from \"../media.ts\"\nimport { shouldPersistSourceUrl } from \"../source-url.ts\"\n\nexport interface FetchResult {\n downloaded: number\n skipped: number\n failed: number\n}\n\n/**\n * Downloads every selected object to its manifest-defined path and records the\n * file hash. The hash is what lets `plan` tell \"untouched\" from \"edited by\n * hand\" on later runs, so a manual retouch is never silently clobbered. The\n * same hash keys a local content cache, allowing `restore` to outlive a\n * provider's temporary storage URL.\n */\nexport async function fetchAssets(\n provider: Provider,\n specs: ResolvedSpec[],\n lock: Lock,\n lockPath: string,\n opts: {\n onProgress?: (msg: string) => void\n concurrency?: number\n repair?: boolean\n /** Replace an existing untracked or modified destination. Explicit ownership override. */\n force?: boolean\n /** Content-addressed media cache. Defaults beside the lockfile; false disables it. */\n cacheDir?: string | false\n } = {},\n): Promise<FetchResult> {\n const log = opts.onProgress ?? (() => {})\n const result: FetchResult = { downloaded: 0, skipped: 0, failed: 0 }\n const specByKey = new Map(specs.map((s) => [lockKey(s.styleId, s.assetId), s]))\n normalizeLockOutputPaths(lock, specs)\n const cacheDir =\n opts.cacheDir === false\n ? null\n : path.resolve(opts.cacheDir ?? path.join(path.dirname(lockPath), \".pixelkiln\", \"cache\"))\n\n // Downloads are independent and IO-bound, so they run concurrently. The\n // lockfile is still written after each one, keeping an interrupted run\n // recoverable.\n const pending = Object.entries(lock.entries).filter(([key, e]) => {\n if (e.provider !== provider.id || !specByKey.has(key)) return false\n if (e.status === \"selected\" || e.status === \"download-failed\") return true\n if (!opts.repair || e.status !== \"downloaded\") return false\n const spec = specByKey.get(key)\n return e.outputs.length === 0 || !spec ||\n e.outputs.some((output) => !existsSync(resolveOutputPath(output.path, spec.root)))\n })\n const concurrency = Math.min(Math.max(1, opts.concurrency ?? 8), Math.max(1, pending.length))\n let cursor = 0\n\n async function worker(): Promise<void> {\n for (;;) {\n const next = pending[cursor++]\n if (!next) return\n const [key, entry] = next\n\n const spec = specByKey.get(key)\n if (!spec) {\n // In the lockfile but no longer in the manifest — the asset was removed.\n log(` skip ${key} (not in current manifest)`)\n result.skipped++\n continue\n }\n if (entry.specHash !== spec.specHash) {\n log(` skip ${key} (source belongs to a stale spec)`)\n result.skipped++\n continue\n }\n const sources = entry.sourceUrls?.length\n ? entry.sourceUrls\n : entry.sourceUrl\n ? [{ url: entry.sourceUrl }]\n : opts.repair && entry.outputs.length\n ? entry.outputs.map((o) => ({ url: \"\", role: o.role, mediaType: o.mediaType }))\n : []\n if (!sources.length) {\n upsert(lock, key, {\n status: \"download-failed\",\n error: \"no persisted source URL to download; poll the job again if it still exists upstream\",\n })\n result.failed++\n continue\n }\n\n const outputs: LockOutput[] = []\n try {\n for (let index = 0; index < sources.length; index++) {\n const source = sources[index]!\n const recorded = entry.outputs.find((o) =>\n source.role ? o.role === source.role : !o.role && sources.length === 1,\n )\n const target = recorded\n ? resolveOutputPath(recorded.path, spec.root)\n : expectedOutputPath(spec, source.role, index, sources.length, source.mediaType)\n\n if (existsSync(target)) {\n const currentHash = await sha256File(target)\n if (recorded && currentHash === recorded.sha256) {\n if (cacheDir) {\n await cacheMedia(\n cacheDir,\n await readFile(target),\n recorded.mediaType ?? MediaType.PNG,\n recorded.sha256,\n )\n }\n outputs.push({ ...recorded, path: portableOutputPath(target, spec.root) })\n continue\n }\n\n const superseded = (entry.supersededOutputs ?? []).find((output, oldIndex, all) =>\n currentOutputPath(output, spec, oldIndex, all.length) === target,\n )\n if (!opts.force) {\n if (!recorded && superseded && currentHash === superseded.sha256) {\n // A stale spec was intentionally regenerated. The old bytes\n // are still exactly the ones PixelKiln wrote, so replacing\n // them does not take ownership of a manual edit.\n } else if (recorded || superseded) {\n throw new Error(\n `refusing to overwrite modified output ${target}; pass --force to replace it`,\n )\n } else {\n throw new Error(\n `refusing to overwrite untracked output ${target}; pass --force to replace it`,\n )\n }\n }\n log(\n ` replace ${path.relative(process.cwd(), target)}` +\n (opts.force ? \" (--force)\" : \" (previous tracked generation)\"),\n )\n }\n\n const expectedMediaType = source.mediaType ?? recorded?.mediaType ?? MediaType.PNG\n let buf = recorded && cacheDir\n ? await readCachedMedia(cacheDir, recorded.sha256, expectedMediaType)\n : null\n if (buf) {\n log(` cached ${path.relative(process.cwd(), target)}`)\n } else {\n if (!source.url) {\n throw new Error(`no source URL or cached bytes remain for ${source.role ?? \"asset\"}`)\n }\n buf = await provider.download(source.url)\n }\n let mediaType: MediaKind\n try {\n mediaType = validateMedia(buf, expectedMediaType)\n } catch (err) {\n const label = expectedMediaType === MediaType.GIF ? \"GIF\" : \"PNG\"\n const mismatch = detectMediaType(buf) !== expectedMediaType\n throw new Error(\n `response for ${source.role ?? \"asset\"} was not ${mismatch ? \"a\" : \"a valid\"} ${label}` +\n (mismatch ? ` (${buf.length} bytes)` : `: ${err instanceof Error ? err.message : String(err)}`),\n )\n }\n if (cacheDir) await cacheMedia(cacheDir, buf, mediaType)\n await mkdir(path.dirname(target), { recursive: true })\n const tmp = `${target}.pixelkiln.tmp`\n await writeFile(tmp, buf)\n outputs.push({\n path: portableOutputPath(target, spec.root),\n sha256: sha256(buf),\n ...(source.role ? { role: source.role } : {}),\n mediaType,\n })\n // Record the intended rename before performing it. If the process\n // dies in either half of this two-step commit, the next repair sees\n // a missing recorded output and safely downloads it again; it never\n // sees an untracked final file and gets stuck refusing to overwrite.\n upsert(lock, key, { outputs: mergeOutputs(entry.outputs, outputs) })\n await saveLock(lockPath, lock)\n await rename(tmp, target)\n log(` wrote ${path.relative(process.cwd(), target)}`)\n }\n const persistentSources = sources.filter((source) => shouldPersistSourceUrl(source.url))\n upsert(lock, key, {\n status: \"downloaded\",\n provider: provider.id,\n outputs,\n // A finished lock may be committed. Inline bytes, machine-local\n // paths, and credential-bearing signed URLs are useful while a\n // download is retryable but must not survive successful ingestion.\n sourceUrl: persistentSources[0]?.url ?? null,\n sourceUrls: persistentSources,\n downloadedAt: new Date().toISOString(),\n error: null,\n supersededOutputs: [],\n })\n result.downloaded++\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n upsert(lock, key, {\n status: \"download-failed\",\n outputs: mergeOutputs(entry.outputs, outputs),\n error: `download failed: ${message}`,\n })\n result.failed++\n log(` FAILED ${key}: ${message}`)\n }\n await saveLock(lockPath, lock)\n }\n }\n\n await Promise.all(Array.from({ length: concurrency }, worker))\n await saveLock(lockPath, lock)\n return result\n}\n\nasync function readCachedMedia(\n cacheDir: string,\n hash: string,\n mediaType: MediaKind,\n): Promise<Buffer | null> {\n const file = path.join(cacheDir, cacheFileName(hash, mediaType))\n if (!existsSync(file)) return null\n try {\n const buf = await readFile(file)\n if (sha256(buf) !== hash) return null\n validateMedia(buf, mediaType)\n return buf\n } catch {\n return null\n }\n}\n\nasync function cacheMedia(\n cacheDir: string,\n buf: Buffer,\n mediaType: MediaKind,\n knownHash?: string,\n): Promise<void> {\n const hash = knownHash ?? sha256(buf)\n validateMedia(buf, mediaType)\n const file = path.join(cacheDir, cacheFileName(hash, mediaType))\n if (await readCachedMedia(cacheDir, hash, mediaType)) return\n await mkdir(cacheDir, { recursive: true })\n const tmp = `${file}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`\n await writeFile(tmp, buf)\n try {\n await rename(tmp, file)\n } catch (err) {\n // Two workers can discover the same content concurrently. If the other\n // one won the rename race, the cache is already complete.\n if (!existsSync(file)) throw err\n } finally {\n await rm(tmp, { force: true })\n }\n}\n\nfunction mergeOutputs(previous: LockOutput[], current: LockOutput[]): LockOutput[] {\n const merged = new Map<string, LockOutput>()\n for (const output of [...previous, ...current]) {\n merged.set(output.role ? `role:${output.role}` : `path:${output.path}`, output)\n }\n return [...merged.values()]\n}\n\n/**\n * Applies the manifest's tags to each generated object upstream. Tagging is\n * free and synchronous, and it makes the account itself queryable — the thing\n * that was missing when 350 objects accumulated with no way to tell which 65\n * were the keepers.\n */\nexport async function pushTags(\n provider: Provider,\n specs: ResolvedSpec[],\n lock: Lock,\n opts: { onProgress?: (msg: string) => void } = {},\n): Promise<number> {\n const log = opts.onProgress ?? (() => {})\n const specByKey = new Map(specs.map((s) => [lockKey(s.styleId, s.assetId), s]))\n let tagged = 0\n\n for (const [key, entry] of Object.entries(lock.entries)) {\n const spec = specByKey.get(key)\n if (!spec || entry.provider !== provider.id || !entry.objectId) continue\n // pixflux results are local files with a synthetic id, not account\n // objects — tagging one would 404.\n if (entry.generator === \"pixflux\") continue\n if (!provider.setTags) return tagged // capability absent; nothing to do\n try {\n await provider.setTags(entry.objectId, spec.tags)\n tagged++\n } catch (err) {\n log(` tag failed ${key}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n return tagged\n}\n","const SENSITIVE_QUERY_KEYS = new Set([\n \"access_token\",\n \"apikey\",\n \"api_key\",\n \"auth\",\n \"authorization\",\n \"awsaccesskeyid\",\n \"googleaccessid\",\n \"key\",\n \"sig\",\n])\n\n/** True when a URL contains credentials or a temporary signing secret. */\nexport function isSensitiveSourceUrl(value: string): boolean {\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n return false\n }\n if (parsed.username || parsed.password) return true\n for (const key of parsed.searchParams.keys()) {\n const normalized = key.toLowerCase()\n if (\n SENSITIVE_QUERY_KEYS.has(normalized) ||\n normalized.includes(\"credential\") ||\n normalized.includes(\"signature\") ||\n normalized.includes(\"security-token\") ||\n normalized.includes(\"token\")\n ) return true\n }\n return false\n}\n\n/**\n * Whether a provider source is safe and useful to retain after its bytes have\n * reached the destination. Inline and machine-local sources are transient;\n * credential-bearing URLs must not settle into a committable lockfile.\n */\nexport function shouldPersistSourceUrl(value: string): boolean {\n let parsed: URL\n try {\n parsed = new URL(value)\n } catch {\n // Preserve unknown legacy/provider references. They remain subject to\n // provider download validation and contain no parseable URL credentials.\n return true\n }\n if (parsed.protocol === \"data:\" || parsed.protocol === \"file:\") return false\n return !isSensitiveSourceUrl(value)\n}\n","import { constants, existsSync } from \"node:fs\"\nimport { access, stat } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport type { LoadedManifest } from \"../manifest.ts\"\nimport type { Provider } from \"../provider.ts\"\nimport type { Lock, ResolvedSpec } from \"../types.ts\"\nimport { sha256File } from \"../hash.ts\"\nimport { currentEntryOutputPath, resolveOutputPath } from \"../outputs.ts\"\nimport { cacheFileName, MediaType } from \"../media.ts\"\nimport { buildPlan, resumeActions, summarize } from \"./plan.ts\"\n\nexport type DoctorLevel = \"ok\" | \"warning\" | \"error\"\n\nexport interface DoctorCheck {\n id: string\n level: DoctorLevel\n message: string\n}\n\nexport interface DoctorReport {\n ok: boolean\n checks: DoctorCheck[]\n}\n\nexport interface DoctorOptions {\n /** Provider checks for a mixed manifest. Supersedes the legacy single target. */\n providers?: DoctorProviderTarget[]\n provider?: Provider\n /** Skip provider connectivity while retaining every local check. */\n offline?: boolean\n apiKeyPresent?: boolean\n credentialEnv?: string\n}\n\nexport interface DoctorProviderTarget {\n id: string\n provider?: Provider\n apiKeyPresent: boolean\n credentialEnv?: string\n missingCredentialEnvs?: readonly string[]\n}\n\n/**\n * Checks the whole project without changing it. Loading/resolving the manifest\n * and loading the lock happen before this function, so schema, style-image,\n * filter, and output-collision validation have already passed if it runs.\n */\nexport async function doctor(\n loaded: LoadedManifest,\n specs: ResolvedSpec[],\n lock: Lock,\n lockPath: string,\n opts: DoctorOptions = {},\n): Promise<DoctorReport> {\n const checks: DoctorCheck[] = []\n const add = (id: string, level: DoctorLevel, message: string) => checks.push({ id, level, message })\n\n add(\n \"manifest\",\n \"ok\",\n `${Object.keys(loaded.manifest.styles).length} style(s), ` +\n `${Object.keys(loaded.manifest.assets).length} asset(s), ${specs.length} resolved spec(s)`,\n )\n add(\"lock\", \"ok\", `${Object.keys(lock.entries).length} valid v2 lock entr(ies)`)\n\n const dirs = [...new Set(specs.flatMap((spec) => [\n path.dirname(spec.outFile),\n ...(spec.quality ? [path.dirname(spec.quality.outFile)] : []),\n ]))]\n const unwritable: string[] = []\n for (const dir of dirs) {\n const ancestor = await nearestExistingDirectory(dir)\n try {\n await access(ancestor, constants.W_OK)\n } catch {\n unwritable.push(dir)\n }\n }\n add(\n \"outputs\",\n unwritable.length ? \"error\" : \"ok\",\n unwritable.length\n ? `output path is not writable: ${unwritable.slice(0, 3).join(\", \")}`\n : `${dirs.length} output director${dirs.length === 1 ? \"y is\" : \"ies are\"} writable`,\n )\n\n const outputOwners = new Map<string, string>()\n const duplicateOutputs: string[] = []\n const specByKey = new Map(specs.map((spec) => [`${spec.styleId}/${spec.assetId}`, spec]))\n for (const [key, entry] of Object.entries(lock.entries)) {\n for (let index = 0; index < entry.outputs.length; index++) {\n const output = entry.outputs[index]!\n const spec = specByKey.get(key)\n const absolute = spec\n ? currentEntryOutputPath(entry, spec, index)\n : resolveOutputPath(output.path, path.dirname(lockPath))\n const owner = outputOwners.get(absolute)\n if (owner && owner !== key) duplicateOutputs.push(`${output.path} (${owner}, ${key})`)\n outputOwners.set(absolute, key)\n }\n }\n if (duplicateOutputs.length) {\n // Name the remedy. This almost always means an asset was renamed or moved\n // between styles and the old entry stayed behind still claiming the path,\n // which `prune` clears — reporting the breakage without saying what fixes\n // it left the only route as hand-editing the lockfile.\n add(\n \"lock-outputs\",\n \"error\",\n `lock entries share output paths: ${duplicateOutputs.slice(0, 3).join(\", \")}` +\n `${duplicateOutputs.length > 3 ? `, and ${duplicateOutputs.length - 3} more` : \"\"}` +\n ` — run \\`pixelkiln prune\\` if the manifest no longer declares them`,\n )\n } else {\n add(\"lock-outputs\", \"ok\", `${outputOwners.size} recorded output path(s) are uniquely owned`)\n }\n\n const cacheDir = path.join(path.dirname(lockPath), \".pixelkiln\", \"cache\")\n const stranded: string[] = []\n const invalidState: string[] = []\n const staleMapUrls: string[] = []\n const now = Date.now()\n for (const [key, entry] of Object.entries(lock.entries)) {\n if ((entry.status === \"pending\" || entry.status === \"processing\") && !entry.jobId) {\n invalidState.push(`${key} (${entry.status} without job id)`)\n }\n if (entry.status === \"review\" && !entry.reviewObjectId) {\n invalidState.push(`${key} (review without review object id)`)\n }\n if (entry.status !== \"selected\" && entry.status !== \"download-failed\") continue\n const hasSource = Boolean(entry.sourceUrl || entry.sourceUrls?.length)\n let hasCache = false\n for (const output of entry.outputs) {\n const cached = path.join(\n cacheDir,\n cacheFileName(output.sha256, output.mediaType ?? MediaType.PNG),\n )\n if (existsSync(cached) && (await sha256File(cached)) === output.sha256) {\n hasCache = true\n break\n }\n }\n if (!hasSource && !hasCache) stranded.push(key)\n if (\n entry.generator === \"map\" &&\n entry.submittedAt &&\n now - Date.parse(entry.submittedAt) > 8 * 60 * 60 * 1000\n ) {\n staleMapUrls.push(key)\n }\n }\n add(\n \"recovery\",\n stranded.length || invalidState.length ? \"error\" : staleMapUrls.length ? \"warning\" : \"ok\",\n invalidState.length\n ? `invalid resumable state: ${invalidState.slice(0, 5).join(\", \")}`\n : stranded.length\n ? `${stranded.length} unfinished entr(ies) have neither source URLs nor cached bytes: ${stranded.slice(0, 5).join(\", \")}`\n : staleMapUrls.length\n ? `${staleMapUrls.length} unfinished map entr(ies) are older than the provider's 8-hour job window`\n : \"no unfinished downloads are stranded without a source or cached bytes\",\n )\n\n const plan = await buildPlan(specs, lock)\n const counts = summarize(plan)\n const unsettled = plan.items.filter((i) => i.state !== \"ok\").length\n add(\n \"plan\",\n unsettled ? \"warning\" : \"ok\",\n unsettled\n ? `${unsettled} spec(s) are not current: ` +\n Object.entries(counts)\n .filter(([, n]) => n > 0)\n .map(([state, n]) => `${n} ${state}`)\n .join(\", \")\n : \"every resolved spec is current\",\n )\n\n const resumable = resumeActions(specs, lock)\n add(\n \"next-actions\",\n resumable.length ? \"warning\" : \"ok\",\n resumable.length\n ? \"resume paid work without regenerating: \" +\n resumable\n .map((action) =>\n `pixelkiln ${action.command} (${action.keys.length} asset${action.keys.length === 1 ? \"\" : \"s\"})`\n )\n .join(\", \")\n : \"no generation stage is waiting for poll, pick, or fetch\",\n )\n\n const quality = plan.items.flatMap((item) => item.quality ? [item.quality] : [])\n const qualityPending = quality.filter((item) => item.state !== \"approved\")\n if (quality.length) {\n add(\n \"quality\",\n qualityPending.length ? \"warning\" : \"ok\",\n qualityPending.length\n ? `${qualityPending.length}/${quality.length} configured quality output(s) are not approved: ` +\n qualityPending.slice(0, 3).map((item) => `${item.key} ${item.state}`).join(\", \")\n : `all ${quality.length} configured quality output(s) are current and approved`,\n )\n }\n\n const legacyTarget = !opts.providers\n const targets: DoctorProviderTarget[] = opts.providers ?? [{\n id: opts.provider?.id ?? \"provider\",\n provider: opts.provider,\n apiKeyPresent: opts.apiKeyPresent ?? Boolean(opts.provider),\n credentialEnv: opts.credentialEnv,\n }]\n for (const target of targets) {\n const checkId = targets.length === 1 ? \"provider\" : `provider:${target.id}`\n if (opts.offline) {\n add(checkId, \"warning\", `${target.id} connectivity skipped (--dry-run)`)\n } else if (!target.provider) {\n add(\n checkId,\n \"error\",\n !target.apiKeyPresent\n ? `${target.missingCredentialEnvs?.length\n ? target.missingCredentialEnvs.join(\", \")\n : target.credentialEnv ?? (legacyTarget ? \"PIXELLAB_API_KEY\" : `${target.id} credential`)} ` +\n `${target.missingCredentialEnvs && target.missingCredentialEnvs.length > 1 ? \"are\" : \"is\"} not configured`\n : `${target.id} is not configured`,\n )\n } else if (!target.provider.balance && !target.provider.checkConnection) {\n add(checkId, \"ok\", `${target.id} configured; connectivity check unavailable`)\n } else if (!target.provider.balance) {\n try {\n await target.provider.checkConnection!()\n add(checkId, \"ok\", `${target.id} reachable; balance reporting unavailable`)\n } catch (err) {\n add(\n checkId,\n \"error\",\n `${legacyTarget ? \"provider\" : target.id} connectivity failed: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n } else {\n try {\n const balance = await target.provider.balance()\n add(\n checkId,\n \"ok\",\n `${target.id} reachable; ${balance.remaining} ${balance.unit} remaining`,\n )\n } catch (err) {\n add(\n checkId,\n \"error\",\n `${legacyTarget ? \"provider\" : target.id} connectivity failed: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n }\n\n return { ok: !checks.some((c) => c.level === \"error\"), checks }\n}\n\nasync function nearestExistingDirectory(start: string): Promise<string> {\n let current = start\n for (;;) {\n try {\n if ((await stat(current)).isDirectory()) return current\n } catch {\n // Walk upward until a parent exists; creating descendants needs write\n // permission on that nearest existing ancestor.\n }\n const parent = path.dirname(current)\n if (parent === current) return current\n current = parent\n }\n}\n","import { existsSync } from \"node:fs\"\nimport { readFile, writeFile } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { requireList, validateCostEstimate, type Provider, type RemoteAsset } from \"../provider.ts\"\nimport { sha256 } from \"../hash.ts\"\nimport { loadCache, saveCache, pruneCache, cachePathFor, type HashCache } from \"../cache.ts\"\nimport { saveLock, upsert } from \"../lock.ts\"\nimport { portableOutputPath } from \"../outputs.ts\"\nimport { decodePng } from \"../png.ts\"\nimport { shouldPersistSourceUrl } from \"../source-url.ts\"\nimport { lockKey, type Lock, type ResolvedSpec } from \"../types.ts\"\n\nexport interface AdoptResult {\n scanned: number\n matched: number\n unmatchedLocal: string[]\n /** Objects on the account that correspond to no local file — safe to delete. */\n unmatchedRemote: RemoteAsset[]\n ambiguous: string[]\n}\n\n/**\n * Reconciles an account full of previously generated objects against the files\n * already committed in the repo, and writes the mapping into the lockfile.\n *\n * Matching is by exact SHA-256 of the image bytes. That was verified to hold:\n * a file downloaded from PixelLab storage is byte-identical to the copy sitting\n * in the repo, so a hash match is proof of provenance rather than a guess. No\n * fuzzy prompt matching is involved and nothing is regenerated.\n */\nexport async function adopt(\n provider: Provider,\n specs: ResolvedSpec[],\n lock: Lock,\n lockPath: string,\n opts: { onProgress?: (msg: string) => void; concurrency?: number; noCache?: boolean } = {},\n): Promise<AdoptResult> {\n const log = opts.onProgress ?? (() => {})\n const concurrency = opts.concurrency ?? 8\n // Generated objects are immutable, so a hash computed once stays valid.\n const cachePath = cachePathFor(lockPath)\n const cache: HashCache = opts.noCache ? { version: 1, hashes: {} } : await loadCache(cachePath)\n let cacheHits = 0\n\n // 1. Hash every local file the manifest expects to exist.\n const localByHash = new Map<string, ResolvedSpec[]>()\n const unmatchedLocal: string[] = []\n for (const spec of specs) {\n if (!existsSync(spec.outFile)) {\n unmatchedLocal.push(`${spec.styleId}/${spec.assetId} (no file at ${spec.outFile})`)\n continue\n }\n const bytes = await readFile(spec.outFile)\n try {\n decodePng(bytes)\n } catch (err) {\n unmatchedLocal.push(\n `${spec.styleId}/${spec.assetId} (invalid PNG: ` +\n `${err instanceof Error ? err.message : String(err)})`,\n )\n continue\n }\n const hash = sha256(bytes)\n const bucket = localByHash.get(hash) ?? []\n bucket.push(spec)\n localByHash.set(hash, bucket)\n }\n log(` hashed ${localByHash.size} distinct local image(s)`)\n\n // 2. Walk the account and hash every remote object's image.\n const remote: RemoteAsset[] = []\n for await (const obj of requireList(provider)()) remote.push(obj)\n log(` found ${remote.length} object(s) on the account`)\n\n const matchedRemote = new Set<string>()\n const ambiguous: string[] = []\n let matched = 0\n let cursor = 0\n\n async function worker() {\n for (;;) {\n const obj = remote[cursor++]\n if (!obj) return\n const url = obj.previewUrl\n if (!url || obj.status !== \"completed\") continue\n\n let hash: string | undefined = cache.hashes[obj.id]\n if (hash) {\n cacheHits++\n } else {\n try {\n const bytes = await provider.download(url)\n decodePng(bytes)\n hash = sha256(bytes)\n } catch {\n continue\n }\n cache.hashes[obj.id] = hash\n }\n\n const hits = localByHash.get(hash)\n if (!hits?.length) continue\n\n matchedRemote.add(obj.id)\n for (const spec of hits) {\n const key = lockKey(spec.styleId, spec.assetId)\n const existing = lock.entries[key]\n if (existing?.objectId && existing.objectId !== obj.id) {\n // Two account objects produced identical bytes. Harmless, but the\n // first wins so re-running adopt stays deterministic.\n ambiguous.push(`${key}: already mapped to ${existing.objectId}, also matches ${obj.id}`)\n continue\n }\n const durableSource = shouldPersistSourceUrl(url) ? url : null\n upsert(lock, key, {\n styleId: spec.styleId,\n assetId: spec.assetId,\n // Deliberately the CURRENT spec hash: adoption declares \"the file on\n // disk satisfies today's spec\", so plan reports it as ok, not stale.\n specHash: spec.specHash,\n generator: spec.generator,\n prompt: obj.prompt || spec.prompt,\n width: obj.width,\n height: obj.height,\n jobId: obj.id,\n objectId: obj.id,\n reviewObjectId: null,\n candidateIndex: null,\n status: \"downloaded\",\n error: null,\n sourceUrl: durableSource,\n sourceUrls: durableSource ? [{ url: durableSource }] : [],\n outputs: [{ path: portableOutputPath(spec.outFile, spec.root), sha256: hash }],\n submittedAt: obj.createdAt,\n downloadedAt: new Date().toISOString(),\n cost: 0, // already paid for, in a previous billing period\n costUnit: validateCostEstimate(provider.id, provider.estimate(spec)).unit,\n provider: provider.id,\n })\n matched++\n log(` adopted ${key} ← ${obj.id}`)\n }\n }\n }\n\n await Promise.all(Array.from({ length: Math.min(concurrency, remote.length || 1) }, worker))\n await saveLock(lockPath, lock)\n\n if (!opts.noCache) {\n pruneCache(cache, new Set(remote.map((o) => o.id)))\n await saveCache(cachePath, cache)\n if (cacheHits) log(` reused ${cacheHits} cached hash(es); downloaded ${remote.length - cacheHits}`)\n }\n\n return {\n scanned: remote.length,\n matched,\n unmatchedLocal,\n unmatchedRemote: remote.filter((o) => !matchedRemote.has(o.id)),\n ambiguous,\n }\n}\n\n/** Applies manifest tags to every adopted object so the account becomes filterable. */\nexport async function tagAdopted(\n provider: Provider,\n specs: ResolvedSpec[],\n lock: Lock,\n opts: { onProgress?: (msg: string) => void } = {},\n): Promise<number> {\n const log = opts.onProgress ?? (() => {})\n const specByKey = new Map(specs.map((s) => [lockKey(s.styleId, s.assetId), s]))\n let count = 0\n for (const [key, entry] of Object.entries(lock.entries)) {\n const spec = specByKey.get(key)\n if (!spec || !entry.objectId) continue\n if (!provider.setTags) return count // capability absent\n try {\n await provider.setTags(entry.objectId, spec.tags)\n count++\n } catch (err) {\n log(` tag failed ${key}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n return count\n}\n\n/**\n * Backfills empty manifest prompts from the prompts recorded on adopted objects.\n *\n * For a project onboarded with `init`, this is how the manifest becomes real:\n * the prompts that actually produced the shipped art are recovered from the\n * account rather than reconstructed by guesswork. Only empty prompts are\n * touched, so hand-authored text is never overwritten.\n */\nexport async function writePromptsBack(\n manifestPath: string,\n lock: Lock,\n opts: {\n onProgress?: (msg: string) => void\n /** Restrict recovered prompts to lock entries from one provider. */\n provider?: string\n /** Restrict manifest writes and missing reports to these asset ids. */\n assetIds?: Iterable<string>\n } = {},\n): Promise<{ filled: number; stillEmpty: string[] }> {\n const log = opts.onProgress ?? (() => {})\n const selectedAssets = opts.assetIds ? new Set(opts.assetIds) : null\n const raw = JSON.parse(await readFile(manifestPath, \"utf8\")) as {\n assets: Record<string, { prompt?: string }>\n }\n\n // An asset can be adopted under several styles; prefer the longest recovered\n // prompt, which is the most complete description of what was generated.\n const best = new Map<string, string>()\n for (const entry of Object.values(lock.entries)) {\n if (opts.provider && entry.provider !== opts.provider) continue\n if (selectedAssets && !selectedAssets.has(entry.assetId)) continue\n if (!entry.objectId || !entry.prompt) continue\n const current = best.get(entry.assetId)\n if (!current || entry.prompt.length > current.length) best.set(entry.assetId, entry.prompt)\n }\n\n let filled = 0\n const stillEmpty: string[] = []\n for (const [id, asset] of Object.entries(raw.assets)) {\n if (selectedAssets && !selectedAssets.has(id)) continue\n if (asset.prompt && asset.prompt.trim()) continue\n const recovered = best.get(id)\n if (recovered) {\n asset.prompt = recovered\n filled++\n } else {\n stillEmpty.push(id)\n }\n }\n\n await writeFile(manifestPath, JSON.stringify(raw, null, 2) + \"\\n\")\n log(` filled ${filled} prompt(s) from adopted objects`)\n return { filled, stillEmpty }\n}\n\nexport function formatUnmatchedRemote(objects: RemoteAsset[], limit = 15): string {\n const lines = objects\n .slice(0, limit)\n .map((o) => ` ${o.id} ${o.createdAt.slice(0, 10)} ${(o.prompt || \"\").slice(0, 60)}`)\n if (objects.length > limit) lines.push(` … and ${objects.length - limit} more`)\n return lines.join(\"\\n\")\n}\n\nexport function relativeToCwd(p: string): string {\n return path.relative(process.cwd(), p) || p\n}\n","import { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport pathModule from \"node:path\"\nimport { z } from \"zod\"\n\nexport const HashCacheSchema = z.object({\n version: z.literal(1),\n /** objectId → sha256 of that object's image bytes. */\n hashes: z.record(z.string()),\n})\n\nexport type HashCache = z.infer<typeof HashCacheSchema>\nconst SHA256_HEX = /^[a-f0-9]{64}$/\n\nexport function isSha256Hash(value: string): boolean {\n return SHA256_HEX.test(value)\n}\n\n/** Strict parser for diagnostics; ordinary cache loading remains self-healing. */\nexport function parseCache(value: unknown): HashCache {\n return HashCacheSchema.parse(value)\n}\n\n/**\n * Remembers the hash of every remote object already downloaded.\n *\n * `adopt` and `salvage` work by hashing image bytes, which means downloading\n * every object on the account on every run — measured at 363 downloads and\n * ~4.5s for one project, and it grows with the account rather than with the\n * work. Generated objects are immutable, so a hash only ever needs computing\n * once.\n *\n * Purely derived state: deleting the file costs one slow run and nothing else.\n * It belongs in .gitignore.\n */\nexport async function loadCache(path: string): Promise<HashCache> {\n if (!existsSync(path)) return { version: 1, hashes: {} }\n try {\n const parsed = HashCacheSchema.safeParse(JSON.parse(await readFile(path, \"utf8\")))\n if (!parsed.success) return { version: 1, hashes: {} }\n // Never trust malformed derived data during adoption. Dropping one cache\n // entry costs one download; trusting it can hide a real provenance match.\n return {\n version: 1,\n hashes: Object.fromEntries(\n Object.entries(parsed.data.hashes).filter(([, hash]) => isSha256Hash(hash)),\n ),\n }\n } catch {\n // A corrupt cache is not worth failing a run over — rebuild it.\n return { version: 1, hashes: {} }\n }\n}\n\nexport async function saveCache(path: string, cache: HashCache): Promise<void> {\n const sorted: Record<string, string> = {}\n for (const key of Object.keys(cache.hashes).sort()) {\n const hash = cache.hashes[key]!\n if (!isSha256Hash(hash)) throw new Error(`Refusing to cache invalid SHA-256 for ${key}`)\n sorted[key] = hash\n }\n await mkdir(pathModule.dirname(pathModule.resolve(path)), { recursive: true })\n const tmp = `${path}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`\n try {\n await writeFile(tmp, JSON.stringify({ version: 1, hashes: sorted }, null, 2) + \"\\n\")\n await rename(tmp, path)\n } finally {\n await rm(tmp, { force: true })\n }\n}\n\n/** Drop entries for objects that no longer exist, so the file cannot grow forever. */\nexport function pruneCache(cache: HashCache, liveIds: Set<string>): number {\n let removed = 0\n for (const id of Object.keys(cache.hashes)) {\n if (!liveIds.has(id)) {\n delete cache.hashes[id]\n removed++\n }\n }\n return removed\n}\n\n/**\n * A lockfile named exactly `*.lock.json` gets the conventional\n * `*.cache.json` sibling. Anything else — a custom `--lock` name, which\n * projects in this monorepo already use for variant lockfiles — falls back\n * to appending `.cache.json` to the whole path instead of returning it\n * unchanged. Returning the input unchanged here used to mean the cache,\n * which is a completely different schema, got written straight over the\n * real lockfile on the very first `adopt`.\n */\nexport function cachePathFor(lockPath: string): string {\n if (lockPath.endsWith(\".lock.json\")) return lockPath.replace(/\\.lock\\.json$/, \".cache.json\")\n return `${lockPath}.cache.json`\n}\n","export interface SheetGroup {\n key: string\n assetId: string\n styleId: string\n prompt: string\n reviewObjectId: string\n frameUrls: string[]\n width: number\n height: number\n mode?: \"candidates\" | \"frame-set\"\n frameLabels?: string[]\n fps?: number\n revision?: {\n mode: \"image-to-image\" | \"inpaint\" | \"outpaint\"\n sourceAssetId: string\n sourceUrl: string\n width: number\n height: number\n }\n}\n\nconst escapeHtml = (s: string) =>\n s.replace(/[&<>\"']/g, (c) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" })[c]!)\n\n/**\n * A contact sheet for choosing among generated candidates.\n *\n * This is the only step that needs human judgement, so it is optimised for one\n * thing: deciding fast. Small candidates render at an exact integer zoom with\n * a transparency checkerboard and a true-size swatch. Large candidates are\n * fitted without changing their aspect ratio, so a wide browser cannot turn a\n * review into an oversized or stretched image wall. Keyboard-first, one row\n * per asset, and the page posts back and closes itself.\n */\nexport function renderSheet(groups: SheetGroup[]): string {\n // Prompts are author-controlled but arbitrary text, and they reach the page\n // both as JSON inside a <script> and via innerHTML. Escape for both: HTML\n // entities for the markup path, and `<\\/` for the script-tag path so a\n // prompt containing \"</script>\" cannot break out.\n const safe = groups.map((g) => ({\n ...g,\n styleId: escapeHtml(g.styleId),\n assetId: escapeHtml(g.assetId),\n prompt: escapeHtml(g.prompt),\n ...(g.revision\n ? {\n revision: {\n ...g.revision,\n sourceAssetId: escapeHtml(g.revision.sourceAssetId),\n },\n }\n : {}),\n }))\n const data = JSON.stringify(safe).replace(/<\\//g, \"<\\\\/\")\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>pixelkiln — pick candidates</title>\n<style>\n :root {\n --bg: #17150f; --panel: #201d17; --panel-deep: #100f0c;\n --line: rgba(243,234,214,.16); --line-strong: rgba(243,234,214,.3);\n --text: #f3ead6; --dim: #9b9384; --accent: #ff6b35;\n --accent-soft: #ff9c5f; --ok: #b9f27c; --warn: #ff9c5f;\n --content: 1440px; --preview: 560px;\n }\n * { box-sizing: border-box; }\n body { margin:0; background:var(--bg); color:var(--text);\n font:14px/1.5 ui-sans-serif,-apple-system,\"SF Pro Text\",Inter,system-ui,sans-serif; }\n header { position:sticky; top:0; z-index:10; background:var(--panel);\n border-bottom:1px solid var(--line-strong); }\n .bar { width:min(100%,var(--content)); margin:0 auto; padding:15px 22px;\n display:flex; align-items:center; gap:16px; flex-wrap:wrap; }\n h1 { font:700 14px/1 ui-monospace,SFMono-Regular,Menlo,monospace;\n margin:0; letter-spacing:-.02em; }\n h1::before { content:'◆'; color:var(--accent); margin-right:9px; font-size:11px; }\n .count { color:var(--dim); font-variant-numeric:tabular-nums; }\n button { font:inherit; font-weight:600; border-radius:0; padding:9px 16px;\n border:1px solid var(--line); background:transparent; color:var(--text); cursor:pointer; }\n button.primary { background:var(--accent); border-color:var(--accent); color:var(--bg); }\n button:disabled { opacity:.45; cursor:not-allowed; }\n main, footer { width:min(100%,var(--content)); margin-inline:auto; }\n main { border-inline:1px solid var(--line); }\n .group { border-bottom:1px solid var(--line); padding:22px; overflow:hidden; }\n .group.done { background:rgba(185,242,124,.035); }\n .ghead { display:flex; align-items:baseline; gap:12px; margin-bottom:16px; flex-wrap:wrap; }\n .style { font-size:10.5px; font-weight:650; text-transform:uppercase; letter-spacing:.03em;\n color:var(--accent-soft); border:1px solid var(--accent); border-radius:0; padding:2px 6px; }\n .aid { font-weight:650; font-family:ui-monospace,SFMono-Regular,Menlo,monospace; }\n .prompt { flex:1; min-width:280px; color:var(--dim); font-size:12.5px; max-width:80ch; }\n .review { display:grid; grid-template-columns:minmax(180px,280px) minmax(0,1fr); gap:16px;\n align-items:start; }\n .review.no-context { display:block; }\n .context { border:1px solid var(--line); padding:8px; background:var(--panel-deep);\n min-width:0; }\n .context-label { display:flex; justify-content:space-between; gap:8px; margin-bottom:7px;\n color:var(--dim); font-size:10.5px; font-variant-numeric:tabular-nums; }\n .context img { display:block; width:100%; height:auto; max-height:420px; object-fit:contain;\n image-rendering:pixelated;\n background-image:linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%),\n linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%);\n background-size:12px 12px; background-position:0 0,6px 6px; }\n .frames { display:flex; flex-wrap:wrap; gap:10px; max-width:100%; overflow-x:auto; }\n .loop { display:flex; align-items:flex-start; gap:12px; margin-bottom:12px; }\n .loop img { image-rendering:pixelated; border:2px solid var(--accent); padding:7px;\n background:var(--panel-deep); max-width:min(var(--preview),calc(100vw - 62px)); height:auto; }\n .loop-copy { color:var(--dim); font-size:11px; max-width:32ch; display:flex;\n flex-direction:column; gap:8px; }\n .loop-copy p { margin:0; }\n .loop-copy button { align-self:flex-start; padding:5px 9px; font-size:10.5px; }\n .cand { border:2px solid var(--line-strong); border-radius:0; padding:7px; background:var(--panel-deep);\n cursor:pointer; display:flex; flex:0 0 auto; flex-direction:column; align-items:center; gap:5px;\n position:relative; max-width:100%; }\n .cand:hover { border-color:var(--dim); }\n .cand.active { border-color:var(--dim); box-shadow:0 0 0 2px color-mix(in srgb, var(--dim) 20%, transparent); }\n .cand.sel { border-color:var(--ok); box-shadow:0 0 0 3px color-mix(in srgb, var(--ok) 22%, transparent); }\n .cand.set-frame { cursor:pointer; }\n .cand img { image-rendering:pixelated; display:block;\n background-image:\n linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%),\n linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%);\n background-size:12px 12px; background-position:0 0,6px 6px; border-radius:0; }\n .cand img.preview { max-width:min(var(--preview),calc(100vw - 62px)); height:auto; }\n .idx { font-size:10.5px; color:var(--dim); font-variant-numeric:tabular-nums; }\n .actual { position:absolute; right:-3px; bottom:-3px; image-rendering:pixelated;\n border:1px solid var(--line); border-radius:0; background:var(--panel); }\n .skip { align-self:center; color:var(--dim); font-size:12px; }\n footer { padding:26px 20px 60px; color:var(--dim); }\n kbd { border:1px solid var(--line); border-bottom-width:2px; border-radius:0;\n padding:1px 5px; font-size:11px; font-family:ui-monospace,Menlo,monospace; }\n #status { color:var(--warn); }\n @media (max-width:640px) {\n .bar, .group { padding-inline:14px; }\n .prompt { min-width:100%; }\n .cand img.preview { max-width:calc(100vw - 50px); }\n }\n @media (max-width:900px) {\n .review { grid-template-columns:1fr; }\n .context { max-width:280px; }\n }\n</style>\n</head>\n<body>\n<header>\n <div class=\"bar\">\n <h1>pixelkiln</h1>\n <span class=\"count\"><span id=\"picked\">0</span> of <span id=\"total\">0</span> chosen</span>\n <span id=\"status\"></span>\n <span style=\"flex:1\"></span>\n <button id=\"submit\" class=\"primary\" disabled>Apply selections</button>\n </div>\n</header>\n<main id=\"root\"></main>\n<footer>\n Click a candidate to choose it, or any ordered frame to accept its whole set;\n click again to undo. In the focused row,\n <kbd>←</kbd>/<kbd>→</kbd> browses every candidate and <kbd>Enter</kbd> chooses;\n <kbd>1</kbd>–<kbd>9</kbd> picks directly, <kbd>0</kbd> skips, and\n <kbd>↑</kbd>/<kbd>↓</kbd> changes rows. Unchosen rows stay in review — nothing is\n discarded by closing this page.\n</footer>\n<script>\nconst GROUPS = ${data};\nconst picks = new Map();\nconst root = document.getElementById('root');\ndocument.getElementById('total').textContent = GROUPS.length;\n\nGROUPS.forEach((g, gi) => {\n const el = document.createElement('section');\n el.className = 'group';\n el.tabIndex = 0;\n el.dataset.gi = String(gi);\n const largestSide = Math.max(g.width, g.height);\n const preferredScale = largestSide <= 48 ? 4 : largestSide <= 96 ? 3 : 2;\n const scale = Math.min(preferredScale, 560 / largestSide);\n const displayScale = scale >= 1 ? Math.floor(scale) : scale;\n const displayWidth = Math.max(1, Math.round(g.width * displayScale));\n const displayHeight = Math.max(1, Math.round(g.height * displayScale));\n const scaleLabel = displayScale >= 1 ? displayScale + '×' : 'fit';\n el.innerHTML =\n '<div class=\"ghead\"><span class=\"style\">' + g.styleId + '</span>' +\n '<span class=\"aid\">' + g.assetId + '</span>' +\n '<span class=\"prompt\">' + g.prompt + '</span></div>' +\n '<div class=\"review' + (g.revision ? '' : ' no-context') + '\">' +\n '<div class=\"frames\"></div></div>';\n const review = el.querySelector('.review');\n const frames = el.querySelector('.frames');\n if (g.revision) {\n const context = document.createElement('aside');\n context.className = 'context';\n const label = document.createElement('div');\n label.className = 'context-label';\n const identity = document.createElement('span');\n identity.textContent = g.revision.mode.toUpperCase() + ' · SOURCE ' + g.revision.sourceAssetId;\n const dimensions = document.createElement('span');\n dimensions.textContent = g.revision.width + '×' + g.revision.height;\n label.append(identity, dimensions);\n const source = document.createElement('img');\n source.src = g.revision.sourceUrl;\n source.alt = 'Revision source ' + g.revision.sourceAssetId;\n context.append(label, source);\n review.insertBefore(context, frames);\n }\n if (g.mode === 'frame-set') {\n const loop = document.createElement('div');\n loop.className = 'loop';\n const preview = document.createElement('img');\n preview.src = g.frameUrls[0];\n preview.width = displayWidth;\n preview.height = displayHeight;\n preview.alt = 'Animated frame-set preview';\n const copy = document.createElement('div');\n copy.className = 'loop-copy';\n const copyText = document.createElement('p');\n copyText.textContent = g.frameUrls.length + ' ordered frames · ' + (g.fps || 12) +\n ' fps. Accepting keeps every frame; one bad frame means leave the set unchosen.';\n const playback = document.createElement('button');\n playback.type = 'button';\n let userPaused = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n let loopVisible = true;\n let pageVisible = !document.hidden;\n let loopTimer = null;\n let loopIndex = 0;\n const stopLoop = () => {\n if (loopTimer !== null) window.clearInterval(loopTimer);\n loopTimer = null;\n };\n const syncLoop = () => {\n stopLoop();\n playback.textContent = userPaused ? 'Play preview' : 'Pause preview';\n playback.setAttribute('aria-pressed', String(userPaused));\n if (!userPaused && loopVisible && pageVisible) {\n loopTimer = window.setInterval(() => {\n loopIndex = (loopIndex + 1) % g.frameUrls.length;\n preview.src = g.frameUrls[loopIndex];\n }, Math.max(16, Math.round(1000 / (g.fps || 12))));\n }\n };\n playback.addEventListener('click', () => {\n userPaused = !userPaused;\n syncLoop();\n });\n copy.append(copyText, playback);\n loop.append(preview, copy);\n review.insertBefore(loop, frames);\n document.addEventListener('visibilitychange', () => {\n pageVisible = !document.hidden;\n syncLoop();\n });\n syncLoop();\n if ('IntersectionObserver' in window) {\n new IntersectionObserver((entries) => {\n loopVisible = entries[0]?.isIntersecting ?? false;\n syncLoop();\n }).observe(loop);\n }\n }\n g.frameUrls.forEach((url, i) => {\n const c = document.createElement('button');\n c.type = 'button';\n c.className = 'cand' + (g.mode === 'frame-set' ? ' set-frame' : '');\n c.tabIndex = -1;\n c.setAttribute('aria-label', g.mode === 'frame-set'\n ? 'Accept ordered frame set from frame ' + (i + 1)\n : 'Choose candidate ' + (i + 1) + ' of ' + g.frameUrls.length);\n\n const preview = document.createElement('img');\n preview.className = 'preview';\n preview.src = url;\n preview.width = displayWidth;\n preview.height = displayHeight;\n preview.loading = 'lazy';\n const index = document.createElement('span');\n index.className = 'idx';\n index.textContent = (g.frameLabels?.[i] || String(i + 1)) + ' · ' +\n g.width + '×' + g.height + ' · ' + scaleLabel;\n c.append(preview, index);\n if (displayScale > 1 && largestSide <= 96) {\n const actual = document.createElement('img');\n actual.className = 'actual';\n actual.src = url;\n actual.width = g.width;\n actual.height = g.height;\n actual.loading = 'lazy';\n actual.setAttribute('aria-label', 'Actual size');\n c.append(actual);\n }\n\n c.onclick = () => {\n activate(i, frames);\n choose(gi, i, c, frames, el);\n // Keep the row as the keyboard target. Otherwise a clicked <button>\n // receives focus and Enter would invoke both its native click and the\n // row shortcut, toggling the same choice twice.\n el.focus();\n };\n c.onmouseenter = () => activate(i, frames);\n frames.appendChild(c);\n });\n frames.dataset.active = '0';\n frames.querySelector('.cand')?.classList.add('active');\n root.appendChild(el);\n});\n\nfunction activate(i, frames) {\n const candidates = [...frames.querySelectorAll('.cand')];\n if (!candidates.length) return null;\n const next = ((i % candidates.length) + candidates.length) % candidates.length;\n candidates.forEach(n => n.classList.remove('active'));\n candidates[next].classList.add('active');\n frames.dataset.active = String(next);\n candidates[next].scrollIntoView({ block: 'nearest', inline: 'nearest' });\n return candidates[next];\n}\n\nfunction choose(gi, i, node, frames, groupEl) {\n if (GROUPS[gi].mode === 'frame-set') {\n const selected = picks.has(gi);\n frames.querySelectorAll('.cand').forEach(n => n.classList.toggle('sel', !selected));\n if (selected) { picks.delete(gi); groupEl.classList.remove('done'); }\n else { picks.set(gi, 0); groupEl.classList.add('done'); }\n refresh();\n return;\n }\n const current = picks.get(gi);\n frames.querySelectorAll('.cand').forEach(n => n.classList.remove('sel'));\n if (current === i) { picks.delete(gi); groupEl.classList.remove('done'); }\n else { picks.set(gi, i); node.classList.add('sel'); groupEl.classList.add('done'); }\n refresh();\n}\nfunction refresh() {\n document.getElementById('picked').textContent = picks.size;\n document.getElementById('submit').disabled = picks.size === 0;\n}\ndocument.addEventListener('keydown', e => {\n const g = document.activeElement?.closest?.('.group');\n if (!g) return;\n const gi = Number(g.dataset.gi);\n const frames = g.querySelector('.frames');\n const candidates = [...frames.querySelectorAll('.cand')];\n const active = Number(frames.dataset.active || 0);\n let advance = false;\n\n if (e.key === 'ArrowLeft') activate(active - 1, frames);\n else if (e.key === 'ArrowRight') activate(active + 1, frames);\n else if (e.key === 'Home') activate(0, frames);\n else if (e.key === 'End') activate(candidates.length - 1, frames);\n else if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {\n const sibling = e.key === 'ArrowUp' ? g.previousElementSibling : g.nextElementSibling;\n if (sibling) { sibling.focus(); sibling.scrollIntoView({ block: 'center', behavior: 'smooth' }); }\n } else if (e.key === 'Enter' || e.key === ' ') {\n const node = candidates[active];\n if (!node) return;\n choose(gi, active, node, frames, g);\n advance = true;\n } else if (e.key === '0') {\n picks.delete(gi); g.classList.remove('done');\n frames.querySelectorAll('.cand').forEach(n => n.classList.remove('sel'));\n refresh();\n advance = true;\n } else if (/^[1-9]$/.test(e.key)) {\n const i = Number(e.key) - 1;\n const node = candidates[i];\n if (!node) return;\n activate(i, frames);\n choose(gi, i, node, frames, g);\n advance = true;\n } else {\n return;\n }\n if (advance) {\n const next = g.nextElementSibling;\n if (next) { next.focus(); next.scrollIntoView({ block: 'center', behavior: 'smooth' }); }\n }\n e.preventDefault();\n});\n\ndocument.getElementById('submit').onclick = async () => {\n const btn = document.getElementById('submit');\n btn.disabled = true;\n const status = document.getElementById('status');\n status.textContent = 'applying…';\n const selections = [...picks.entries()].map(([gi, index]) => ({ key: GROUPS[gi].key, index }));\n try {\n const res = await fetch('/apply', {\n method: 'POST', headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ selections }),\n });\n if (!res.ok) throw new Error(await res.text());\n status.textContent = 'done — you can close this tab';\n document.body.style.opacity = '.6';\n } catch (err) {\n status.textContent = 'failed: ' + err.message;\n btn.disabled = false;\n }\n};\n</script>\n</body>\n</html>`\n}\n","import { createServer } from \"node:http\"\nimport { spawn } from \"node:child_process\"\nimport { readFile } from \"node:fs/promises\"\n\n/**\n * The HTTP plumbing shared by every local review page (`pick`, `salvage`):\n * serve one static page at `/`, accept one POST of decisions, hand the parsed\n * body to the caller, and resolve once that caller's handler succeeds.\n *\n * This exists because `pick` and `salvage` each hand-rolled the identical\n * server — same GET/POST routing, same ephemeral-port dance, same `open`\n * spawn, same error handling — and a bug fixed in one silently stayed a bug\n * in the other (as happened here: `salvage`'s manifest-write bug had no\n * equivalent in `pick` only because `pick` never merges a whole manifest back\n * in). A third review page now gets this for free instead of a third copy to\n * keep in sync.\n *\n * Deliberately NOT a full framework: one page, one apply endpoint, one round\n * trip. Anything needing more should not reach for this.\n */\nexport interface ReviewServerOptions<TResult> {\n /** The full HTML document served at GET /. */\n html: string\n /** Parses the POSTed decisions and performs them. Only closes the server\n * on success — a thrown error leaves the page free to retry. */\n handleApply: (body: unknown) => Promise<TResult>\n /** Logged once the server is listening, given its localhost URL. */\n onReady: (url: string) => void\n port?: number\n /** Open the URL in the system browser once listening. Default true. */\n open?: boolean\n onProgress?: (msg: string) => void\n /** Exact local media routes exposed only for the lifetime of this review. */\n assets?: ReadonlyMap<string, { path: string; contentType: string }>\n}\n\nexport function serveReviewPage<TResult>(opts: ReviewServerOptions<TResult>): Promise<TResult> {\n const log = opts.onProgress ?? (() => {})\n\n return new Promise<TResult>((resolve, reject) => {\n const server = createServer(async (req, res) => {\n if (req.method === \"GET\" && req.url && opts.assets?.has(req.url)) {\n try {\n const asset = opts.assets.get(req.url)!\n const bytes = await readFile(asset.path)\n res.writeHead(200, {\n \"Content-Type\": asset.contentType,\n \"Cache-Control\": \"no-store\",\n \"X-Content-Type-Options\": \"nosniff\",\n })\n res.end(bytes)\n } catch {\n res.writeHead(404, { \"Content-Type\": \"text/plain\" })\n res.end(\"review asset is unavailable\")\n }\n return\n }\n\n if (req.method === \"GET\" && (req.url === \"/\" || req.url?.startsWith(\"/?\"))) {\n res.writeHead(200, { \"Content-Type\": \"text/html; charset=utf-8\" })\n res.end(opts.html)\n return\n }\n\n if (req.method === \"POST\" && req.url === \"/apply\") {\n const expectedOrigin = req.headers.host ? `http://${req.headers.host}` : null\n if (req.headers.origin && req.headers.origin !== expectedOrigin) {\n res.writeHead(403, { \"Content-Type\": \"text/plain\" })\n res.end(\"cross-origin review submissions are not allowed\")\n return\n }\n if (!req.headers[\"content-type\"]?.toLowerCase().startsWith(\"application/json\")) {\n res.writeHead(415, { \"Content-Type\": \"text/plain\" })\n res.end(\"application/json is required\")\n return\n }\n try {\n const chunks: Buffer[] = []\n let bytes = 0\n for await (const c of req) {\n const chunk = c as Buffer\n bytes += chunk.length\n if (bytes > 64 * 1024) {\n res.writeHead(413, { \"Content-Type\": \"text/plain\" })\n res.end(\"review submission is too large\")\n return\n }\n chunks.push(chunk)\n }\n const body: unknown = JSON.parse(Buffer.concat(chunks).toString(\"utf8\"))\n const result = await opts.handleApply(body)\n res.writeHead(200, { \"Content-Type\": \"application/json\" })\n res.end(JSON.stringify(result))\n server.close(() => resolve(result))\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n log(` apply failed: ${message}`)\n res.writeHead(500, { \"Content-Type\": \"text/plain\" })\n res.end(message)\n }\n return\n }\n\n res.writeHead(404)\n res.end()\n })\n\n server.on(\"error\", reject)\n server.listen(opts.port ?? 0, \"127.0.0.1\", () => {\n const address = server.address()\n const port = typeof address === \"object\" && address ? address.port : opts.port\n opts.onReady(`http://127.0.0.1:${port}/`)\n if (opts.open !== false && process.platform === \"darwin\") {\n spawn(\"open\", [`http://127.0.0.1:${port}/`], { stdio: \"ignore\", detached: true }).unref()\n }\n })\n })\n}\n","import { requireSelectCandidate, type Provider } from \"../provider.ts\"\nimport { saveLock, upsert } from \"../lock.ts\"\nimport { lockKey, type Lock, type ResolvedSpec } from \"../types.ts\"\nimport { renderSheet, type SheetGroup } from \"./sheet.ts\"\nimport { serveReviewPage } from \"./review-server.ts\"\n\nexport interface PickResult {\n selected: number\n skipped: number\n}\n\nexport interface ReviewReadyInfo {\n url: string\n keys: string[]\n}\n\n/**\n * Serves the contact sheet on localhost, waits for the selections to be\n * applied, then shuts down.\n *\n * Selections are committed through the provider (`select-frames` promotes the chosen\n * candidate to its own object and drops the rest) and written to the lockfile\n * before the browser gets its response, so a closed tab never loses a choice.\n */\nexport async function runPicker(\n provider: Provider,\n lock: Lock,\n lockPath: string,\n opts: {\n port?: number\n open?: boolean\n onProgress?: (msg: string) => void\n /** Optional lock-key selection for a filtered or mixed-provider run. */\n keys?: Iterable<string>\n /** Resolved intent supplies immutable revision context for comparison. */\n specs?: ResolvedSpec[]\n /** Receives the live URL as soon as the server listens. */\n onReady?: (info: ReviewReadyInfo) => void\n } = {},\n): Promise<PickResult> {\n const log = opts.onProgress ?? (() => {})\n const selectedKeys = opts.keys ? new Set(opts.keys) : null\n const specByKey = new Map(\n (opts.specs ?? []).map((spec) => [lockKey(spec.styleId, spec.assetId), spec]),\n )\n const reviewAssets = new Map<string, { path: string; contentType: string }>()\n\n const groups: SheetGroup[] = []\n for (const [key, entry] of Object.entries(lock.entries)) {\n if (entry.provider !== provider.id || (selectedKeys && !selectedKeys.has(key))) continue\n if (entry.status !== \"review\" || !entry.reviewObjectId) continue\n try {\n const spec = specByKey.get(key)\n const state = await provider.poll(entry.reviewObjectId, entry.generator, { spec })\n if (\n (state.status !== \"review\" && state.status !== \"review-set\") ||\n (state.status === \"review\" ? !state.candidateUrls.length : !state.frameUrls.length)\n ) continue\n const frameUrls = state.status === \"review\" ? state.candidateUrls : state.frameUrls\n const sourceRoute = spec?.revision\n ? `/revision-source/${encodeURIComponent(String(groups.length))}`\n : null\n if (sourceRoute && spec?.revision) {\n reviewAssets.set(sourceRoute, {\n path: spec.revision.sourceFile,\n contentType: spec.revision.sourceFormat === \"jpeg\" ? \"image/jpeg\" : \"image/png\",\n })\n }\n groups.push({\n key,\n assetId: entry.assetId,\n styleId: entry.styleId,\n prompt: entry.prompt,\n reviewObjectId: entry.reviewObjectId,\n frameUrls,\n width: entry.width,\n height: entry.height,\n ...(state.status === \"review-set\"\n ? {\n mode: \"frame-set\" as const,\n frameLabels: state.sources.map((source, index) => source.role ?? `frame-${index}`),\n fps: state.fps,\n }\n : { mode: \"candidates\" as const }),\n ...(sourceRoute && spec?.revision && spec.revision.sourceWidth && spec.revision.sourceHeight\n ? {\n revision: {\n mode: spec.revision.mode,\n sourceAssetId: spec.revision.sourceAssetId,\n sourceUrl: sourceRoute,\n width: spec.revision.sourceWidth,\n height: spec.revision.sourceHeight,\n },\n }\n : {}),\n })\n } catch (err) {\n log(` could not load candidates for ${key}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n\n if (groups.length === 0) return { selected: 0, skipped: 0 }\n\n const html = renderSheet(groups)\n const byKey = new Map(groups.map((g) => [g.key, g]))\n\n return serveReviewPage<PickResult>({\n html,\n port: opts.port,\n open: opts.open,\n onProgress: log,\n assets: reviewAssets,\n onReady: (url) => {\n const info = { url, keys: groups.map((group) => group.key) }\n if (opts.onReady) {\n opts.onReady(info)\n } else {\n log(`\\n ${groups.length} asset(s) awaiting selection: ${url}`)\n log(` (leave this running; it exits once you apply)\\n`)\n }\n },\n handleApply: async (body) => {\n const { selections } = body as { selections: { key: string; index: number }[] }\n\n let selected = 0\n for (const { key, index } of selections) {\n const group = byKey.get(key)\n const entry = lock.entries[key]\n if (!group || !entry?.reviewObjectId) continue\n if (!Number.isInteger(index) || index < 0 || index >= group.frameUrls.length) continue\n\n if (group.mode === \"frame-set\") {\n const spec = specByKey.get(key)\n const state = await provider.poll(entry.reviewObjectId, entry.generator, { spec })\n if (state.status !== \"review-set\") {\n throw new Error(`Frame set ${key} is no longer ready for review`)\n }\n upsert(lock, key, {\n status: \"selected\",\n objectId: state.objectId,\n candidateIndex: null,\n sourceUrl: state.sources[0]?.url ?? null,\n sourceUrls: state.sources,\n provider: provider.id,\n providerMetadata: state.metadata\n ? {\n ...entry.providerMetadata,\n [provider.id]: {\n ...entry.providerMetadata[provider.id],\n ...state.metadata,\n },\n }\n : entry.providerMetadata,\n })\n selected++\n log(` accepted ${key} → ${state.sources.length} ordered frames`)\n continue\n }\n\n // Promote the chosen candidate; the review parent is removed upstream\n // once nothing is left in it.\n const { objectId, sourceUrl, metadata } = await requireSelectCandidate(provider)(\n entry.reviewObjectId,\n index,\n `asset:${entry.assetId}`,\n entry.generator,\n )\n\n upsert(lock, key, {\n status: \"selected\",\n objectId,\n candidateIndex: index,\n sourceUrl: sourceUrl ?? group.frameUrls[index] ?? null,\n sourceUrls: [],\n provider: provider.id,\n providerMetadata: metadata\n ? {\n ...entry.providerMetadata,\n [provider.id]: {\n ...entry.providerMetadata[provider.id],\n ...metadata,\n },\n }\n : entry.providerMetadata,\n })\n selected++\n log(` picked ${key} → candidate ${index + 1}`)\n }\n\n await saveLock(lockPath, lock)\n return { selected, skipped: groups.length - selected }\n },\n })\n}\n","import { readdir, readFile, writeFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport type { Generator, Manifest } from \"../types.ts\"\n\n/** Minimal PNG header read — avoids pulling in an image library just for dimensions. */\nexport function pngSize(buf: Buffer): { width: number; height: number } | null {\n if (buf.length < 24) return null\n const isPng = buf.readUInt32BE(0) === 0x89504e47 && buf.readUInt32BE(4) === 0x0d0a1a0a\n if (!isPng) return null\n if (buf.toString(\"ascii\", 12, 16) !== \"IHDR\") return null\n return { width: buf.readUInt32BE(16), height: buf.readUInt32BE(20) }\n}\n\n/** Path segment → a stable, readable asset id. */\nexport function slugify(value: string): string {\n return value\n .replace(/\\.png$/i, \"\")\n .replace(/[^a-zA-Z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .toLowerCase()\n}\n\nexport interface ScannedAsset {\n id: string\n category: string\n file: string\n width: number\n height: number\n}\n\nasync function walk(dir: string, exclude: string[]): Promise<string[]> {\n const out: string[] = []\n for (const entry of await readdir(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name)\n if (exclude.some((x) => full.includes(x))) continue\n if (entry.isDirectory()) out.push(...(await walk(full, exclude)))\n else if (entry.name.toLowerCase().endsWith(\".png\")) out.push(full)\n }\n return out\n}\n\n/**\n * Scans an existing asset tree and produces manifest entries for it.\n *\n * Prompts are left empty on purpose. For a project whose art already exists,\n * the accurate prompts are the ones actually used upstream — `adopt\n * --write-prompts` recovers those from the matched objects rather than having\n * anyone invent plausible-looking replacements.\n */\nexport async function scanAssets(\n root: string,\n opts: { exclude?: string[] } = {},\n): Promise<{ assets: ScannedAsset[]; skipped: string[] }> {\n const exclude = opts.exclude ?? []\n const files = await walk(root, exclude)\n const assets: ScannedAsset[] = []\n const skipped: string[] = []\n const seen = new Map<string, number>()\n\n for (const file of files.sort()) {\n const size = pngSize(await readFile(file))\n if (!size) {\n skipped.push(`${file} (not a readable PNG)`)\n continue\n }\n const rel = path.relative(root, file)\n const category = path.dirname(rel) === \".\" ? \"\" : path.dirname(rel)\n let id = slugify(path.basename(rel))\n\n // Basenames repeat across category folders; disambiguate rather than collide.\n if (seen.has(id)) {\n const n = seen.get(id)! + 1\n seen.set(id, n)\n id = `${slugify(category.replace(/[/\\\\]/g, \"_\"))}_${id}`.replace(/^_+/, \"\")\n } else {\n seen.set(id, 1)\n }\n\n assets.push({ id, category, file: rel, width: size.width, height: size.height })\n }\n\n return { assets, skipped }\n}\n\nexport function buildManifest(\n name: string,\n styleId: string,\n generator: Generator,\n outDir: string,\n scanned: ScannedAsset[],\n): Manifest {\n const squares = scanned.filter((a) => a.width === a.height)\n const commonSize = squares.length ? mode(squares.map((a) => a.width)) : 64\n\n const assets: Manifest[\"assets\"] = {}\n for (const asset of scanned) {\n assets[asset.id] = {\n prompt: \"\",\n promptByStyle: {},\n category: asset.category || undefined,\n file: asset.file,\n tags: [],\n styles: [],\n providerInputs: {},\n ...(generator === \"map\"\n ? { width: asset.width, height: asset.height }\n : asset.width === asset.height && asset.width !== commonSize\n ? { size: asset.width }\n : {}),\n }\n }\n\n return {\n name,\n provider: \"pixellab\",\n styles: {\n [styleId]: {\n generator,\n size: commonSize,\n // Matches the schema default: a scaffolded style is for sprites, and\n // a sprite wants its background stripped.\n noBackground: true,\n promptPrefix: \"\",\n promptSuffix: \"\",\n styleImages: [],\n palette: [],\n outDir,\n tags: [name],\n providerOptions: {},\n },\n },\n assets,\n }\n}\n\nfunction mode(values: number[]): number {\n const counts = new Map<number, number>()\n for (const v of values) counts.set(v, (counts.get(v) ?? 0) + 1)\n return [...counts.entries()].sort((a, b) => b[1] - a[1])[0]?.[0] ?? 64\n}\n\nexport async function writeManifestFile(target: string, manifest: Manifest): Promise<void> {\n if (existsSync(target)) {\n throw new Error(`${target} already exists — refusing to overwrite an existing manifest.`)\n }\n await writeFile(target, JSON.stringify(manifest, null, 2) + \"\\n\")\n}\n","import { readFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { requireList, type Provider, type RemoteAsset } from \"../provider.ts\"\nimport { loadManifest } from \"../manifest.ts\"\nimport { parseLock, type Lock, type Manifest } from \"../types.ts\"\n\n/**\n * Objects on the account that no known lockfile claims.\n *\n * The point of this is recovery, not cleanup. An account accumulates work that\n * was generated, paid for, and never landed in a repo — alternate takes,\n * abandoned experiments, whole categories that were explored and forgotten.\n * Measured on one account: 190 of 361 objects were unclaimed, and a visual\n * sample showed usable character portraits, tree variants, terrain tiles, and\n * UI icons rather than rejects.\n *\n * Correctness here depends entirely on being given EVERY lockfile. One account\n * is shared across projects, so an incomplete claim set makes another project's\n * shipped art look like an orphan.\n */\nexport interface LoadClaimsOptions {\n /** Include only entries owned by this provider. */\n provider?: string\n /** Prefix ids with their provider so unrelated accounts cannot collide. */\n qualify?: boolean\n}\n\nexport function providerClaimId(provider: string, objectId: string): string {\n // Encode both halves so a provider/id pair such as (\"a:b\", \"c\") cannot\n // collide with (\"a\", \"b:c\"). Built-in ids stay human-readable.\n return `${encodeURIComponent(provider)}:${encodeURIComponent(objectId)}`\n}\n\nexport async function loadClaims(\n lockPaths: string[],\n opts: LoadClaimsOptions = {},\n): Promise<Set<string>> {\n const claimed = new Set<string>()\n for (const p of lockPaths) {\n if (!existsSync(p)) throw new Error(`Claim lockfile not found: ${p}`)\n let parsed: Lock\n try {\n parsed = parseLock(JSON.parse(await readFile(p, \"utf8\")))\n } catch {\n throw new Error(`Claim lockfile is malformed: ${p}`)\n }\n for (const entry of Object.values(parsed.entries)) {\n if (opts.provider && entry.provider !== opts.provider) continue\n const add = (id: string | null) => {\n if (id) claimed.add(opts.qualify ? providerClaimId(entry.provider, id) : id)\n }\n add(entry.objectId)\n add(entry.reviewObjectId)\n add(entry.jobId)\n }\n }\n return claimed\n}\n\nexport interface Orphan {\n id: string\n prompt: string\n width: number\n height: number\n createdAt: string\n previewUrl: string\n tags: string[]\n}\n\nexport async function findOrphans(\n provider: Provider,\n claimed: Set<string>,\n opts: { onProgress?: (msg: string) => void } = {},\n): Promise<{ orphans: Orphan[]; total: number }> {\n const log = opts.onProgress ?? (() => {})\n const all: RemoteAsset[] = []\n for await (const obj of requireList(provider)()) all.push(obj)\n log(` scanned ${all.length} object(s) on the account`)\n\n const orphans = all\n .filter((o) =>\n !claimed.has(o.id) &&\n !claimed.has(providerClaimId(provider.id, o.id)) &&\n o.status === \"completed\" &&\n o.previewUrl,\n )\n .map((o) => ({\n id: o.id,\n prompt: o.prompt || \"(no prompt recorded)\",\n width: o.width,\n height: o.height,\n createdAt: o.createdAt,\n previewUrl: o.previewUrl!,\n tags: o.tags ?? [],\n }))\n // Newest first: recent work is likeliest to be worth recovering.\n .sort((a, b) => b.createdAt.localeCompare(a.createdAt))\n\n return { orphans, total: all.length }\n}\n\n/**\n * Fragments shorter than this match too much by accident (an empty\n * `promptPrefix`/`promptSuffix`, or a short one like \"clean\", would otherwise\n * \"match\" nearly every prompt via `.includes`).\n */\nconst MIN_STYLE_FRAGMENT_LENGTH = 12\n\n/**\n * Whether a style's `promptPrefix`/`promptSuffix` — boilerplate baked into\n * every generation of that style — appears in a prompt. Unlike\n * `matchOrphanStyle`, this never assumes a match just because a manifest\n * only has one style: it is the \"is this genuinely recognisable\" check, used\n * both by `matchOrphanStyle` and to test a prompt against a project that\n * isn't the current one.\n */\nfunction matchStyleByPattern(prompt: string, manifest: Manifest): string | null {\n const p = prompt.toLowerCase()\n for (const styleId of Object.keys(manifest.styles)) {\n const style = manifest.styles[styleId]!\n for (const raw of [style.promptPrefix, style.promptSuffix]) {\n const frag = raw?.trim().toLowerCase()\n if (frag && frag.length >= MIN_STYLE_FRAGMENT_LENGTH && p.includes(frag)) return styleId\n }\n }\n return null\n}\n\n/**\n * Which manifest style, if any, an orphan's prompt was generated from.\n *\n * A manifest with only one style skips the pattern check entirely — there is\n * nothing to disambiguate, and a style with an empty prefix/suffix (common\n * for single-style projects that don't template their prompts, like a\n * `map`-generator asset pack) would otherwise match nothing at all. This is\n * a routing decision (\"where would salvage import this\"), not a claim that\n * the content is genuinely this project's — see `groupOrphansByStyle`'s\n * `siblings` param for that distinction, which single-style manifests need\n * and multi-style ones get from the plain pattern check already.\n */\nexport function matchOrphanStyle(prompt: string, manifest: Manifest): string | null {\n const styleIds = Object.keys(manifest.styles)\n if (styleIds.length <= 1) return styleIds[0] ?? null\n return matchStyleByPattern(prompt, manifest)\n}\n\n/** A sibling project's manifest, consulted only to recognise its own style\n * patterns — never as an import target. */\nexport interface SiblingManifest {\n /** How to refer to this sibling in output — a project directory name, typically. */\n label: string\n manifest: Manifest\n}\n\n/**\n * Loads every sibling project's manifest for `groupOrphansByStyle`'s\n * sibling-exclusion signal, from the union of a workspace catalog's\n * registered manifests and the conventional sibling beside each `--claims`\n * lockfile (same directory, by the convention `--lock` defaults from\n * `--manifest`). The two sources are meant to combine, not choose between\n * (docs/RECOVERY.md: \"`--claims` still works and unions with a workspace's\n * claim set\") — a `--claims` path passed alongside `--workspace` must still\n * contribute its own style signal. Best-effort: a missing or malformed\n * sibling just means no extra signal for that orphan, not an error.\n */\nexport async function loadSiblingManifests(\n ownManifestPath: string,\n workspaceManifestPaths: string[],\n claimPaths: string[],\n): Promise<SiblingManifest[]> {\n const own = path.resolve(ownManifestPath)\n const siblingManifestPaths = [\n ...new Set([\n ...workspaceManifestPaths,\n ...claimPaths.map((c) => path.join(path.dirname(path.resolve(c)), \"pixelkiln.manifest.json\")),\n ]),\n ]\n const siblings: SiblingManifest[] = []\n for (const siblingManifestPath of siblingManifestPaths) {\n if (path.resolve(siblingManifestPath) === own) continue\n if (!existsSync(siblingManifestPath)) continue\n try {\n const { manifest } = await loadManifest(siblingManifestPath)\n siblings.push({ label: path.basename(path.dirname(siblingManifestPath)), manifest })\n } catch {\n // Not this run's problem to solve — the orphan just gets no extra signal.\n }\n }\n return siblings\n}\n\nexport interface OrphanGroups {\n /** styleId → its matched orphans, in manifest style order. */\n matched: Map<string, Orphan[]>\n /** Orphans that matched no style anywhere known — this manifest or any sibling. */\n unmatched: Orphan[]\n /** \"<sibling label>: <styleId>\" → orphans that confidently matched a\n * SIBLING's own pattern instead of this manifest's — excluded from\n * `matched` even where this manifest would otherwise have swallowed them\n * by default (a single-style manifest with nothing of its own to check\n * against). Empty unless `siblings` was passed to `groupOrphansByStyle`. */\n elsewhere: Map<string, Orphan[]>\n}\n\n/**\n * Splits orphans by the style that most likely produced them.\n *\n * `salvage` used to hand a single `--style` to a whole session regardless of\n * how many the orphan pool actually spanned, so importing anything wrong\n * silently mislabeled it under the first style in the manifest. Grouping\n * first lets the caller run one correctly-scoped session per style instead.\n *\n * A single-style manifest has no pattern of its own to filter by, so by\n * default everything routes to that one style — correct for a genuinely\n * single-project account, wrong for a shared one where the orphan pool is\n * mostly a sibling's art. Passing that sibling's manifest via `siblings` (its\n * lockfile sits beside it, by the same convention `--lock` defaults from\n * `--manifest`) lets a confident match against ITS pattern win instead,\n * pulling those orphans out of `matched` and into `elsewhere` even though\n * this manifest would otherwise have claimed them.\n */\nexport function groupOrphansByStyle(\n orphans: Orphan[],\n manifest: Manifest,\n siblings: SiblingManifest[] = [],\n): OrphanGroups {\n const matched = new Map<string, Orphan[]>()\n const elsewhere = new Map<string, Orphan[]>()\n const unmatched: Orphan[] = []\n const ownStyleIds = Object.keys(manifest.styles)\n for (const styleId of ownStyleIds) matched.set(styleId, [])\n\n for (const o of orphans) {\n const own = matchStyleByPattern(o.prompt, manifest)\n if (own) {\n matched.get(own)!.push(o)\n continue\n }\n\n const sibling = siblings.find((s) => matchStyleByPattern(o.prompt, s.manifest))\n if (sibling) {\n const key = `${sibling.label}: ${matchStyleByPattern(o.prompt, sibling.manifest)}`\n const list = elsewhere.get(key) ?? []\n list.push(o)\n elsewhere.set(key, list)\n continue\n }\n\n // Nothing recognised it anywhere. A single-style manifest still has no\n // better place to put it than its one style — the same pragmatic default\n // matchOrphanStyle uses — but a multi-style one genuinely doesn't know.\n if (ownStyleIds.length <= 1 && ownStyleIds[0]) matched.get(ownStyleIds[0])!.push(o)\n else unmatched.push(o)\n }\n for (const [styleId, list] of [...matched]) if (!list.length) matched.delete(styleId)\n return { matched, unmatched, elsewhere }\n}\n\n/**\n * A prompt makes a better id than a UUID. These are a starting point meant to\n * be renamed, so the goal is \"recognisable at a glance\", not perfection.\n */\nconst STYLE_WORDS = new Set([\n \"a\", \"an\", \"the\", \"one\", \"two\", \"three\", \"single\", \"centered\", \"center\", \"with\", \"and\",\n \"of\", \"on\", \"in\", \"for\", \"its\", \"has\", \"pixel\", \"art\", \"style\", \"game\", \"icon\",\n \"transparent\", \"background\", \"no\", \"premium\", \"indie\", \"achievement\", \"sprite\",\n \"isometric\", \"topdown\", \"top\", \"down\", \"view\", \"high\", \"low\", \"detailed\", \"simple\",\n \"clean\", \"bold\", \"dark\", \"outline\", \"silhouette\", \"colour\", \"color\", \"palette\",\n])\n\nexport function idFromPrompt(prompt: string, taken: Set<string>): string {\n // Prompts commonly read \"<style boilerplate>: <the actual subject>\". When a\n // colon is present the subject is after it, and using the whole string would\n // name every asset after the shared prefix.\n const colon = prompt.indexOf(\":\")\n const subject = colon >= 0 && colon < prompt.length - 12 ? prompt.slice(colon + 1) : prompt\n\n const words = subject\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length > 2 && !STYLE_WORDS.has(w))\n .slice(0, 4)\n\n let base = words.join(\"_\") || \"salvaged\"\n let id = base\n let n = 2\n while (taken.has(id)) id = `${base}_${n++}`\n taken.add(id)\n return id\n}\n\n/**\n * Placeholder spec hash written by a salvage import. The real hash cannot be\n * computed until the manifest has been rewritten with the new asset, so the CLI\n * re-baselines these immediately afterwards. Exported so the writer and the\n * re-baseliner reference one constant rather than two copies of a string.\n */\nexport const SALVAGED_SPEC_HASH = \"salvaged\"\n\nexport type SalvageAction = \"import\" | \"keep\" | \"discard\"\n\nexport interface SalvageDecision {\n id: string\n action: SalvageAction\n}\n\n/**\n * Tags are the durable record of a decision. They are free and synchronous, and\n * unlike a local file they survive on the account itself — so a later salvage\n * run from a different machine sees what was already triaged.\n *\n * `discard` deliberately only tags. Deleting is a separate, explicit command.\n */\nexport async function applyTags(\n provider: Provider,\n decisions: SalvageDecision[],\n existing: Map<string, string[]>,\n opts: { onProgress?: (msg: string) => void } = {},\n): Promise<{ tagged: number; failed: number }> {\n const log = opts.onProgress ?? (() => {})\n let tagged = 0\n let failed = 0\n\n for (const { id, action } of decisions) {\n const current = (existing.get(id) ?? []).filter(\n (t) => t !== \"pixelkiln:keep\" && t !== \"pixelkiln:discard\" && t !== \"pixelkiln:imported\",\n )\n const decisionTag = `pixelkiln:${action === \"import\" ? \"imported\" : action}`\n // PixelLab caps tags at 20. Preserve the decision tag even when the object\n // already has 20 unrelated tags; it is the durable record of this action.\n const next = [...current.slice(0, 19), decisionTag]\n if (!provider.setTags) return { tagged, failed }\n try {\n await provider.setTags(id, next)\n tagged++\n } catch (err) {\n failed++\n log(` tag failed ${id}: ${err instanceof Error ? err.message : String(err)}`)\n }\n }\n return { tagged, failed }\n}\n","import { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\"\nimport { existsSync } from \"node:fs\"\nimport path from \"node:path\"\nimport { z } from \"zod\"\n\n/**\n * One sibling project registered in a workspace catalog. Only paths and\n * identity live here — never a credential. Each project keeps loading its own\n * key from its own `.env`, the same as it does standalone.\n */\nexport const WorkspaceProjectSchema = z\n .object({\n id: z.string().min(1),\n /** Manifest path, relative to the catalog file's own directory. */\n manifest: z.string().min(1),\n /** Lockfile path, relative to the catalog file's own directory. */\n lock: z.string().min(1),\n provider: z.string().min(1).default(\"pixellab\"),\n /** Free-form label for a shared account, e.g. distinguishing sandboxes. */\n account: z.string().optional(),\n })\n .strict()\n\nexport const WorkspaceSchema = z\n .object({\n version: z.literal(1),\n projects: z.array(WorkspaceProjectSchema).default([]),\n })\n .strict()\n\nexport type WorkspaceProject = z.infer<typeof WorkspaceProjectSchema>\nexport type Workspace = z.infer<typeof WorkspaceSchema>\n\n/**\n * Parses a workspace catalog, rejecting anything that is not v1.\n *\n * Mirrors `parseLock`'s stance: no migration path, fail loudly rather than\n * guess at a hand-edited or corrupted file's intent.\n */\nexport function parseWorkspace(raw: unknown): Workspace {\n const parsed = WorkspaceSchema.safeParse(raw)\n if (parsed.success) return parsed.data\n throw new Error(\n `Workspace catalog is not valid v1:\\n${parsed.error.issues\n .slice(0, 5)\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\")}`,\n )\n}\n\nexport async function loadWorkspace(workspacePath: string): Promise<Workspace> {\n if (!existsSync(workspacePath)) return { version: 1, projects: [] }\n let raw: unknown\n try {\n raw = JSON.parse(await readFile(workspacePath, \"utf8\"))\n } catch (err) {\n throw new Error(\n `Workspace catalog at ${workspacePath} is malformed:\\n` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n return parseWorkspace(raw)\n}\n\n/** Atomic write — a crash mid-save must not leave a truncated catalog. */\nexport async function saveWorkspace(workspacePath: string, ws: Workspace): Promise<void> {\n const sorted: Workspace = {\n version: 1,\n projects: [...ws.projects].sort((a, b) => a.id.localeCompare(b.id)),\n }\n await mkdir(path.dirname(path.resolve(workspacePath)), { recursive: true })\n const tmp = `${workspacePath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`\n try {\n await writeFile(tmp, JSON.stringify(sorted, null, 2) + \"\\n\")\n await rename(tmp, workspacePath)\n } finally {\n await rm(tmp, { force: true })\n }\n}\n\n/** Stored path convention: relative to the catalog's directory, forward-slash. */\nexport function toPortablePath(dir: string, absolute: string): string {\n return path.relative(dir, absolute).split(path.sep).join(\"/\")\n}\n\n/** Resolve a registered project's stored paths against the catalog's directory. */\nexport function resolveProject(\n dir: string,\n project: WorkspaceProject,\n): { manifestPath: string; lockPath: string } {\n return {\n manifestPath: path.resolve(dir, project.manifest.split(\"/\").join(path.sep)),\n lockPath: path.resolve(dir, project.lock.split(\"/\").join(path.sep)),\n }\n}\n\nexport interface WorkspaceDiagnostic {\n id:\n | \"duplicate-id\"\n | \"duplicate-lock\"\n | \"duplicate-manifest\"\n | \"missing-manifest\"\n | \"missing-lock\"\n | \"absolute-path\"\n | \"mixed-provider\"\n level: \"error\" | \"warning\"\n message: string\n}\n\n/**\n * Checks the catalog without touching the network or any registered\n * project's files. Duplicate ids and duplicate lock paths are errors — either\n * would corrupt the union claim set. A duplicate manifest is only a warning,\n * because a manifest paired with a variant `--lock` is an already-supported\n * pattern (see `cachePathFor`). Missing files are errors: a claim set derived\n * from a workspace that silently skipped a project is the exact hazard this\n * catalog exists to prevent.\n */\nexport function validateWorkspace(ws: Workspace, dir: string): WorkspaceDiagnostic[] {\n const diagnostics: WorkspaceDiagnostic[] = []\n\n const idCounts = new Map<string, number>()\n const lockOwners = new Map<string, string[]>()\n const manifestOwners = new Map<string, string[]>()\n\n for (const project of ws.projects) {\n idCounts.set(project.id, (idCounts.get(project.id) ?? 0) + 1)\n\n const { manifestPath, lockPath } = resolveProject(dir, project)\n lockOwners.set(lockPath, [...(lockOwners.get(lockPath) ?? []), project.id])\n manifestOwners.set(manifestPath, [...(manifestOwners.get(manifestPath) ?? []), project.id])\n\n if (path.isAbsolute(project.manifest) || path.isAbsolute(project.lock)) {\n diagnostics.push({\n id: \"absolute-path\",\n level: \"warning\",\n message:\n `project \"${project.id}\" stores an absolute path — the catalog will not resolve ` +\n `correctly if this tree is cloned or moved elsewhere`,\n })\n }\n if (!existsSync(manifestPath)) {\n diagnostics.push({\n id: \"missing-manifest\",\n level: \"error\",\n message: `project \"${project.id}\" manifest not found: ${manifestPath}`,\n })\n }\n if (!existsSync(lockPath)) {\n diagnostics.push({\n id: \"missing-lock\",\n level: \"error\",\n message: `project \"${project.id}\" lockfile not found: ${lockPath}`,\n })\n }\n }\n\n for (const [id, count] of idCounts) {\n if (count > 1) {\n diagnostics.push({\n id: \"duplicate-id\",\n level: \"error\",\n message: `project id \"${id}\" is registered ${count} times`,\n })\n }\n }\n for (const [lockPath, ids] of lockOwners) {\n if (ids.length > 1) {\n diagnostics.push({\n id: \"duplicate-lock\",\n level: \"error\",\n message: `${ids.join(\", \")} all register the same lockfile: ${lockPath}`,\n })\n }\n }\n for (const [manifestPath, ids] of manifestOwners) {\n if (ids.length > 1) {\n diagnostics.push({\n id: \"duplicate-manifest\",\n level: \"warning\",\n message:\n `${ids.join(\", \")} share manifest ${manifestPath} — expected only when they are ` +\n `variant lockfiles beside one manifest`,\n })\n }\n }\n\n const providers = new Set(ws.projects.map((p) => p.provider))\n if (providers.size > 1) {\n diagnostics.push({\n id: \"mixed-provider\",\n level: \"warning\",\n message:\n `registered projects use different providers: ${[...providers].sort().join(\", \")} — ` +\n `spend totals are kept separate per unit, but confirm this is intentional`,\n })\n }\n\n return diagnostics\n}\n","import { loadLock, spendByUnit } from \"../lock.ts\"\nimport { loadManifest, resolveSpecs } from \"../manifest.ts\"\nimport { normalizeLockOutputPaths } from \"../outputs.ts\"\nimport type { CostUnit } from \"../provider.ts\"\nimport {\n resolveProject,\n validateWorkspace,\n type Workspace,\n type WorkspaceDiagnostic,\n} from \"../workspace.ts\"\nimport { loadClaims } from \"./salvage.ts\"\nimport { buildPlan, summarize, type PlanState } from \"./plan.ts\"\n\nexport interface WorkspaceClaims {\n /** Provider-qualified remote ids (`provider:id`) across every lock. */\n claimed: Set<string>\n /** Claim count contributed by each registered project. */\n byProject: Record<string, number>\n lockPaths: string[]\n}\n\n/**\n * The complete account-wide claim set, derived from every registered lock.\n *\n * Delegates the union rule itself to `loadClaims` rather than reimplementing\n * it, so the workspace and single-project `--claims` paths cannot drift. Each\n * lock is loaded one at a time — rather than handing `loadClaims` the whole\n * path list at once — purely so a failure can be attributed to the project\n * that owns it; the safety property (any unreadable registered lock aborts\n * before returning a claim set) is identical either way.\n */\nexport async function workspaceClaims(ws: Workspace, dir: string): Promise<WorkspaceClaims> {\n const lockPaths: string[] = []\n const byProject: Record<string, number> = {}\n const claimed = new Set<string>()\n\n for (const project of ws.projects) {\n const { lockPath } = resolveProject(dir, project)\n lockPaths.push(lockPath)\n let projectClaims: Set<string>\n try {\n projectClaims = await loadClaims([lockPath], { qualify: true })\n } catch (err) {\n throw new Error(\n `Project \"${project.id}\" lockfile is unreadable: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n byProject[project.id] = projectClaims.size\n for (const id of projectClaims) claimed.add(id)\n }\n\n return { claimed, byProject, lockPaths }\n}\n\nfunction emptyStateCounts(): Record<PlanState, number> {\n return {\n ok: 0, missing: 0, untracked: 0, stale: 0, orphaned: 0, \"in-flight\": 0,\n recoverable: 0, blocked: 0, failed: 0,\n }\n}\n\nexport interface WorkspaceProjectStatus {\n id: string\n /** Legacy/default catalog provider. */\n provider: string\n /** Effective providers resolved from every manifest style. */\n providers: string[]\n account: string | null\n manifest: string\n lock: string\n entries: number\n byState: Record<PlanState, number>\n spendByUnit: Record<CostUnit, number>\n error: string | null\n}\n\nexport interface WorkspaceStatusReport {\n version: 1\n safe: boolean\n /** The catalog's own directory — resolved paths in `projects` sit under it. */\n dir: string\n projects: WorkspaceProjectStatus[]\n totals: {\n byState: Record<PlanState, number>\n spendByUnit: Record<CostUnit, number>\n claims: number\n }\n diagnostics: WorkspaceDiagnostic[]\n}\n\n/**\n * Aggregate, read-only account/project state — offline throughout, using the\n * same offline cost estimator `plan` uses. A project whose manifest or lock\n * fails to load surfaces as that project's own `error` rather than aborting\n * the whole report, so one broken sibling does not hide every other\n * project's status. It never writes to any registered project's lock.\n */\nexport async function workspaceStatus(ws: Workspace, dir: string): Promise<WorkspaceStatusReport> {\n const diagnostics = validateWorkspace(ws, dir)\n const projects: WorkspaceProjectStatus[] = []\n const totalsByState = emptyStateCounts()\n const totalsSpend: Record<CostUnit, number> = { generations: 0, usd: 0, free: 0 }\n\n for (const project of ws.projects) {\n const { manifestPath, lockPath } = resolveProject(dir, project)\n const base = {\n id: project.id,\n provider: project.provider,\n account: project.account ?? null,\n manifest: manifestPath,\n lock: lockPath,\n }\n try {\n const loaded = await loadManifest(manifestPath)\n const specs = await resolveSpecs(loaded)\n const providers = [...new Set(\n Object.values(loaded.manifest.styles).map(\n (style) => style.provider ?? loaded.manifest.provider,\n ),\n )].sort()\n if (!providers.length) providers.push(loaded.manifest.provider)\n const lock = await loadLock(lockPath)\n normalizeLockOutputPaths(lock, specs)\n const plan = await buildPlan(specs, lock)\n const byState = summarize(plan)\n const spend = spendByUnit(lock)\n for (const state of Object.keys(byState) as PlanState[]) {\n totalsByState[state] += byState[state]\n }\n for (const unit of Object.keys(spend) as CostUnit[]) {\n totalsSpend[unit] = (totalsSpend[unit] ?? 0) + (spend[unit] ?? 0)\n }\n projects.push({\n ...base,\n provider: providers.length === 1 ? providers[0]! : project.provider,\n providers,\n entries: Object.keys(lock.entries).length,\n byState,\n spendByUnit: spend,\n error: null,\n })\n } catch (err) {\n projects.push({\n ...base,\n providers: [project.provider],\n entries: 0,\n byState: emptyStateCounts(),\n spendByUnit: { generations: 0, usd: 0, free: 0 },\n error: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n let claims = 0\n try {\n claims = (await workspaceClaims(ws, dir)).claimed.size\n } catch {\n // Already visible via a project's own `error` or a missing-lock\n // diagnostic; not worth surfacing a second time here.\n }\n\n return {\n version: 1,\n safe: !diagnostics.some((d) => d.level === \"error\") && projects.every((p) => !p.error),\n dir,\n projects,\n totals: { byState: totalsByState, spendByUnit: totalsSpend, claims },\n diagnostics,\n }\n}\n","import { existsSync } from \"node:fs\"\nimport { readFile, readdir, rm } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport {\n cachePathFor,\n isSha256Hash,\n parseCache,\n saveCache,\n type HashCache,\n} from \"../cache.ts\"\nimport { sha256 } from \"../hash.ts\"\nimport type { Lock } from \"../types.ts\"\nimport { mediaTypeFromExtension, validateMedia } from \"../media.ts\"\n\nexport interface ContentCacheIssue {\n name: string\n reason: string\n}\n\nexport interface ContentCacheHealth {\n path: string\n exists: boolean\n files: number\n bytes: number\n valid: number\n referenced: number\n unreferenced: string[]\n missingReferenced: string[]\n invalid: ContentCacheIssue[]\n}\n\nexport interface RemoteHashCacheHealth {\n path: string\n exists: boolean\n entries: number\n valid: number\n invalidIds: string[]\n error: string | null\n}\n\nexport interface CacheHealthReport {\n safe: boolean\n content: ContentCacheHealth\n remoteHashes: RemoteHashCacheHealth\n removed: {\n contentFiles: number\n remoteHashEntries: number\n resetRemoteHashCache: boolean\n }\n}\n\nexport interface CacheHealthOptions {\n /** Remove invalid and unreferenced content, plus invalid remote hash entries. */\n prune?: boolean\n}\n\n/**\n * Inspect both local caches without contacting the provider.\n *\n * Content PNGs are project-local and keyed by lockfile SHA, so orphaned bytes\n * can be removed safely. The object-hash cache is account-wide: this function\n * validates its schema and hashes but never removes an object merely because\n * the current project does not reference it. `adopt` owns that live-ID prune,\n * because only it has walked the complete provider account.\n */\nexport async function inspectCaches(\n lock: Lock,\n lockPath: string,\n options: CacheHealthOptions = {},\n): Promise<CacheHealthReport> {\n if (options.prune && !existsSync(lockPath)) {\n throw new Error(`Refusing to prune without an existing lockfile at ${path.resolve(lockPath)}`)\n }\n const contentDir = path.resolve(path.dirname(lockPath), \".pixelkiln\", \"cache\")\n const remotePath = path.resolve(cachePathFor(lockPath))\n const referenced = new Set(\n Object.values(lock.entries).flatMap((entry) => entry.outputs.map((output) => output.sha256)),\n )\n\n let content = await inspectContentCache(contentDir, referenced)\n let remoteHashes = await inspectRemoteHashCache(remotePath)\n const removed = { contentFiles: 0, remoteHashEntries: 0, resetRemoteHashCache: false }\n\n if (options.prune) {\n const names = new Set([\n ...content.unreferenced,\n ...content.invalid.map((issue) => issue.name),\n ])\n for (const name of names) {\n // Every name came directly from a non-recursive readdir of contentDir;\n // removing this explicit child cannot escape through path traversal.\n try {\n await rm(path.join(contentDir, name), { force: true })\n removed.contentFiles++\n } catch {\n // Directories and permission failures remain in the follow-up report.\n }\n }\n\n if (remoteHashes.error) {\n await saveCache(remotePath, { version: 1, hashes: {} })\n removed.resetRemoteHashCache = true\n } else if (remoteHashes.invalidIds.length) {\n const cache = parseCache(JSON.parse(await readFile(remotePath, \"utf8\")))\n for (const id of remoteHashes.invalidIds) delete cache.hashes[id]\n removed.remoteHashEntries = remoteHashes.invalidIds.length\n await saveCache(remotePath, cache)\n }\n\n content = await inspectContentCache(contentDir, referenced)\n remoteHashes = await inspectRemoteHashCache(remotePath)\n }\n\n return {\n safe: content.invalid.length === 0 && !remoteHashes.error && remoteHashes.invalidIds.length === 0,\n content,\n remoteHashes,\n removed,\n }\n}\n\nasync function inspectContentCache(\n contentDir: string,\n referenced: Set<string>,\n): Promise<ContentCacheHealth> {\n const report: ContentCacheHealth = {\n path: contentDir,\n exists: existsSync(contentDir),\n files: 0,\n bytes: 0,\n valid: 0,\n referenced: 0,\n unreferenced: [],\n missingReferenced: [],\n invalid: [],\n }\n if (!report.exists) {\n report.missingReferenced = [...referenced].sort()\n return report\n }\n\n const present = new Set<string>()\n const entries = await readdir(contentDir, { withFileTypes: true })\n for (const entry of entries) {\n if (!entry.isFile()) {\n report.invalid.push({ name: entry.name, reason: \"not a regular file\" })\n continue\n }\n report.files++\n const file = path.join(contentDir, entry.name)\n const mediaType = mediaTypeFromExtension(entry.name)\n const expected = mediaType ? entry.name.slice(0, -4) : \"\"\n let bytes: Buffer\n try {\n bytes = await readFile(file)\n report.bytes += bytes.length\n } catch (err) {\n report.invalid.push({\n name: entry.name,\n reason: `unreadable: ${err instanceof Error ? err.message : String(err)}`,\n })\n continue\n }\n if (!isSha256Hash(expected)) {\n report.invalid.push({ name: entry.name, reason: \"filename is not <sha256>.png or <sha256>.gif\" })\n continue\n }\n if (sha256(bytes) !== expected) {\n report.invalid.push({ name: entry.name, reason: \"bytes do not match filename hash\" })\n continue\n }\n try {\n validateMedia(bytes, mediaType!)\n } catch (err) {\n report.invalid.push({\n name: entry.name,\n reason: `invalid ${mediaType === \"image/gif\" ? \"GIF\" : \"PNG\"}: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n })\n continue\n }\n present.add(expected)\n report.valid++\n if (referenced.has(expected)) report.referenced++\n else report.unreferenced.push(entry.name)\n }\n report.unreferenced.sort()\n report.missingReferenced = [...referenced].filter((hash) => !present.has(hash)).sort()\n return report\n}\n\nasync function inspectRemoteHashCache(remotePath: string): Promise<RemoteHashCacheHealth> {\n const report: RemoteHashCacheHealth = {\n path: remotePath,\n exists: existsSync(remotePath),\n entries: 0,\n valid: 0,\n invalidIds: [],\n error: null,\n }\n if (!report.exists) return report\n let cache: HashCache\n try {\n cache = parseCache(JSON.parse(await readFile(remotePath, \"utf8\")))\n } catch (err) {\n report.error = err instanceof Error ? err.message : String(err)\n return report\n }\n report.entries = Object.keys(cache.hashes).length\n for (const [id, hash] of Object.entries(cache.hashes)) {\n if (isSha256Hash(hash)) report.valid++\n else report.invalidIds.push(id)\n }\n report.invalidIds.sort()\n return report\n}\n","import type { LockEntry, ResolvedSpec } from \"../types.ts\"\nimport { fallbackOutputRole, resolveSpecEntryOutputs } from \"../outputs.ts\"\nimport { packSprites, type PackedFrame, type PackedSource } from \"./pack.ts\"\n\nexport type TilesetFormat = \"generic\" | \"tiled\" | \"godot\"\n\nexport interface NormalizedTileRules {\n ruleType: \"edge\" | \"corner\" | \"outline\"\n arity: 4 | 6\n connectivity?: \"same\" | \"other\"\n terrains: string[]\n /** Provider tile index to adjacency mask. Tiles absent here are stamp-only. */\n masks: Record<number, number>\n raw: Record<string, unknown>\n}\n\nexport interface GenericTileset {\n format: \"pixelkiln-tileset\"\n version: 1\n name: string\n style: string\n asset: string\n image: string\n tile: { width: number; height: number }\n sheet: { width: number; height: number; columns: number }\n tiles: Array<{\n id: number\n /** Original provider index; can differ from id when stamp-only keys leave gaps. */\n sourceIndex: number\n role: string\n x: number\n y: number\n width: number\n height: number\n bitmask?: number\n stampOnly: boolean\n }>\n /** Complete provider object, even when its rule family is not normalized yet. */\n providerRules: Record<string, unknown> | null\n rules: NormalizedTileRules | null\n}\n\nexport interface TilesetExport {\n png: Buffer\n extension: \".json\" | \".tsj\" | \".tres\"\n document: string\n generic: GenericTileset\n sources: PackedSource[]\n}\n\nexport interface TilesetExportOptions {\n format: TilesetFormat\n manifestDir: string\n imageName: string\n columns?: number\n}\n\n/** Parse the deliberately open provider schema into the stable export subset. */\nexport function normalizeTileRules(raw: unknown): NormalizedTileRules | null {\n if (!isRecord(raw)) return null\n const ruleType = raw.rule_type\n const arity = raw.arity\n if (ruleType !== \"edge\" && ruleType !== \"corner\" && ruleType !== \"outline\") return null\n if (arity !== 4 && arity !== 6) return null\n\n const masks: Record<number, number> = {}\n if (isRecord(raw.tiles)) {\n for (const [key, value] of Object.entries(raw.tiles)) {\n const index = tileIndex(key)\n const mask = typeof value === \"number\"\n ? value\n : isRecord(value) && typeof value.bitmask === \"number\"\n ? value.bitmask\n : isRecord(value) && typeof value.mask === \"number\"\n ? value.mask\n : null\n if (index !== null && mask !== null && Number.isInteger(mask) && mask >= 0) masks[index] = mask\n }\n }\n\n const connectivity = raw.connectivity === \"same\" || raw.connectivity === \"other\"\n ? raw.connectivity\n : undefined\n const terrains = Array.isArray(raw.terrains)\n ? raw.terrains.filter((item): item is string => typeof item === \"string\")\n : []\n return {\n ruleType,\n arity,\n ...(connectivity ? { connectivity } : {}),\n terrains,\n masks,\n raw,\n }\n}\n\n/** Build an atlas plus generic, Tiled TSJ, or Godot 4 TileSet metadata. */\nexport function exportTileset(\n entry: LockEntry,\n spec: ResolvedSpec,\n options: TilesetExportOptions,\n): TilesetExport {\n const outputs = resolveSpecEntryOutputs(entry, spec)\n if (!outputs.length) throw new Error(`${spec.styleId}/${spec.assetId} has no downloaded outputs`)\n\n const packed = packSprites(\n outputs.map((output) => ({\n id: output.role ?? fallbackOutputRole(output.index),\n path: output.absolutePath,\n })),\n { columns: options.columns, order: \"input\" },\n )\n if (packed.skipped.length) {\n throw new Error(\n `Cannot export ${spec.styleId}/${spec.assetId}: ` +\n packed.skipped.map((item) => `${item.id}: ${item.reason}`).join(\"; \"),\n )\n }\n\n const metadata = entry.providerMetadata?.[entry.provider]\n const rawRules = isRecord(metadata) ? metadata.tileRules : undefined\n const rules = normalizeTileRules(rawRules)\n const frames = packed.atlas.frames\n const generic = buildGeneric(\n spec,\n options.imageName,\n packed.atlas,\n frames,\n isRecord(rawRules) ? rawRules : null,\n rules,\n )\n\n if (options.format === \"generic\") {\n return {\n png: packed.png,\n extension: \".json\",\n document: JSON.stringify(generic, null, 2) + \"\\n\",\n generic,\n sources: packed.sources,\n }\n }\n\n assertUniformTiles(generic)\n if ((rawRules !== undefined || entry.tileFeature) && !rules) {\n throw new Error(\n `${options.format} export needs recognized adjacency rules; use --format generic ` +\n `to retain this provider rule object without guessing`,\n )\n }\n if (rules?.arity === 6) {\n throw new Error(\n `${options.format} export does not yet map six-edge hex masks safely; use --format generic`,\n )\n }\n if (rules?.ruleType === \"outline\") {\n throw new Error(\n `${options.format} export cannot infer adjacency from outline/stamp-only rules; use --format generic`,\n )\n }\n\n if (options.format === \"tiled\") {\n return {\n png: packed.png,\n extension: \".tsj\",\n document: JSON.stringify(buildTiled(generic), null, 2) + \"\\n\",\n generic,\n sources: packed.sources,\n }\n }\n return {\n png: packed.png,\n extension: \".tres\",\n document: buildGodot(generic, spec),\n generic,\n sources: packed.sources,\n }\n}\n\nfunction buildGeneric(\n spec: ResolvedSpec,\n imageName: string,\n atlas: { sheet: { width: number; height: number }; cell: { width: number; height: number }; columns: number },\n frames: PackedFrame[],\n providerRules: Record<string, unknown> | null,\n rules: NormalizedTileRules | null,\n): GenericTileset {\n return {\n format: \"pixelkiln-tileset\",\n version: 1,\n name: `${spec.styleId}/${spec.assetId}`,\n style: spec.styleId,\n asset: spec.assetId,\n image: imageName,\n tile: { ...atlas.cell },\n sheet: { ...atlas.sheet, columns: atlas.columns },\n tiles: frames.map((frame, index) => {\n const sourceIndex = tileIndex(frame.id) ?? index\n return {\n id: index,\n sourceIndex,\n role: frame.id,\n x: frame.x,\n y: frame.y,\n width: frame.width,\n height: frame.height,\n ...(rules?.masks[sourceIndex] !== undefined ? { bitmask: rules.masks[sourceIndex] } : {}),\n stampOnly: rules ? rules.masks[sourceIndex] === undefined : true,\n }\n }),\n providerRules,\n rules,\n }\n}\n\nfunction buildTiled(generic: GenericTileset): Record<string, unknown> {\n const rules = generic.rules\n const tiled: Record<string, unknown> = {\n type: \"tileset\",\n version: \"1.10\",\n tiledversion: \"1.12.2\",\n name: generic.name.replace(\"/\", \"-\"),\n tilewidth: generic.tile.width,\n tileheight: generic.tile.height,\n tilecount: generic.tiles.length,\n columns: generic.sheet.columns,\n image: generic.image,\n imagewidth: generic.sheet.width,\n imageheight: generic.sheet.height,\n margin: 0,\n spacing: 0,\n }\n if (!rules || rules.ruleType === \"outline\") return tiled\n\n const terrainNames = terrainNamesFor(rules)\n tiled.wangsets = [{\n name: generic.name,\n type: rules.ruleType,\n tile: representativeTile(generic, 0),\n colors: terrainNames.map((name, index) => ({\n name,\n color: index === 0 ? \"#5ab552\" : \"#4c78a8\",\n tile: representativeTile(generic, index),\n probability: 1,\n })),\n properties: rules.connectivity\n ? [{ name: \"pixelkiln:connectivity\", type: \"string\", value: rules.connectivity }]\n : [],\n wangtiles: generic.tiles\n .filter((tile) => tile.bitmask !== undefined)\n .map((tile) => ({ tileid: tile.id, wangid: tiledWangId(rules, tile.bitmask!) })),\n }]\n return tiled\n}\n\nfunction tiledWangId(rules: NormalizedTileRules, mask: number): number[] {\n const bitColor = (bit: number) => ((mask & (1 << bit)) !== 0 ? 1 : 2)\n if (rules.ruleType === \"corner\") {\n // Tiled order: top edge, NE, right edge, SE, bottom edge, SW, left edge, NW.\n return [0, bitColor(2), 0, bitColor(0), 0, bitColor(1), 0, bitColor(3)]\n }\n // PixelLab edge mask: bit0=N bit1=E bit2=S bit3=W.\n return [bitColor(0), 0, bitColor(1), 0, bitColor(2), 0, bitColor(3), 0]\n}\n\nfunction buildGodot(generic: GenericTileset, spec: ResolvedSpec): string {\n const rules = generic.rules\n const lines = [\n `[gd_resource type=\"TileSet\" load_steps=3 format=3]`,\n \"\",\n `[ext_resource type=\"Texture2D\" path=${JSON.stringify(`./${generic.image}`)} id=\"1_texture\"]`,\n \"\",\n `[sub_resource type=\"TileSetAtlasSource\" id=\"TileSetAtlasSource_pixelkiln\"]`,\n `texture = ExtResource(\"1_texture\")`,\n `texture_region_size = Vector2i(${generic.tile.width}, ${generic.tile.height})`,\n ]\n\n for (const tile of generic.tiles) {\n const x = tile.id % generic.sheet.columns\n const y = Math.floor(tile.id / generic.sheet.columns)\n lines.push(`${x}:${y}/0 = 0`)\n if (!rules || tile.bitmask === undefined || rules.ruleType === \"outline\") continue\n const values = godotTerrainBits(rules, tile.bitmask)\n lines.push(`${x}:${y}/0/terrain_set = 0`)\n lines.push(`${x}:${y}/0/terrain = ${dominantTerrain(values)}`)\n for (const [side, value] of Object.entries(values)) {\n lines.push(`${x}:${y}/0/terrains_peering_bit/${side} = ${value}`)\n }\n }\n\n lines.push(\"\", \"[resource]\")\n lines.push(`tile_size = Vector2i(${generic.tile.width}, ${generic.tile.height})`)\n const shape = godotTileShape(spec.tileType ?? \"isometric\")\n if (shape !== 0) lines.push(`tile_shape = ${shape}`)\n if (rules && rules.ruleType !== \"outline\") {\n lines.push(`terrain_set_0/mode = ${rules.ruleType === \"corner\" ? 1 : 2}`)\n for (const [index, name] of terrainNamesFor(rules).entries()) {\n lines.push(`terrain_set_0/terrain_${index}/name = ${JSON.stringify(name)}`)\n lines.push(\n `terrain_set_0/terrain_${index}/color = ` +\n (index === 0 ? \"Color(0.3529, 0.7098, 0.3216, 1)\" : \"Color(0.298, 0.4706, 0.6588, 1)\"),\n )\n }\n }\n lines.push(`sources/0 = SubResource(\"TileSetAtlasSource_pixelkiln\")`, \"\")\n return lines.join(\"\\n\")\n}\n\nfunction godotTerrainBits(rules: NormalizedTileRules, mask: number): Record<string, number> {\n const terrain = (bit: number) => ((mask & (1 << bit)) !== 0 ? 0 : 1)\n if (rules.ruleType === \"corner\") {\n return {\n top_left_corner: terrain(3),\n top_right_corner: terrain(2),\n bottom_left_corner: terrain(1),\n bottom_right_corner: terrain(0),\n }\n }\n return {\n top_side: terrain(0),\n right_side: terrain(1),\n bottom_side: terrain(2),\n left_side: terrain(3),\n }\n}\n\nfunction dominantTerrain(values: Record<string, number>): number {\n const terrainZero = Object.values(values).filter((value) => value === 0).length\n return terrainZero * 2 >= Object.keys(values).length ? 0 : 1\n}\n\nfunction godotTileShape(tileType: string | undefined): number {\n if (tileType === \"isometric\" || tileType === \"oblique\") return 1\n if (tileType === \"hex\" || tileType === \"hex_pointy\") return 3\n return 0\n}\n\nfunction representativeTile(generic: GenericTileset, terrainIndex: number): number {\n const rules = generic.rules!\n const full = (1 << rules.arity) - 1\n const wanted = terrainIndex === 0 ? full : 0\n return generic.tiles.find((tile) => tile.bitmask === wanted)?.id ?? -1\n}\n\nfunction terrainNamesFor(rules: NormalizedTileRules): string[] {\n return [rules.terrains[0] ?? \"feature\", rules.terrains[1] ?? \"background\"]\n}\n\nfunction assertUniformTiles(generic: GenericTileset): void {\n const mismatched = generic.tiles.filter(\n (tile) => tile.width !== generic.tile.width || tile.height !== generic.tile.height,\n )\n if (mismatched.length) {\n throw new Error(\n `Engine tilesets require uniform ${generic.tile.width}x${generic.tile.height} cells; ` +\n `mismatched: ${mismatched.map((tile) => tile.role).join(\", \")}. Use --format generic.`,\n )\n }\n}\n\nfunction tileIndex(key: string): number | null {\n const match = key.match(/(?:^|[_-])(\\d+)$/)\n return match ? Number(match[1]) : null\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n}\n","import { mkdir, writeFile, readFile } from \"node:fs/promises\"\nimport path from \"node:path\"\nimport type { Provider } from \"../provider.ts\"\nimport { sha256 } from \"../hash.ts\"\nimport { saveLock, upsert } from \"../lock.ts\"\nimport { portableOutputPath } from \"../outputs.ts\"\nimport { decodePng } from \"../png.ts\"\nimport { shouldPersistSourceUrl } from \"../source-url.ts\"\nimport { lockKey, type Lock, type Manifest } from \"../types.ts\"\nimport {\n applyTags,\n idFromPrompt,\n SALVAGED_SPEC_HASH,\n type Orphan,\n type SalvageDecision,\n} from \"../pipeline/salvage.ts\"\nimport { renderSalvageSheet } from \"./salvage-sheet.ts\"\nimport { serveReviewPage } from \"./review-server.ts\"\n\nconst PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])\n\nexport interface SalvageResult {\n imported: number\n kept: number\n discarded: number\n failed: number\n}\n\n/**\n * Serves the triage sheet and applies decisions.\n *\n * `import` is the only action that touches local state: it downloads the image,\n * writes a manifest asset and a lock entry, so a recovered sprite becomes a\n * first-class tracked asset rather than a loose file. `keep` and `discard` only\n * write tags upstream — no object is ever deleted here.\n */\nexport async function runSalvage(\n provider: Provider,\n orphans: Orphan[],\n ctx: {\n manifestPath: string\n manifest: Manifest\n styleId: string\n importDir: string\n lock: Lock\n lockPath: string\n },\n opts: { port?: number; open?: boolean; onProgress?: (msg: string) => void } = {},\n): Promise<SalvageResult> {\n const log = opts.onProgress ?? (() => {})\n const html = renderSalvageSheet(orphans, {\n styleId: ctx.styleId,\n importDir: path.relative(process.cwd(), ctx.importDir) || \".\",\n })\n const byId = new Map(orphans.map((o) => [o.id, o]))\n const existingTags = new Map(orphans.map((o) => [o.id, o.tags]))\n\n return serveReviewPage<SalvageResult>({\n html,\n port: opts.port,\n open: opts.open,\n onProgress: log,\n onReady: (url) => {\n log(`\\n ${orphans.length} unclaimed object(s) to triage: ${url}`)\n log(` (nothing is deleted here — discard only tags)\\n`)\n },\n handleApply: async (body) => {\n const { decisions } = body as { decisions: SalvageDecision[] }\n\n const result: SalvageResult = { imported: 0, kept: 0, discarded: 0, failed: 0 }\n const taken = new Set(Object.keys(ctx.manifest.assets))\n const importedAssetIds: string[] = []\n\n for (const decision of decisions) {\n const orphan = byId.get(decision.id)\n if (!orphan) continue\n\n if (decision.action === \"import\") {\n try {\n const buf = await provider.download(orphan.previewUrl)\n if (!buf.subarray(0, 8).equals(PNG_SIGNATURE)) throw new Error(\"not a PNG\")\n decodePng(buf)\n\n const assetId = idFromPrompt(orphan.prompt, taken)\n const rel = path.join(\"_salvaged\", `${assetId}.png`)\n const outFile = path.resolve(ctx.importDir, rel)\n await mkdir(path.dirname(outFile), { recursive: true })\n await writeFile(outFile, buf)\n\n ctx.manifest.assets[assetId] = {\n prompt: orphan.prompt,\n promptByStyle: {},\n category: \"_salvaged\",\n file: rel,\n tags: [\"salvaged\"],\n styles: [ctx.styleId],\n providerInputs: {},\n ...(orphan.width === orphan.height\n ? { size: orphan.width }\n : { width: orphan.width, height: orphan.height }),\n }\n\n const durableSource = shouldPersistSourceUrl(orphan.previewUrl)\n ? orphan.previewUrl\n : null\n\n upsert(ctx.lock, lockKey(ctx.styleId, assetId), {\n styleId: ctx.styleId,\n assetId,\n specHash: SALVAGED_SPEC_HASH,\n generator: orphan.width === orphan.height ? \"1dir\" : \"map\",\n prompt: orphan.prompt,\n width: orphan.width,\n height: orphan.height,\n jobId: orphan.id,\n reviewObjectId: null,\n objectId: orphan.id,\n candidateIndex: null,\n status: \"downloaded\",\n error: null,\n // The bytes are already local. Do not turn a temporary signed\n // review URL into a credential-bearing committed lock entry.\n sourceUrl: durableSource,\n sourceUrls: durableSource ? [{ url: durableSource }] : [],\n outputs: [{\n path: portableOutputPath(outFile, path.dirname(ctx.manifestPath)),\n sha256: sha256(buf),\n }],\n submittedAt: orphan.createdAt,\n downloadedAt: new Date().toISOString(),\n cost: 0, // already paid for, in an earlier period\n costUnit: \"generations\",\n provider: provider.id,\n })\n importedAssetIds.push(assetId)\n result.imported++\n log(` imported ${assetId} ← ${orphan.id}`)\n } catch (err) {\n result.failed++\n log(` import failed ${orphan.id}: ${err instanceof Error ? err.message : String(err)}`)\n }\n } else if (decision.action === \"keep\") {\n result.kept++\n } else {\n result.discarded++\n }\n }\n\n await applyTags(provider, decisions, existingTags, { onProgress: log })\n\n // Persist the manifest additions and the lock together. Only the\n // newly imported entries are written back — re-merging the whole\n // in-memory manifest would overwrite every pre-existing asset with\n // its loadManifest()-normalized copy, turning a one-asset import\n // into a diff touching the entire file.\n const raw = JSON.parse(await readFile(ctx.manifestPath, \"utf8\")) as Manifest\n for (const id of importedAssetIds) raw.assets[id] = ctx.manifest.assets[id]!\n await writeFile(ctx.manifestPath, JSON.stringify(raw, null, 2) + \"\\n\")\n await saveLock(ctx.lockPath, ctx.lock)\n\n return result\n },\n })\n}\n","import type { Orphan } from \"../pipeline/salvage.ts\"\n\nconst escapeHtml = (s: string) =>\n s.replace(/[&<>\"']/g, (c) => ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\", \"'\": \"&#39;\" })[c]!)\n\nexport interface SalvageSheetContext {\n /** The style every \"import\" on this page will be tagged and routed under. */\n styleId: string\n /** Where an import lands, shown so the page answers \"where does this go\"\n * without anyone needing to go check the manifest. */\n importDir: string\n}\n\n/**\n * Triage sheet for unclaimed account objects.\n *\n * Optimised for volume: a couple of hundred items, most of which get a\n * one-keystroke verdict. Everything defaults to no decision, so closing the tab\n * changes nothing, and `discard` only ever writes a tag — deletion is a\n * separate command that has to be asked for by name.\n *\n * `salvage` opens one tab per matched style in sequence (grouping — see\n * pipeline/salvage.ts), and every one of them used to render the exact same\n * generic title. With several left open across styles there was no way to\n * tell them apart short of squinting at which images loaded. The tab title\n * and header now name the style the page is actually scoped to.\n */\nexport function renderSalvageSheet(orphans: Orphan[], ctx?: SalvageSheetContext): string {\n const safe = orphans.map((o) => ({ ...o, prompt: escapeHtml(o.prompt) }))\n const data = JSON.stringify(safe).replace(/<\\//g, \"<\\\\/\")\n const styleId = ctx ? escapeHtml(ctx.styleId) : null\n const importDir = ctx ? escapeHtml(ctx.importDir) : null\n\n return `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>pixelkiln salvage${styleId ? ` — ${styleId}` : \"\"}</title>\n<style>\n :root { --bg:#0f1115; --panel:#171a21; --line:#262b36; --text:#e6e8ee; --dim:#8b93a7;\n --import:#6ee7a8; --keep:#7cc4ff; --discard:#f87171; }\n @media (prefers-color-scheme: light) {\n :root { --bg:#f6f7f9; --panel:#fff; --line:#dfe3ea; --text:#1a1d23; --dim:#666e80;\n --import:#0a8f52; --keep:#1a6fd4; --discard:#c0392b; }\n }\n * { box-sizing:border-box; }\n body { margin:0; background:var(--bg); color:var(--text);\n font:14px/1.5 ui-sans-serif,-apple-system,\"SF Pro Text\",Inter,system-ui,sans-serif; }\n header { position:sticky; top:0; z-index:10; background:var(--panel);\n border-bottom:1px solid var(--line); padding:12px 20px; display:flex; gap:14px;\n align-items:center; flex-wrap:wrap; }\n h1 { font-size:15px; margin:0; font-weight:600; }\n h1 .ctx { font-weight:500; color:var(--dim); }\n h1 .dest { font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:12.5px; }\n .tally { color:var(--dim); font-variant-numeric:tabular-nums; }\n .tally b { color:var(--text); font-weight:600; }\n button { font:inherit; font-weight:550; border-radius:7px; padding:7px 14px;\n border:1px solid var(--line); background:transparent; color:var(--text); cursor:pointer; }\n button.primary { background:var(--import); border-color:var(--import); color:#08130d; }\n button:disabled { opacity:.45; cursor:not-allowed; }\n main { display:grid; grid-template-columns:repeat(auto-fill,minmax(190px,1fr)); gap:12px; padding:18px 20px 80px; }\n .card { border:2px solid var(--line); border-radius:10px; background:var(--panel);\n padding:10px; display:flex; flex-direction:column; gap:8px; }\n .card.import { border-color:var(--import); }\n .card.keep { border-color:var(--keep); }\n .card.discard { border-color:var(--discard); opacity:.5; }\n .thumb { height:120px; display:flex; align-items:center; justify-content:center;\n border-radius:6px;\n background-image:\n linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%),\n linear-gradient(45deg,#0000 25%,#7f7f7f22 25%,#7f7f7f22 75%,#0000 75%);\n background-size:12px 12px; background-position:0 0,6px 6px; }\n .thumb img { image-rendering:pixelated; max-height:112px; max-width:100%; }\n .meta { font-size:11px; color:var(--dim); font-variant-numeric:tabular-nums; }\n .prompt { font-size:11.5px; color:var(--dim); max-height:3.2em; overflow:hidden; }\n .acts { display:flex; gap:5px; }\n .acts button { flex:1; padding:5px 0; font-size:11.5px; }\n .acts button.on-import { background:var(--import); border-color:var(--import); color:#08130d; }\n .acts button.on-keep { background:var(--keep); border-color:var(--keep); color:#04121f; }\n .acts button.on-discard { background:var(--discard); border-color:var(--discard); color:#fff; }\n footer { position:fixed; bottom:0; left:0; right:0; background:var(--panel);\n border-top:1px solid var(--line); padding:10px 20px; font-size:12px; color:var(--dim); }\n kbd { border:1px solid var(--line); border-bottom-width:2px; border-radius:4px;\n padding:1px 5px; font-size:11px; font-family:ui-monospace,Menlo,monospace; }\n</style>\n</head>\n<body>\n<header>\n <h1>pixelkiln salvage${\n styleId\n ? ` <span class=\"ctx\">— ${styleId}<span class=\"dest\"> → ${importDir}/_salvaged/</span></span>`\n : \"\"\n }</h1>\n <span class=\"tally\"><b id=\"ti\">0</b> import · <b id=\"tk\">0</b> keep · <b id=\"td\">0</b> discard ·\n <b id=\"tu\">0</b> undecided</span>\n <span style=\"flex:1\"></span>\n <button id=\"allDiscard\">Discard all undecided</button>\n <button id=\"allKeep\">Keep all undecided</button>\n <button id=\"submit\" class=\"primary\" disabled>Apply</button>\n</header>\n<main id=\"grid\"></main>\n<footer>\n <b>import</b> downloads it and adds it to your manifest · <b>keep</b> tags it and leaves it ·\n <b>discard</b> only tags it — nothing is deleted here.\n Hover a card and press <kbd>i</kbd> / <kbd>k</kbd> / <kbd>d</kbd>, or <kbd>u</kbd> to undo.\n</footer>\n<script>\nconst ITEMS = ${data};\nconst picks = new Map();\nconst grid = document.getElementById('grid');\nlet hovered = null;\n\nITEMS.forEach((o, i) => {\n const el = document.createElement('div');\n el.className = 'card';\n el.dataset.i = String(i);\n el.innerHTML =\n '<div class=\"thumb\"><img src=\"' + o.previewUrl + '\" loading=\"lazy\"></div>' +\n '<div class=\"meta\">' + o.width + '×' + o.height + ' · ' + o.createdAt.slice(0,10) + '</div>' +\n '<div class=\"prompt\">' + o.prompt + '</div>' +\n '<div class=\"acts\">' +\n '<button data-a=\"import\">import</button>' +\n '<button data-a=\"keep\">keep</button>' +\n '<button data-a=\"discard\">discard</button>' +\n '</div>';\n el.querySelectorAll('.acts button').forEach(b => {\n b.onclick = () => choose(i, b.dataset.a);\n });\n el.onmouseenter = () => { hovered = i; };\n grid.appendChild(el);\n});\n\nfunction choose(i, action) {\n if (picks.get(i) === action) picks.delete(i); else picks.set(i, action);\n const el = grid.children[i];\n el.className = 'card' + (picks.has(i) ? ' ' + picks.get(i) : '');\n el.querySelectorAll('.acts button').forEach(b => {\n b.className = picks.get(i) === b.dataset.a ? 'on-' + b.dataset.a : '';\n });\n refresh();\n}\n\nfunction refresh() {\n const c = { import: 0, keep: 0, discard: 0 };\n for (const a of picks.values()) c[a]++;\n ti.textContent = c.import; tk.textContent = c.keep; td.textContent = c.discard;\n tu.textContent = ITEMS.length - picks.size;\n document.getElementById('submit').disabled = picks.size === 0;\n}\n\ndocument.addEventListener('keydown', e => {\n if (hovered === null) return;\n const map = { i: 'import', k: 'keep', d: 'discard' };\n if (map[e.key]) { choose(hovered, map[e.key]); e.preventDefault(); }\n else if (e.key === 'u') { picks.delete(hovered); choose(hovered, '__none__'); }\n});\n\ndocument.getElementById('allKeep').onclick = () => {\n ITEMS.forEach((_, i) => { if (!picks.has(i)) choose(i, 'keep'); });\n};\ndocument.getElementById('allDiscard').onclick = () => {\n ITEMS.forEach((_, i) => { if (!picks.has(i)) choose(i, 'discard'); });\n};\n\ndocument.getElementById('submit').onclick = async () => {\n const btn = document.getElementById('submit');\n btn.disabled = true; btn.textContent = 'applying…';\n const decisions = [...picks.entries()].map(([i, action]) => ({ id: ITEMS[i].id, action }));\n try {\n const res = await fetch('/apply', {\n method: 'POST', headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ decisions }),\n });\n if (!res.ok) throw new Error(await res.text());\n btn.textContent = 'done — close this tab';\n document.body.style.opacity = '.6';\n } catch (err) {\n btn.textContent = 'failed: ' + err.message; btn.disabled = false;\n }\n};\nrefresh();\n</script>\n</body>\n</html>`\n}\n","import path from \"node:path\"\nimport { existsSync } from \"node:fs\"\nimport { readdir, readFile } from \"node:fs/promises\"\nimport { fileURLToPath } from \"node:url\"\nimport { z } from \"zod\"\nimport { writeArtifactBundle } from \"./artifacts.ts\"\nimport { sha256, sha256File } from \"./hash.ts\"\nimport { StyleSchema, type Style } from \"./types.ts\"\n\nconst SHA256_RE = /^[0-9a-f]{64}$/\nconst RECIPE_ID_RE = /^[a-z0-9][a-z0-9-]*\\/[a-z0-9][a-z0-9-]*$/\nconst VERSION_RE = /^\\d+\\.\\d+\\.\\d+$/\nconst RECIPE_FILE = \"pixelkiln.recipe.json\"\nconst RECIPE_DIR_TOKEN = \"{{recipeDir}}\"\n\nconst PortablePathSchema = z.string().min(1).refine((value) => {\n if (value.includes(\"\\\\\") || path.posix.isAbsolute(value)) return false\n const parts = value.split(\"/\")\n return !parts.includes(\"\") && !parts.includes(\".\") && !parts.includes(\"..\")\n}, \"expected a portable relative path without '.', '..', or backslashes\")\n\nconst RecipeBindingSchema = z.object({\n nodeId: z.string().min(1),\n input: z.string().min(1),\n}).strict()\n\nexport const RecipeSchema = z.object({\n $schema: z.string().url().optional(),\n format: z.literal(\"pixelkiln-recipe\"),\n schemaVersion: z.literal(1),\n id: z.string().regex(RECIPE_ID_RE, \"expected provider/name\"),\n version: z.string().regex(VERSION_RE, \"expected x.y.z\"),\n provider: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),\n summary: z.string().min(1).max(240),\n files: z.array(z.object({\n path: PortablePathSchema,\n role: z.enum([\"workflow\", \"reference\"]),\n sha256: z.string().regex(SHA256_RE),\n }).strict()).default([]),\n models: z.array(z.object({\n path: PortablePathSchema,\n sha256: z.string().regex(SHA256_RE),\n source: z.string().url(),\n license: z.string().min(1),\n }).strict()).default([]),\n styleId: z.string().regex(/^[a-z0-9][a-z0-9-]*$/),\n style: StyleSchema,\n workflow: z.object({\n path: PortablePathSchema,\n outputNodeId: z.string().min(1),\n numImages: z.number().int().min(1).max(16),\n bindings: z.object({\n prompt: RecipeBindingSchema,\n width: RecipeBindingSchema.optional(),\n height: RecipeBindingSchema.optional(),\n batchSize: RecipeBindingSchema.optional(),\n seed: RecipeBindingSchema.optional(),\n sourceImage: RecipeBindingSchema.optional(),\n maskImage: RecipeBindingSchema.optional(),\n strength: RecipeBindingSchema.optional(),\n }).strict(),\n }).strict().optional(),\n quality: z.object({\n stage: z.enum([\"composition-source\", \"production-candidate\"]),\n workingCanvas: z.object({\n width: z.number().int().min(16),\n height: z.number().int().min(16),\n }).strict(),\n recommendedNativeSize: z.object({\n min: z.number().int().min(1),\n max: z.number().int().min(1),\n }).strict(),\n paletteColors: z.object({\n min: z.number().int().min(1),\n max: z.number().int().min(1),\n }).strict(),\n background: z.enum([\"opaque\", \"transparent\", \"full-bleed\"]),\n checks: z.array(z.enum([\n \"prompt-coverage\",\n \"native-grid\",\n \"final-palette\",\n \"alpha-edge\",\n \"human-1x\",\n ])).min(1),\n notes: z.array(z.string().min(1)).default([]),\n }).strict(),\n integrity: z.object({\n algorithm: z.literal(\"sha256\"),\n digest: z.string().regex(SHA256_RE),\n }).strict(),\n}).strict().superRefine((recipe, context) => {\n if (recipe.style.provider && recipe.style.provider !== recipe.provider) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"style\", \"provider\"],\n message: \"must match the recipe provider\",\n })\n }\n const filePaths = recipe.files.map((file) => file.path)\n if (new Set(filePaths).size !== filePaths.length) {\n context.addIssue({ code: z.ZodIssueCode.custom, path: [\"files\"], message: \"duplicate file path\" })\n }\n const modelPaths = recipe.models.map((model) => model.path)\n if (new Set(modelPaths).size !== modelPaths.length) {\n context.addIssue({ code: z.ZodIssueCode.custom, path: [\"models\"], message: \"duplicate model path\" })\n }\n if (filePaths.includes(RECIPE_FILE)) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"files\"],\n message: `${RECIPE_FILE} cannot hash itself`,\n })\n }\n if (recipe.quality.recommendedNativeSize.min > recipe.quality.recommendedNativeSize.max) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"quality\", \"recommendedNativeSize\"],\n message: \"min cannot exceed max\",\n })\n }\n if (recipe.quality.paletteColors.min > recipe.quality.paletteColors.max) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"quality\", \"paletteColors\"],\n message: \"min cannot exceed max\",\n })\n }\n if (recipe.workflow && !recipe.files.some(\n (file) => file.path === recipe.workflow!.path && file.role === \"workflow\",\n )) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"workflow\", \"path\"],\n message: \"must name a file whose role is workflow\",\n })\n }\n if (recipe.provider === \"comfyui\") {\n if (!recipe.workflow) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"workflow\"],\n message: \"ComfyUI recipes require workflow metadata\",\n })\n return\n }\n const options = recipe.style.providerOptions.comfyui\n if (!options || typeof options !== \"object\" || Array.isArray(options)) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"style\", \"providerOptions\", \"comfyui\"],\n message: \"ComfyUI recipes require ComfyUI provider options\",\n })\n return\n }\n const expected = {\n workflowFile: `${RECIPE_DIR_TOKEN}/${recipe.workflow.path}`,\n outputNodeId: recipe.workflow.outputNodeId,\n numImages: recipe.workflow.numImages,\n bindings: recipe.workflow.bindings,\n }\n if (JSON.stringify(canonical(options)) !== JSON.stringify(canonical(expected))) {\n context.addIssue({\n code: z.ZodIssueCode.custom,\n path: [\"style\", \"providerOptions\", \"comfyui\"],\n message: \"must match workflow metadata and use {{recipeDir}} for workflowFile\",\n })\n }\n }\n})\n\nexport type Recipe = z.infer<typeof RecipeSchema>\n\nexport interface LoadedRecipe {\n recipe: Recipe\n path: string\n dir: string\n bundled: boolean\n}\n\nexport interface RecipeFileVerification {\n path: string\n expectedSha256: string\n actualSha256: string | null\n status: \"ok\" | \"missing\" | \"mismatch\"\n}\n\nexport interface RecipeModelVerification {\n path: string\n expectedSha256: string\n actualSha256: string | null\n source: string\n license: string\n status: RecipeFileVerification[\"status\"] | \"unchecked\"\n}\n\nexport interface RecipeVerification {\n version: 1\n ok: boolean\n recipe: {\n id: string\n version: string\n path: string\n bundled: boolean\n }\n integrity: {\n expectedSha256: string\n actualSha256: string\n status: \"ok\" | \"mismatch\"\n }\n files: RecipeFileVerification[]\n models: RecipeModelVerification[]\n modelRoot: string | null\n}\n\nexport interface InstallRecipeOptions {\n out?: string\n force?: boolean\n cwd?: string\n bundledRoot?: string\n}\n\nexport interface InstallRecipeResult {\n recipe: Recipe\n destination: string\n changed: string[]\n unchanged: string[]\n styleId: string\n style: Style\n}\n\nfunction canonical(value: unknown): unknown {\n if (value === null || typeof value === \"string\" || typeof value === \"boolean\") return value\n if (typeof value === \"number\") {\n if (!Number.isFinite(value)) throw new Error(\"Recipe numbers must be finite.\")\n return value\n }\n if (Array.isArray(value)) return value.map(canonical)\n if (typeof value === \"object\") {\n const sorted: Record<string, unknown> = {}\n for (const key of Object.keys(value).sort()) {\n const item = (value as Record<string, unknown>)[key]\n if (item !== undefined) sorted[key] = canonical(item)\n }\n return sorted\n }\n throw new Error(`Recipe metadata cannot contain ${typeof value} values.`)\n}\n\nexport function recipeDigest(recipe: Recipe): string {\n const { integrity: _integrity, ...payload } = recipe\n return sha256(JSON.stringify(canonical(payload)))\n}\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nasync function readRecipeFile(recipePath: string, bundled: boolean): Promise<LoadedRecipe> {\n const absolute = path.resolve(recipePath)\n let raw: unknown\n try {\n raw = JSON.parse(await readFile(absolute, \"utf8\"))\n } catch (error) {\n throw new Error(`Could not read recipe ${absolute}: ${message(error)}`, { cause: error })\n }\n const parsed = RecipeSchema.safeParse(raw)\n if (!parsed.success) {\n throw new Error(\n `Invalid recipe ${absolute}:\\n` +\n parsed.error.issues.map((issue) => ` ${issue.path.join(\".\") || \"$\"}: ${issue.message}`).join(\"\\n\"),\n )\n }\n return { recipe: parsed.data, path: absolute, dir: path.dirname(absolute), bundled }\n}\n\nasync function walkRecipeFiles(root: string): Promise<string[]> {\n if (!existsSync(root)) return []\n const out: string[] = []\n for (const entry of await readdir(root, { withFileTypes: true })) {\n const resolved = path.join(root, entry.name)\n if (entry.isDirectory()) out.push(...await walkRecipeFiles(resolved))\n else if (entry.isFile() && entry.name === RECIPE_FILE) out.push(resolved)\n }\n return out\n}\n\nexport function bundledRecipeRoot(): string {\n return fileURLToPath(new URL(\"../recipes/\", import.meta.url))\n}\n\nexport async function listBundledRecipes(root = bundledRecipeRoot()): Promise<LoadedRecipe[]> {\n const recipes = await Promise.all(\n (await walkRecipeFiles(path.resolve(root))).map((file) => readRecipeFile(file, true)),\n )\n return recipes.sort((a, b) =>\n a.recipe.id.localeCompare(b.recipe.id) || compareVersions(b.recipe.version, a.recipe.version),\n )\n}\n\nfunction compareVersions(a: string, b: string): number {\n const av = a.split(\".\").map(Number)\n const bv = b.split(\".\").map(Number)\n for (let i = 0; i < 3; i++) {\n const difference = av[i]! - bv[i]!\n if (difference) return difference\n }\n return 0\n}\n\nfunction parseSelector(selector: string): { id: string; version?: string } {\n const match = selector.match(/^([^@]+?)(?:@(\\d+\\.\\d+\\.\\d+))?$/)\n if (!match || !RECIPE_ID_RE.test(match[1]!)) {\n throw new Error(`Invalid recipe selector \"${selector}\". Expected provider/name or provider/name@x.y.z.`)\n }\n return { id: match[1]!, version: match[2] }\n}\n\nexport async function resolveRecipe(\n target: string,\n bundledRoot = bundledRecipeRoot(),\n): Promise<LoadedRecipe> {\n const local = path.resolve(target)\n if (existsSync(local)) {\n const recipePath = path.basename(local) === RECIPE_FILE ? local : path.join(local, RECIPE_FILE)\n return readRecipeFile(recipePath, false)\n }\n if (target.startsWith(\".\") || target.startsWith(\"/\") || target.includes(\"\\\\\")) {\n throw new Error(`Recipe path not found: ${local}`)\n }\n const selector = parseSelector(target)\n const matches = (await listBundledRecipes(bundledRoot)).filter((entry) =>\n entry.recipe.id === selector.id &&\n (selector.version === undefined || entry.recipe.version === selector.version),\n )\n if (!matches.length) throw new Error(`Bundled recipe not found: ${target}`)\n return matches[0]!\n}\n\nasync function verifyFile(root: string, file: { path: string; sha256: string }): Promise<RecipeFileVerification> {\n const absolute = path.resolve(root, ...file.path.split(\"/\"))\n if (!existsSync(absolute)) {\n return { path: file.path, expectedSha256: file.sha256, actualSha256: null, status: \"missing\" }\n }\n const actualSha256 = await sha256File(absolute)\n return {\n path: file.path,\n expectedSha256: file.sha256,\n actualSha256,\n status: actualSha256 === file.sha256 ? \"ok\" : \"mismatch\",\n }\n}\n\nexport async function verifyRecipe(\n target: string,\n options: { modelRoot?: string; bundledRoot?: string } = {},\n): Promise<RecipeVerification> {\n const loaded = await resolveRecipe(target, options.bundledRoot)\n const actualIntegrity = recipeDigest(loaded.recipe)\n const files = await Promise.all(loaded.recipe.files.map((file) => verifyFile(loaded.dir, file)))\n const modelRoot = options.modelRoot ? path.resolve(options.modelRoot) : null\n const models: RecipeModelVerification[] = modelRoot\n ? await Promise.all(loaded.recipe.models.map(async (model) => ({\n ...await verifyFile(modelRoot, model),\n source: model.source,\n license: model.license,\n })))\n : loaded.recipe.models.map((model) => ({\n path: model.path,\n expectedSha256: model.sha256,\n actualSha256: null,\n source: model.source,\n license: model.license,\n status: \"unchecked\",\n }))\n const integrityStatus = actualIntegrity === loaded.recipe.integrity.digest ? \"ok\" : \"mismatch\"\n return {\n version: 1,\n ok:\n integrityStatus === \"ok\" &&\n files.every((file) => file.status === \"ok\") &&\n (!modelRoot || models.every((model) => model.status === \"ok\")),\n recipe: {\n id: loaded.recipe.id,\n version: loaded.recipe.version,\n path: loaded.path,\n bundled: loaded.bundled,\n },\n integrity: {\n expectedSha256: loaded.recipe.integrity.digest,\n actualSha256: actualIntegrity,\n status: integrityStatus,\n },\n files,\n models,\n modelRoot,\n }\n}\n\nfunction renderStyle(style: Style, destination: string, cwd: string): Style {\n const portableDir = path.relative(cwd, destination).split(path.sep).join(\"/\") || \".\"\n const replace = (value: unknown): unknown => {\n if (typeof value === \"string\") return value.replaceAll(RECIPE_DIR_TOKEN, portableDir)\n if (Array.isArray(value)) return value.map(replace)\n if (value && typeof value === \"object\") {\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, replace(item)]))\n }\n return value\n }\n return replace(style) as Style\n}\n\nexport async function installRecipe(\n target: string,\n options: InstallRecipeOptions = {},\n): Promise<InstallRecipeResult> {\n const cwd = path.resolve(options.cwd ?? process.cwd())\n const loaded = await resolveRecipe(target, options.bundledRoot)\n const verification = await verifyRecipe(loaded.path)\n if (!verification.ok) {\n throw new Error(`Recipe ${loaded.recipe.id}@${loaded.recipe.version} failed integrity verification.`)\n }\n const destination = options.out\n ? path.resolve(cwd, options.out)\n : path.join(cwd, \"pixelkiln-recipes\", ...loaded.recipe.id.split(\"/\"), loaded.recipe.version)\n const sources = [\n { path: RECIPE_FILE, source: loaded.path },\n ...loaded.recipe.files.map((file) => ({ path: file.path, source: path.join(loaded.dir, ...file.path.split(\"/\")) })),\n ]\n const files = await Promise.all(sources.map(async (file) => ({\n path: path.join(destination, ...file.path.split(\"/\")),\n data: await readFile(file.source),\n })))\n\n if (!options.force) {\n for (const file of files) {\n if (!existsSync(file.path)) continue\n const current = await readFile(file.path)\n if (!current.equals(file.data)) {\n throw new Error(\n `Recipe destination has local changes: ${file.path}. Choose another --out or pass --force to replace declared recipe files.`,\n )\n }\n }\n }\n\n const written = await writeArtifactBundle(files)\n const renderedStyle = renderStyle(loaded.recipe.style, destination, cwd)\n return {\n recipe: loaded.recipe,\n destination,\n changed: written.changed,\n unchanged: written.unchanged,\n styleId: loaded.recipe.styleId,\n // A recipe snippet should remain correct when pasted into a manifest whose\n // top-level default is another provider.\n style: { ...renderedStyle, provider: renderedStyle.provider ?? loaded.recipe.provider },\n }\n}\n","import path from \"node:path\"\nimport { existsSync } from \"node:fs\"\nimport { readFile } from \"node:fs/promises\"\nimport { z } from \"zod\"\nimport {\n readArtifactBundleManifest,\n verifyArtifactBundle,\n writeArtifactBundle,\n} from \"../artifacts.ts\"\nimport { sha256, sha256File } from \"../hash.ts\"\nimport { decodePng, type DecodedPng } from \"../png.ts\"\nimport { colorDistance } from \"./audit.ts\"\n\nconst SHA256_RE = /^[0-9a-f]{64}$/\nconst HEX_RE = /^#[0-9a-f]{6}$/\nconst MAX_REDMEAN_DISTANCE = 765\n\nconst QualityPathSchema = z.string().min(1).refine(\n (value) => !path.posix.isAbsolute(value) && !value.includes(\"\\\\\"),\n \"expected a portable relative path\",\n)\n\nexport const DEFAULT_QUALITY_TOLERANCES = {\n requireExactHash: false,\n maxColorCountIncrease: 0,\n maxNewColors: 0,\n maxTransparencyDelta: 0.01,\n maxPartialAlphaIncrease: 0,\n maxEdgeDensityDelta: 0.03,\n maxEdgeContrastDrop: 0.03,\n maxIsolatedPixelIncrease: 0.005,\n} as const\n\nexport const QualityToleranceSchema = z.object({\n requireExactHash: z.boolean(),\n maxColorCountIncrease: z.number().int().min(0),\n maxNewColors: z.number().int().min(0),\n maxTransparencyDelta: z.number().min(0).max(1),\n maxPartialAlphaIncrease: z.number().min(0).max(1),\n maxEdgeDensityDelta: z.number().min(0).max(1),\n maxEdgeContrastDrop: z.number().min(0).max(1),\n maxIsolatedPixelIncrease: z.number().min(0).max(1),\n}).strict()\n\nexport type QualityTolerances = z.infer<typeof QualityToleranceSchema>\n\nexport const ImageQualityMetricsSchema = z.object({\n sha256: z.string().regex(SHA256_RE),\n width: z.number().int().min(1),\n height: z.number().int().min(1),\n colorCount: z.number().int().min(0),\n colors: z.array(z.string().regex(HEX_RE)),\n transparency: z.number().min(0).max(1),\n partialAlpha: z.number().min(0).max(1),\n edgeDensity: z.number().min(0).max(1),\n meanEdgeContrast: z.number().min(0).max(1),\n isolatedPixelRatio: z.number().min(0).max(1),\n}).strict()\n\nexport type ImageQualityMetrics = z.infer<typeof ImageQualityMetricsSchema>\n\nconst QualityBaselineCaseSchema = z.object({\n id: z.string().regex(/^[a-z0-9][a-z0-9/_-]*$/),\n file: QualityPathSchema,\n record: z.object({\n path: QualityPathSchema,\n sha256: z.string().regex(SHA256_RE),\n }).strict().optional(),\n expected: ImageQualityMetricsSchema,\n tolerances: QualityToleranceSchema,\n}).strict()\n\nexport const QualityBaselineSchema = z.object({\n $schema: z.string().url().optional(),\n format: z.literal(\"pixelkiln-quality-baseline\"),\n schemaVersion: z.literal(1),\n cases: z.array(QualityBaselineCaseSchema).min(1),\n}).strict().superRefine((baseline, context) => {\n const ids = baseline.cases.map((entry) => entry.id)\n if (new Set(ids).size !== ids.length) {\n context.addIssue({ code: z.ZodIssueCode.custom, path: [\"cases\"], message: \"duplicate case id\" })\n }\n})\n\nexport type QualityBaseline = z.infer<typeof QualityBaselineSchema>\n\nconst QualityInputSchema = z.object({\n id: z.string().regex(/^[a-z0-9][a-z0-9/_-]*$/),\n path: z.string().min(1),\n record: z.string().min(1).optional(),\n tolerances: QualityToleranceSchema.partial().optional(),\n}).strict()\n\nexport interface ResolvedQualityInput {\n id: string\n file: string\n record?: string\n tolerances: QualityTolerances\n}\n\nexport interface QualitySnapshotResult {\n baseline: QualityBaseline\n path: string\n changed: boolean\n}\n\nexport interface QualityRegressionCaseResult {\n id: string\n file: string\n status: \"pass\" | \"fail\"\n hashChanged: boolean\n expected: ImageQualityMetrics\n actual: ImageQualityMetrics | null\n violations: string[]\n warnings: string[]\n}\n\nexport interface QualityRegressionReport {\n version: 1\n safe: boolean\n baseline: string\n summary: {\n total: number\n passed: number\n failed: number\n changed: number\n }\n cases: QualityRegressionCaseResult[]\n}\n\nfunction message(error: unknown): string {\n return error instanceof Error ? error.message : String(error)\n}\n\nfunction round(value: number): number {\n return Number(value.toFixed(6))\n}\n\nfunction pixelKey(pixels: Buffer, offset: number): number {\n const alpha = pixels[offset + 3]!\n if (alpha === 0) return 0\n return (\n ((pixels[offset]! << 24) >>> 0) |\n (pixels[offset + 1]! << 16) |\n (pixels[offset + 2]! << 8) |\n alpha\n ) >>> 0\n}\n\nfunction edgeContrast(pixels: Buffer, a: number, b: number): number {\n const alphaA = pixels[a + 3]!\n const alphaB = pixels[b + 3]!\n const alphaDistance = Math.abs(alphaA - alphaB) / 255\n if (alphaA === 0 || alphaB === 0) return alphaDistance\n const rgbDistance = colorDistance(\n { r: pixels[a]!, g: pixels[a + 1]!, b: pixels[a + 2]! },\n { r: pixels[b]!, g: pixels[b + 1]!, b: pixels[b + 2]! },\n ) / MAX_REDMEAN_DISTANCE\n return Math.min(1, Math.max(alphaDistance, rgbDistance))\n}\n\nexport function measureDecodedImageQuality(\n png: DecodedPng,\n digest: string,\n): ImageQualityMetrics {\n const colors = new Set<number>()\n let transparent = 0\n let partialAlpha = 0\n let visible = 0\n let isolated = 0\n\n for (let offset = 0; offset < png.pixels.length; offset += 4) {\n const alpha = png.pixels[offset + 3]!\n if (alpha === 0) {\n transparent++\n continue\n }\n visible++\n if (alpha < 255) partialAlpha++\n colors.add((png.pixels[offset]! << 16) | (png.pixels[offset + 1]! << 8) | png.pixels[offset + 2]!)\n\n const index = offset / 4\n const x = index % png.width\n const y = Math.floor(index / png.width)\n const key = pixelKey(png.pixels, offset)\n const hasSameNeighbor =\n (x > 0 && pixelKey(png.pixels, offset - 4) === key) ||\n (x + 1 < png.width && pixelKey(png.pixels, offset + 4) === key) ||\n (y > 0 && pixelKey(png.pixels, offset - png.width * 4) === key) ||\n (y + 1 < png.height && pixelKey(png.pixels, offset + png.width * 4) === key)\n if (!hasSameNeighbor) {\n isolated++\n }\n }\n\n let neighborPairs = 0\n let changedPairs = 0\n let contrastTotal = 0\n for (let y = 0; y < png.height; y++) {\n for (let x = 0; x < png.width; x++) {\n const offset = (y * png.width + x) * 4\n if (x + 1 < png.width) {\n const neighbor = offset + 4\n neighborPairs++\n if (pixelKey(png.pixels, offset) !== pixelKey(png.pixels, neighbor)) {\n changedPairs++\n contrastTotal += edgeContrast(png.pixels, offset, neighbor)\n }\n }\n if (y + 1 < png.height) {\n const neighbor = offset + png.width * 4\n neighborPairs++\n if (pixelKey(png.pixels, offset) !== pixelKey(png.pixels, neighbor)) {\n changedPairs++\n contrastTotal += edgeContrast(png.pixels, offset, neighbor)\n }\n }\n }\n }\n\n const total = png.width * png.height\n return {\n sha256: digest,\n width: png.width,\n height: png.height,\n colorCount: colors.size,\n colors: [...colors]\n .sort((a, b) => a - b)\n .map((color) => `#${color.toString(16).padStart(6, \"0\")}`),\n transparency: round(total ? transparent / total : 0),\n partialAlpha: round(total ? partialAlpha / total : 0),\n edgeDensity: round(neighborPairs ? changedPairs / neighborPairs : 0),\n meanEdgeContrast: round(changedPairs ? contrastTotal / changedPairs : 0),\n isolatedPixelRatio: round(visible ? isolated / visible : 0),\n }\n}\n\nexport async function measureImageQuality(file: string): Promise<ImageQualityMetrics> {\n const absolute = path.resolve(file)\n let bytes: Buffer\n try {\n bytes = await readFile(absolute)\n } catch (error) {\n throw new Error(`Cannot read quality image ${absolute}: ${message(error)}`, { cause: error })\n }\n try {\n return measureDecodedImageQuality(decodePng(bytes), sha256(bytes))\n } catch (error) {\n throw new Error(`Cannot measure quality image ${absolute}: ${message(error)}`, { cause: error })\n }\n}\n\nexport function resolveQualityInputs(raw: unknown, inputsFilePath: string): ResolvedQualityInput[] {\n const parsed = z.array(QualityInputSchema).min(1).safeParse(raw)\n if (!parsed.success) {\n throw new Error(\n \"--inputs must be a non-empty JSON array of quality cases:\\n\" +\n parsed.error.issues.map((issue) => ` ${issue.path.join(\".\") || \"$\"}: ${issue.message}`).join(\"\\n\"),\n )\n }\n const ids = parsed.data.map((entry) => entry.id)\n if (new Set(ids).size !== ids.length) throw new Error(\"--inputs contains a duplicate quality case id.\")\n const root = path.dirname(path.resolve(inputsFilePath))\n return parsed.data.map((entry) => ({\n id: entry.id,\n file: path.resolve(root, entry.path),\n ...(entry.record ? { record: path.resolve(root, entry.record) } : {}),\n tolerances: QualityToleranceSchema.parse({\n ...DEFAULT_QUALITY_TOLERANCES,\n ...entry.tolerances,\n }),\n }))\n}\n\nfunction portableRelative(from: string, to: string): string {\n return path.relative(from, path.resolve(to)).split(path.sep).join(\"/\") || \".\"\n}\n\nasync function verifyRecordForImage(recordPath: string, imagePath: string): Promise<void> {\n const verification = await verifyArtifactBundle(recordPath)\n if (!verification.current) {\n const changed = [...verification.changedSources, ...verification.changedOutputs]\n throw new Error(\n `Quality record is not current: ${recordPath}` +\n (changed.length ? ` (${changed.join(\", \")})` : \"\"),\n )\n }\n const record = await readArtifactBundleManifest(recordPath)\n const options = record.options\n if (\n record.kind !== \"refine\" ||\n options === null ||\n typeof options !== \"object\" ||\n (options as { schema?: unknown }).schema !== \"pixelkiln-quality\"\n ) {\n throw new Error(`Quality record ${recordPath} is not a PixelKiln refinement record.`)\n }\n const outputs = record.outputs.map((output) => path.resolve(path.dirname(recordPath), output.path))\n if (!outputs.includes(path.resolve(imagePath))) {\n throw new Error(`Quality record ${recordPath} does not own ${imagePath}.`)\n }\n}\n\nexport async function snapshotQualityBaseline(\n inputs: ResolvedQualityInput[],\n baselinePath: string,\n options: { force?: boolean } = {},\n): Promise<QualitySnapshotResult> {\n if (!inputs.length) throw new Error(\"Cannot snapshot an empty quality baseline.\")\n const absolute = path.resolve(baselinePath)\n for (const input of inputs) {\n if (\n path.resolve(input.file) === absolute ||\n (input.record && path.resolve(input.record) === absolute)\n ) {\n throw new Error(`Quality baseline output would overwrite an input: ${absolute}.`)\n }\n }\n const root = path.dirname(absolute)\n const cases = []\n for (const input of [...inputs].sort((a, b) => a.id.localeCompare(b.id))) {\n const expected = await measureImageQuality(input.file)\n let record: { path: string; sha256: string } | undefined\n if (input.record) {\n await verifyRecordForImage(input.record, input.file)\n record = {\n path: portableRelative(root, input.record),\n sha256: await sha256File(input.record),\n }\n }\n cases.push({\n id: input.id,\n file: portableRelative(root, input.file),\n ...(record ? { record } : {}),\n expected,\n tolerances: input.tolerances,\n })\n }\n const baseline = QualityBaselineSchema.parse({\n $schema: \"https://unpkg.com/pixelkiln/schema/quality-baseline.schema.json\",\n format: \"pixelkiln-quality-baseline\",\n schemaVersion: 1,\n cases,\n })\n const data = Buffer.from(JSON.stringify(baseline, null, 2) + \"\\n\")\n if (existsSync(absolute) && !options.force) {\n const current = await readFile(absolute)\n if (!current.equals(data)) {\n throw new Error(`Quality baseline already exists with different content: ${absolute}. Pass --force to replace it.`)\n }\n }\n const result = await writeArtifactBundle([{ path: absolute, data }])\n return { baseline, path: absolute, changed: result.changed.length > 0 }\n}\n\nexport async function readQualityBaseline(baselinePath: string): Promise<QualityBaseline> {\n const absolute = path.resolve(baselinePath)\n let raw: unknown\n try {\n raw = JSON.parse(await readFile(absolute, \"utf8\"))\n } catch (error) {\n throw new Error(`Could not read quality baseline ${absolute}: ${message(error)}`, { cause: error })\n }\n const parsed = QualityBaselineSchema.safeParse(raw)\n if (!parsed.success) {\n throw new Error(\n `Invalid quality baseline ${absolute}:\\n` +\n parsed.error.issues.map((issue) => ` ${issue.path.join(\".\") || \"$\"}: ${issue.message}`).join(\"\\n\"),\n )\n }\n return parsed.data\n}\n\nfunction regressionViolations(\n expected: ImageQualityMetrics,\n actual: ImageQualityMetrics,\n tolerances: QualityTolerances,\n): { violations: string[]; warnings: string[] } {\n const violations: string[] = []\n const warnings: string[] = []\n const changed = actual.sha256 !== expected.sha256\n if (expected.width !== actual.width || expected.height !== actual.height) {\n violations.push(\n `dimensions changed from ${expected.width}x${expected.height} to ${actual.width}x${actual.height}`,\n )\n }\n if (changed && tolerances.requireExactHash) violations.push(\"image hash changed\")\n else if (changed) warnings.push(\"image hash changed; metric tolerances decide this case\")\n\n const colorIncrease = actual.colorCount - expected.colorCount\n if (colorIncrease > tolerances.maxColorCountIncrease) {\n violations.push(\n `color count increased by ${colorIncrease} (allowed ${tolerances.maxColorCountIncrease})`,\n )\n }\n const expectedColors = new Set(expected.colors)\n const newColors = actual.colors.filter((color) => !expectedColors.has(color))\n if (newColors.length > tolerances.maxNewColors) {\n violations.push(\n `${newColors.length} new color(s) exceed ${tolerances.maxNewColors}: ${newColors.slice(0, 8).join(\", \")}`,\n )\n }\n const transparencyDelta = Math.abs(actual.transparency - expected.transparency)\n if (transparencyDelta > tolerances.maxTransparencyDelta) {\n violations.push(\n `transparency changed by ${(transparencyDelta * 100).toFixed(2)} points ` +\n `(allowed ${(tolerances.maxTransparencyDelta * 100).toFixed(2)})`,\n )\n }\n const partialAlphaIncrease = actual.partialAlpha - expected.partialAlpha\n if (partialAlphaIncrease > tolerances.maxPartialAlphaIncrease) {\n violations.push(\n `partial-alpha pixels increased by ${(partialAlphaIncrease * 100).toFixed(2)} points ` +\n `(allowed ${(tolerances.maxPartialAlphaIncrease * 100).toFixed(2)})`,\n )\n }\n const edgeDensityDelta = Math.abs(actual.edgeDensity - expected.edgeDensity)\n if (edgeDensityDelta > tolerances.maxEdgeDensityDelta) {\n violations.push(\n `edge density changed by ${(edgeDensityDelta * 100).toFixed(2)} points ` +\n `(allowed ${(tolerances.maxEdgeDensityDelta * 100).toFixed(2)})`,\n )\n }\n const edgeContrastDrop = expected.meanEdgeContrast - actual.meanEdgeContrast\n if (edgeContrastDrop > tolerances.maxEdgeContrastDrop) {\n violations.push(\n `mean edge contrast dropped by ${(edgeContrastDrop * 100).toFixed(2)} points ` +\n `(allowed ${(tolerances.maxEdgeContrastDrop * 100).toFixed(2)})`,\n )\n }\n const isolatedIncrease = actual.isolatedPixelRatio - expected.isolatedPixelRatio\n if (isolatedIncrease > tolerances.maxIsolatedPixelIncrease) {\n violations.push(\n `isolated-pixel ratio increased by ${(isolatedIncrease * 100).toFixed(2)} points ` +\n `(allowed ${(tolerances.maxIsolatedPixelIncrease * 100).toFixed(2)})`,\n )\n }\n return { violations, warnings }\n}\n\nexport async function checkQualityBaseline(baselinePath: string): Promise<QualityRegressionReport> {\n const absolute = path.resolve(baselinePath)\n const baseline = await readQualityBaseline(absolute)\n const root = path.dirname(absolute)\n const cases: QualityRegressionCaseResult[] = []\n\n for (const entry of baseline.cases) {\n const file = path.resolve(root, entry.file)\n let actual: ImageQualityMetrics | null = null\n const violations: string[] = []\n const warnings: string[] = []\n try {\n actual = await measureImageQuality(file)\n const regression = regressionViolations(entry.expected, actual, entry.tolerances)\n violations.push(...regression.violations)\n warnings.push(...regression.warnings)\n } catch (error) {\n violations.push(message(error))\n }\n\n if (entry.record) {\n const recordPath = path.resolve(root, entry.record.path)\n try {\n const recordHash = await sha256File(recordPath)\n if (recordHash !== entry.record.sha256) violations.push(\"quality record hash changed\")\n await verifyRecordForImage(recordPath, file)\n } catch (error) {\n violations.push(message(error))\n }\n }\n\n cases.push({\n id: entry.id,\n file,\n status: violations.length ? \"fail\" : \"pass\",\n hashChanged: actual !== null && actual.sha256 !== entry.expected.sha256,\n expected: entry.expected,\n actual,\n violations,\n warnings,\n })\n }\n\n const failed = cases.filter((entry) => entry.status === \"fail\").length\n return {\n version: 1,\n safe: failed === 0,\n baseline: absolute,\n summary: {\n total: cases.length,\n passed: cases.length - failed,\n failed,\n changed: cases.filter((entry) => entry.hashChanged).length,\n },\n cases,\n }\n}\n"],"mappings":"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AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBA8GQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":["path","existsSync","readFile","path","path","chunk","hex","sha256","path","workflow","frameJob","images","promptId","history","entry","status","message","existsSync","readFileSync","randomUUID","path","message","path","z","path","randomUUID","res","existsSync","readFileSync","DEFAULT_BASE_URL","path","sourceRef","message","DEFAULT_BASE_URL","SOURCE_PROTOCOL","value","asset","message","mode","mode","readFile","existsSync","path","path","readFile","existsSync","path","existsSync","readFile","path","path","path","path","existsSync","readFile","readFileSync","path","path","readFileSync","inputs","packed","existsSync","path","existsSync","path","path","readFile","rm","path","createHash","randomUUID","mkdir","readFile","rename","rm","writeFile","canonical","remove","cleanupErrors","readFile","existsSync","path","existsSync","readFile","path","message","hex","path","readFile","rm","source","output","path","existsSync","existsSync","path","existsSync","path","existsSync","path","sleep","log","message","sleep","log","existsSync","mkdir","readFile","rename","rm","writeFile","path","log","path","existsSync","readFile","mkdir","writeFile","rename","message","rm","existsSync","stat","path","message","path","existsSync","stat","existsSync","readFile","writeFile","path","mkdir","readFile","rename","rm","writeFile","existsSync","z","path","log","existsSync","readFile","writeFile","readFile","log","chunk","message","log","readFile","writeFile","existsSync","path","readFile","existsSync","path","existsSync","readFile","log","path","existsSync","log","mkdir","readFile","rename","rm","writeFile","existsSync","path","z","existsSync","readFile","readdir","rm","path","existsSync","path","rm","readFile","readdir","isRecord","mkdir","writeFile","readFile","path","escapeHtml","PNG_SIGNATURE","log","path","mkdir","writeFile","readFile","path","existsSync","readdir","readFile","z","z","path","canonical","message","readFile","existsSync","readdir","path","existsSync","readFile","z","SHA256_RE","z","path","message","digest","readFile","portableRelative","existsSync","path","existsSync","amount","item","readFile","result","loaded","lock","providers","manifestDir"]}