@glasstrace/sdk 0.14.1 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/{chunk-ERGEG4ZQ.js → chunk-2LDBR3F3.js} +16 -3
  2. package/dist/chunk-2LDBR3F3.js.map +1 -0
  3. package/dist/chunk-A2AZL6MZ.js +309 -0
  4. package/dist/chunk-A2AZL6MZ.js.map +1 -0
  5. package/dist/{chunk-ARAOZCZT.js → chunk-ROFOJQWN.js} +118 -16
  6. package/dist/chunk-ROFOJQWN.js.map +1 -0
  7. package/dist/{chunk-WV3NIPWJ.js → chunk-ZNOD6FC7.js} +18 -276
  8. package/dist/chunk-ZNOD6FC7.js.map +1 -0
  9. package/dist/cli/init.cjs +458 -115
  10. package/dist/cli/init.cjs.map +1 -1
  11. package/dist/cli/init.d.cts +33 -1
  12. package/dist/cli/init.d.ts +33 -1
  13. package/dist/cli/init.js +144 -42
  14. package/dist/cli/init.js.map +1 -1
  15. package/dist/cli/mcp-add.cjs.map +1 -1
  16. package/dist/cli/mcp-add.js +4 -2
  17. package/dist/cli/mcp-add.js.map +1 -1
  18. package/dist/cli/uninit.cjs +181 -60
  19. package/dist/cli/uninit.cjs.map +1 -1
  20. package/dist/cli/uninit.d.cts +38 -8
  21. package/dist/cli/uninit.d.ts +38 -8
  22. package/dist/cli/uninit.js +6 -3
  23. package/dist/cli/validate.cjs +135 -0
  24. package/dist/cli/validate.cjs.map +1 -0
  25. package/dist/cli/validate.d.cts +60 -0
  26. package/dist/cli/validate.d.ts +60 -0
  27. package/dist/cli/validate.js +103 -0
  28. package/dist/cli/validate.js.map +1 -0
  29. package/dist/index.cjs +123 -47
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.d.cts +45 -5
  32. package/dist/index.d.ts +45 -5
  33. package/dist/index.js +109 -46
  34. package/dist/index.js.map +1 -1
  35. package/dist/{source-map-uploader-W6VPGY26.js → source-map-uploader-3GWUQDTS.js} +6 -2
  36. package/package.json +6 -4
  37. package/dist/chunk-ARAOZCZT.js.map +0 -1
  38. package/dist/chunk-ERGEG4ZQ.js.map +0 -1
  39. package/dist/chunk-WV3NIPWJ.js.map +0 -1
  40. /package/dist/{source-map-uploader-W6VPGY26.js.map → source-map-uploader-3GWUQDTS.js.map} +0 -0
@@ -1,3 +1,7 @@
1
+ import {
2
+ isDevApiKey,
3
+ readEnvLocalApiKey
4
+ } from "./chunk-A2AZL6MZ.js";
1
5
  import {
2
6
  NEXT_CONFIG_NAMES
3
7
  } from "./chunk-BL3YDC6V.js";
@@ -315,12 +319,75 @@ function processTomlMcpConfig(content) {
315
319
  }
316
320
  return { action: "removed-section", content: result + "\n" };
317
321
  }
322
+ function writeShutdownMarker(projectRoot) {
323
+ const dirPath = path.join(projectRoot, ".glasstrace");
324
+ if (!fs.existsSync(dirPath)) {
325
+ return false;
326
+ }
327
+ const markerPath = path.join(dirPath, "shutdown-requested");
328
+ const tmpPath = `${markerPath}.tmp`;
329
+ const body = JSON.stringify({ requestedAt: (/* @__PURE__ */ new Date()).toISOString() });
330
+ try {
331
+ fs.writeFileSync(tmpPath, body, { encoding: "utf-8", mode: 384 });
332
+ try {
333
+ fs.chmodSync(tmpPath, 384);
334
+ } catch {
335
+ }
336
+ fs.renameSync(tmpPath, markerPath);
337
+ return true;
338
+ } catch {
339
+ try {
340
+ fs.unlinkSync(tmpPath);
341
+ } catch {
342
+ }
343
+ return false;
344
+ }
345
+ }
346
+ async function defaultPrompt(question, defaultValue) {
347
+ if (!process.stdin.isTTY) return defaultValue;
348
+ const readline = await import("readline");
349
+ const rl = readline.createInterface({
350
+ input: process.stdin,
351
+ output: process.stdout
352
+ });
353
+ return new Promise((resolve) => {
354
+ const suffix = defaultValue ? " [Y/n] " : " [y/N] ";
355
+ rl.question(question + suffix, (answer) => {
356
+ rl.close();
357
+ const trimmed = answer.trim().toLowerCase();
358
+ if (trimmed === "") {
359
+ resolve(defaultValue);
360
+ return;
361
+ }
362
+ resolve(trimmed === "y" || trimmed === "yes");
363
+ });
364
+ });
365
+ }
318
366
  async function runUninit(options) {
319
367
  const { projectRoot, dryRun } = options;
368
+ const force = options.force === true;
369
+ const prompt = options.prompt ?? defaultPrompt;
320
370
  const summary = [];
321
371
  const warnings = [];
322
372
  const errors = [];
323
373
  const prefix = dryRun ? "[dry run] " : "";
374
+ try {
375
+ if (!dryRun) {
376
+ const markerWritten = writeShutdownMarker(projectRoot);
377
+ if (markerWritten) {
378
+ summary.push("Wrote .glasstrace/shutdown-requested marker");
379
+ }
380
+ } else {
381
+ const dirPath = path.join(projectRoot, ".glasstrace");
382
+ if (fs.existsSync(dirPath)) {
383
+ summary.push(`${prefix}Would write .glasstrace/shutdown-requested marker`);
384
+ }
385
+ }
386
+ } catch (err) {
387
+ warnings.push(
388
+ `Shutdown marker write failed: ${err instanceof Error ? err.message : String(err)}`
389
+ );
390
+ }
324
391
  try {
325
392
  let configHandled = false;
326
393
  for (const name of NEXT_CONFIG_NAMES) {
@@ -403,23 +470,57 @@ async function runUninit(options) {
403
470
  const envPath = path.join(projectRoot, ".env.local");
404
471
  if (fs.existsSync(envPath)) {
405
472
  const content = fs.readFileSync(envPath, "utf-8");
406
- const lines = content.split("\n");
407
- const filtered = lines.filter((line) => {
408
- const trimmed = line.trim();
409
- return !(/^\s*#?\s*GLASSTRACE_API_KEY\s*=/.test(trimmed) || /^\s*#?\s*GLASSTRACE_COVERAGE_MAP\s*=/.test(trimmed));
410
- });
411
- if (filtered.length !== lines.length) {
412
- const result = filtered.join("\n");
413
- if (result.trim().length === 0) {
414
- if (!dryRun) {
415
- fs.unlinkSync(envPath);
416
- }
417
- summary.push(`${prefix}Deleted .env.local (no remaining entries)`);
473
+ const existingKey = readEnvLocalApiKey(content);
474
+ const hasDevKey = isDevApiKey(existingKey);
475
+ let proceed = true;
476
+ let devKeyPath = "none";
477
+ if (hasDevKey) {
478
+ if (dryRun) {
479
+ devKeyPath = "dry-run-preview";
480
+ } else if (force) {
481
+ devKeyPath = "force-bypass";
418
482
  } else {
419
- if (!dryRun) {
420
- fs.writeFileSync(envPath, result, "utf-8");
483
+ const confirmed = await prompt(
484
+ ".env.local contains a claimed Glasstrace developer API key (gt_dev_...). Removing it will require you to re-authenticate. Continue?",
485
+ false
486
+ );
487
+ proceed = confirmed;
488
+ if (confirmed) devKeyPath = "interactive-confirmed";
489
+ }
490
+ }
491
+ if (!proceed) {
492
+ warnings.push(
493
+ "Preserved GLASSTRACE_API_KEY in .env.local (claimed dev key; re-run with --force to remove)"
494
+ );
495
+ } else {
496
+ const lines = content.split("\n");
497
+ const filtered = lines.filter((line) => {
498
+ const trimmed = line.trim();
499
+ return !(/^\s*#?\s*GLASSTRACE_API_KEY\s*=/.test(trimmed) || /^\s*#?\s*GLASSTRACE_COVERAGE_MAP\s*=/.test(trimmed));
500
+ });
501
+ if (filtered.length !== lines.length) {
502
+ const result = filtered.join("\n");
503
+ if (result.trim().length === 0) {
504
+ if (!dryRun) {
505
+ fs.unlinkSync(envPath);
506
+ }
507
+ summary.push(`${prefix}Deleted .env.local (no remaining entries)`);
508
+ } else {
509
+ if (!dryRun) {
510
+ fs.writeFileSync(envPath, result, "utf-8");
511
+ }
512
+ let devKeyAnnotation = "";
513
+ if (devKeyPath === "interactive-confirmed") {
514
+ devKeyAnnotation = " (dev key confirmed)";
515
+ } else if (devKeyPath === "force-bypass") {
516
+ devKeyAnnotation = " (dev key removed via --force)";
517
+ } else if (devKeyPath === "dry-run-preview") {
518
+ devKeyAnnotation = " (dev key would be removed; real run would require confirmation)";
519
+ }
520
+ summary.push(
521
+ `${prefix}Removed GLASSTRACE entries from .env.local${devKeyAnnotation}`
522
+ );
421
523
  }
422
- summary.push(`${prefix}Removed GLASSTRACE entries from .env.local`);
423
524
  }
424
525
  }
425
526
  }
@@ -579,6 +680,7 @@ export {
579
680
  removeMarkerSection,
580
681
  processJsonMcpConfig,
581
682
  processTomlMcpConfig,
683
+ writeShutdownMarker,
582
684
  runUninit
583
685
  };
584
- //# sourceMappingURL=chunk-ARAOZCZT.js.map
686
+ //# sourceMappingURL=chunk-ROFOJQWN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/uninit.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { NEXT_CONFIG_NAMES } from \"./constants.js\";\nimport { readEnvLocalApiKey, isDevApiKey } from \"./scaffolder.js\";\n\n/**\n * Options for the uninit command.\n */\nexport interface UninitOptions {\n projectRoot: string;\n dryRun: boolean;\n /**\n * When true, skip interactive confirmation before destructive actions\n * such as removing a claimed developer API key from `.env.local`\n * (DISC-1247 Scenario 6).\n */\n force?: boolean;\n /**\n * Optional prompt callback; when omitted, uninit uses a TTY-based\n * `readline` prompt in interactive mode and defaults to `false`\n * (abort) when no TTY is attached. Exposed for testing.\n */\n prompt?: (question: string, defaultValue: boolean) => Promise<boolean>;\n}\n\n/**\n * Result of running the uninit command.\n */\nexport interface UninitResult {\n exitCode: number;\n summary: string[];\n warnings: string[];\n errors: string[];\n}\n\n/**\n * MCP config files that init may create.\n * These are JSON files containing `mcpServers.glasstrace`.\n */\nconst MCP_CONFIG_FILES = [\".mcp.json\", \".cursor/mcp.json\", \".gemini/settings.json\"] as const;\n\n/**\n * Agent info files that may contain glasstrace marker sections.\n * Both HTML-style (`<!-- glasstrace:mcp:start -->`) and hash-style\n * (`# glasstrace:mcp:start`) markers are supported.\n */\nconst AGENT_INFO_FILES = [\n \"CLAUDE.md\",\n \"codex.md\",\n \".cursorrules\",\n] as const;\n\n/**\n * Advances past a string literal (double-quoted, single-quoted, or template\n * literal), respecting backslash escapes.\n *\n * Note: Template literals with `${...}` interpolations containing nested\n * backticks are not fully supported — the scanner stops at the first\n * unescaped backtick. This is acceptable because config files (the primary\n * use case for `findMatchingParen`/`findMatchingBrace`) do not use nested\n * template literals.\n *\n * @param text - The source text.\n * @param start - The index of the opening quote character.\n * @param quote - The quote character (`\"`, `'`, or `` ` ``).\n * @returns The index immediately after the closing quote.\n * @internal Exported for unit testing only.\n */\nexport function skipString(text: string, start: number, quote: string): number {\n let i = start + 1;\n while (i < text.length) {\n if (text[i] === \"\\\\\") {\n i += 2;\n continue;\n }\n if (text[i] === quote) {\n return i + 1;\n }\n i++;\n }\n return text.length;\n}\n\n/**\n * Finds the matching closing delimiter for an opening delimiter at the given\n * position, accounting for nesting and skipping delimiters that appear inside\n * string literals (`\"`, `'`, `` ` ``), single-line comments (`//`), and block\n * comments.\n *\n * @param text - The source text to search.\n * @param openPos - The index of the opening delimiter.\n * @param openChar - The opening delimiter character (e.g., `(` or `{`).\n * @param closeChar - The closing delimiter character (e.g., `)` or `}`).\n * @returns The index of the matching closing delimiter, or -1 if not found.\n * @internal Exported for unit testing only.\n */\nexport function findMatchingDelimiter(\n text: string,\n openPos: number,\n openChar: string,\n closeChar: string,\n): number {\n let depth = 0;\n let i = openPos;\n while (i < text.length) {\n const ch = text[i];\n\n // Skip string literals\n if (ch === '\"' || ch === \"'\" || ch === \"`\") {\n i = skipString(text, i, ch);\n continue;\n }\n\n // Skip single-line comments.\n // Note: This may misidentify regex literals containing `//` (e.g.,\n // `/api\\//`). Config files — the primary use case — do not contain\n // regex literals, so this trade-off is acceptable.\n if (ch === \"/\" && text[i + 1] === \"/\") {\n const newline = text.indexOf(\"\\n\", i);\n if (newline === -1) {\n return -1;\n }\n i = newline + 1;\n continue;\n }\n\n // Skip block comments\n if (ch === \"/\" && text[i + 1] === \"*\") {\n const end = text.indexOf(\"*/\", i + 2);\n if (end === -1) {\n return -1;\n }\n i = end + 2;\n continue;\n }\n\n if (ch === openChar) {\n depth++;\n } else if (ch === closeChar) {\n depth--;\n if (depth === 0) {\n return i;\n }\n }\n i++;\n }\n return -1;\n}\n\n/**\n * Finds the matching closing parenthesis for an opening paren at the given\n * position, accounting for nested parentheses and skipping delimiters inside\n * string literals and comments.\n *\n * @param text - The source text to search.\n * @param openPos - The index of the opening `(`.\n * @returns The index of the matching `)`, or -1 if not found.\n * @internal Exported for unit testing only.\n */\nexport function findMatchingParen(text: string, openPos: number): number {\n return findMatchingDelimiter(text, openPos, \"(\", \")\");\n}\n\n/**\n * Removes the `withGlasstraceConfig(...)` wrapper from an ESM default export,\n * restoring the inner expression.\n *\n * Before: `export default withGlasstraceConfig(innerExpr);`\n * After: `export default innerExpr;`\n *\n * @internal Exported for unit testing only.\n */\nexport function unwrapExport(content: string): { content: string; unwrapped: boolean } {\n const pattern = /export\\s+default\\s+withGlasstraceConfig\\s*\\(/;\n const match = pattern.exec(content);\n if (!match) {\n return { content, unwrapped: false };\n }\n\n // Find the opening paren of withGlasstraceConfig(\n const openParenIdx = match.index + match[0].length - 1;\n const closeParenIdx = findMatchingParen(content, openParenIdx);\n if (closeParenIdx === -1) {\n return { content, unwrapped: false };\n }\n\n const innerExpr = content.slice(openParenIdx + 1, closeParenIdx).trim();\n if (innerExpr.length === 0) {\n return { content, unwrapped: false };\n }\n\n // Everything before `export default ...`\n const before = content.slice(0, match.index);\n // Everything after the closing `)` (skip optional semicolon and trailing whitespace)\n const afterClose = content.slice(closeParenIdx + 1);\n const trailing = afterClose.replace(/^;?\\s*/, \"\");\n\n const result = before + `export default ${innerExpr};\\n` + trailing;\n\n return { content: result, unwrapped: true };\n}\n\n/**\n * Removes the `withGlasstraceConfig(...)` wrapper from a CJS module.exports,\n * restoring the inner expression.\n *\n * Before: `module.exports = withGlasstraceConfig(innerExpr);`\n * After: `module.exports = innerExpr;`\n *\n * @internal Exported for unit testing only.\n */\nexport function unwrapCJSExport(content: string): { content: string; unwrapped: boolean } {\n const pattern = /module\\.exports\\s*=\\s*withGlasstraceConfig\\s*\\(/;\n const match = pattern.exec(content);\n if (!match) {\n return { content, unwrapped: false };\n }\n\n const openParenIdx = match.index + match[0].length - 1;\n const closeParenIdx = findMatchingParen(content, openParenIdx);\n if (closeParenIdx === -1) {\n return { content, unwrapped: false };\n }\n\n const innerExpr = content.slice(openParenIdx + 1, closeParenIdx).trim();\n if (innerExpr.length === 0) {\n return { content, unwrapped: false };\n }\n\n const before = content.slice(0, match.index);\n const afterClose = content.slice(closeParenIdx + 1);\n const trailing = afterClose.replace(/^;?\\s*/, \"\");\n\n const result = before + `module.exports = ${innerExpr};\\n` + trailing;\n\n return { content: result, unwrapped: true };\n}\n\n/**\n * Removes the `import { withGlasstraceConfig } from \"@glasstrace/sdk\"` line\n * from file content. If `withGlasstraceConfig` is the only imported specifier,\n * the entire import line is removed. If other specifiers exist, only\n * `withGlasstraceConfig` is removed from the specifier list.\n *\n * @internal Exported for unit testing only.\n */\nexport function removeGlasstraceConfigImport(content: string): string {\n // ESM: import { withGlasstraceConfig } from \"@glasstrace/sdk\"\n const esmSoleImport =\n /import\\s*\\{\\s*withGlasstraceConfig\\s*\\}\\s*from\\s*[\"']@glasstrace\\/sdk[\"']\\s*;?\\s*\\n?/;\n if (esmSoleImport.test(content)) {\n return content.replace(esmSoleImport, \"\");\n }\n\n // ESM with multiple specifiers — remove withGlasstraceConfig from the list\n const esmMultiImport =\n /import\\s*\\{([^}]*)\\}\\s*from\\s*[\"']@glasstrace\\/sdk[\"']/;\n const multiMatch = esmMultiImport.exec(content);\n if (multiMatch) {\n const specifiers = multiMatch[1]\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\" && s !== \"withGlasstraceConfig\");\n if (specifiers.length === 0) {\n // All specifiers were withGlasstraceConfig — remove entire import\n return content.replace(\n /import\\s*\\{[^}]*\\}\\s*from\\s*[\"']@glasstrace\\/sdk[\"']\\s*;?\\s*\\n?/,\n \"\",\n );\n }\n const newImport = `import { ${specifiers.join(\", \")} } from \"@glasstrace/sdk\"`;\n return content.replace(multiMatch[0], newImport);\n }\n\n // CJS: const { withGlasstraceConfig } = require(\"@glasstrace/sdk\")\n const cjsSoleRequire =\n /const\\s*\\{\\s*withGlasstraceConfig\\s*\\}\\s*=\\s*require\\s*\\(\\s*[\"']@glasstrace\\/sdk[\"']\\s*\\)\\s*;?\\s*\\n?/;\n if (cjsSoleRequire.test(content)) {\n return content.replace(cjsSoleRequire, \"\");\n }\n\n // CJS with multiple specifiers\n const cjsMultiRequire =\n /const\\s*\\{([^}]*)\\}\\s*=\\s*require\\s*\\(\\s*[\"']@glasstrace\\/sdk[\"']\\s*\\)/;\n const cjsMultiMatch = cjsMultiRequire.exec(content);\n if (cjsMultiMatch) {\n const specifiers = cjsMultiMatch[1]\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\" && s !== \"withGlasstraceConfig\");\n if (specifiers.length === 0) {\n return content.replace(\n /const\\s*\\{[^}]*\\}\\s*=\\s*require\\s*\\(\\s*[\"']@glasstrace\\/sdk[\"']\\s*\\)\\s*;?\\s*\\n?/,\n \"\",\n );\n }\n const newRequire = `const { ${specifiers.join(\", \")} } = require(\"@glasstrace/sdk\")`;\n return content.replace(cjsMultiMatch[0], newRequire);\n }\n\n return content;\n}\n\n/**\n * Removes blank lines that appear consecutively (more than one empty line\n * in a row) at the top of a file, which can occur after removing import lines.\n */\nfunction cleanLeadingBlankLines(content: string): string {\n return content.replace(/^\\n{2,}/, \"\\n\");\n}\n\n/**\n * Determines whether an instrumentation.ts file was created by `glasstrace init`\n * (i.e., contains only the standard template with no user-added code).\n *\n * A file is considered init-created if:\n * - The only import from any package is `@glasstrace/sdk`\n * - The only meaningful statement in `register()` is `registerGlasstrace()`\n * - There are no other top-level statements, exports, or declarations outside\n * the register function (prevents deleting files where users added their own code)\n *\n * @internal Exported for unit testing only.\n */\nexport function isInitCreatedInstrumentation(content: string): boolean {\n const lines = content.split(\"\\n\");\n\n // Check that all imports are from @glasstrace/sdk\n const importLines = lines.filter(\n (l) => /^\\s*import\\s/.test(l) && !l.trim().startsWith(\"//\"),\n );\n const nonGlasstraceImports = importLines.filter(\n (l) => !l.includes(\"@glasstrace/sdk\"),\n );\n if (nonGlasstraceImports.length > 0) {\n return false;\n }\n\n // Check that the register() function body only contains registerGlasstrace()\n // and comments — no other meaningful statements\n const registerFnRegex = /export\\s+(?:async\\s+)?function\\s+register\\s*\\([^)]*\\)\\s*\\{/;\n const match = registerFnRegex.exec(content);\n if (!match) {\n // No register function — not a standard init template\n return false;\n }\n\n // Extract the function body\n const afterBrace = content.slice(match.index + match[0].length);\n const closingBraceIdx = findMatchingBrace(content, match.index + match[0].length - 1);\n if (closingBraceIdx === -1) {\n return false;\n }\n\n const body = afterBrace.slice(0, closingBraceIdx - (match.index + match[0].length));\n const bodyLines = body.split(\"\\n\");\n\n // Filter out comments and blank lines — only meaningful statements remain\n const statements = bodyLines.filter((l) => {\n const trimmed = l.trim();\n return trimmed !== \"\" && !trimmed.startsWith(\"//\");\n });\n\n // The only statement should be registerGlasstrace()\n if (statements.length !== 1) {\n return false;\n }\n if (!/^\\s*registerGlasstrace\\s*\\(\\s*\\)\\s*;?\\s*$/.test(statements[0])) {\n return false;\n }\n\n // Verify no other top-level code exists outside imports and the register function.\n // Extract everything that isn't an import line or inside the register() function.\n const beforeFn = content.slice(0, match.index);\n const afterFn = content.slice(closingBraceIdx + 1);\n\n const topLevelBefore = beforeFn.split(\"\\n\").filter((l) => {\n const trimmed = l.trim();\n return (\n trimmed !== \"\" &&\n !trimmed.startsWith(\"//\") &&\n !trimmed.startsWith(\"import \") &&\n !trimmed.startsWith(\"import{\")\n );\n });\n\n const topLevelAfter = afterFn.split(\"\\n\").filter((l) => {\n const trimmed = l.trim();\n return trimmed !== \"\" && !trimmed.startsWith(\"//\");\n });\n\n return topLevelBefore.length === 0 && topLevelAfter.length === 0;\n}\n\n/**\n * Finds the matching closing brace for an opening brace at the given position,\n * skipping delimiters inside string literals and comments.\n */\nfunction findMatchingBrace(text: string, openPos: number): number {\n return findMatchingDelimiter(text, openPos, \"{\", \"}\");\n}\n\n/**\n * Removes the `registerGlasstrace()` call and its `@glasstrace/sdk` import\n * from an instrumentation.ts file, preserving all other code.\n *\n * @internal Exported for unit testing only.\n */\nexport function removeRegisterGlasstrace(content: string): string {\n let result = content;\n\n // Remove all comment-block + registerGlasstrace() call pairs.\n // The init template creates a multi-line comment block before the call:\n // // Glasstrace must be registered before Prisma instrumentation\n // // to ensure all ORM spans are captured correctly.\n // // If you use @prisma/instrumentation, import it after this call.\n // registerGlasstrace();\n // Use global flag to handle multiple occurrences.\n result = result.replace(\n /[ \\t]*\\/\\/\\s*Glasstrace must be registered[^\\n]*\\n(?:[ \\t]*\\/\\/[^\\n]*\\n)*[ \\t]*registerGlasstrace\\s*\\(\\s*\\)\\s*;?\\s*\\n?/g,\n \"\",\n );\n\n // Remove any remaining standalone registerGlasstrace() calls (global)\n result = result.replace(\n /[ \\t]*registerGlasstrace\\s*\\(\\s*\\)\\s*;?\\s*\\n?/g,\n \"\",\n );\n\n // Remove the import line for registerGlasstrace from @glasstrace/sdk\n // If it's the sole import, remove the whole line\n const soleImportPattern =\n /import\\s*\\{\\s*registerGlasstrace\\s*\\}\\s*from\\s*[\"']@glasstrace\\/sdk[\"']\\s*;?\\s*\\n?/;\n if (soleImportPattern.test(result)) {\n result = result.replace(soleImportPattern, \"\");\n } else {\n // Multiple specifiers — remove only registerGlasstrace\n const multiImportPattern =\n /import\\s*\\{([^}]*)\\}\\s*from\\s*[\"']@glasstrace\\/sdk[\"']/;\n const multiMatch = multiImportPattern.exec(result);\n if (multiMatch) {\n const specifiers = multiMatch[1]\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => s !== \"\" && s !== \"registerGlasstrace\");\n if (specifiers.length === 0) {\n result = result.replace(\n /import\\s*\\{[^}]*\\}\\s*from\\s*[\"']@glasstrace\\/sdk[\"']\\s*;?\\s*\\n?/,\n \"\",\n );\n } else {\n const newImport = `import { ${specifiers.join(\", \")} } from \"@glasstrace/sdk\"`;\n result = result.replace(multiMatch[0], newImport);\n }\n }\n }\n\n return cleanLeadingBlankLines(result);\n}\n\n/**\n * Removes content between glasstrace marker comments from a file.\n * Supports both HTML markers (`<!-- glasstrace:mcp:start/end -->`) and\n * hash markers (`# glasstrace:mcp:start/end`).\n *\n * @internal Exported for unit testing only.\n */\nexport function removeMarkerSection(content: string): { content: string; removed: boolean } {\n const lines = content.split(\"\\n\");\n let startIdx = -1;\n let endIdx = -1;\n\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i].trim();\n if (\n trimmed === \"<!-- glasstrace:mcp:start -->\" ||\n trimmed === \"# glasstrace:mcp:start\"\n ) {\n startIdx = i;\n } else if (\n (trimmed === \"<!-- glasstrace:mcp:end -->\" ||\n trimmed === \"# glasstrace:mcp:end\") &&\n startIdx !== -1\n ) {\n endIdx = i;\n break;\n }\n }\n\n if (startIdx === -1 || endIdx === -1) {\n return { content, removed: false };\n }\n\n const before = lines.slice(0, startIdx);\n const after = lines.slice(endIdx + 1);\n\n // Remove trailing blank line that may have preceded the marker block\n while (before.length > 0 && before[before.length - 1].trim() === \"\") {\n before.pop();\n }\n\n const result = [...before, ...after].join(\"\\n\");\n // Ensure file ends with newline if it has content\n const trimmedResult = result.trimEnd();\n return {\n content: trimmedResult.length > 0 ? trimmedResult + \"\\n\" : \"\",\n removed: true,\n };\n}\n\n/**\n * Removes the `glasstrace` key from an MCP config JSON file's `mcpServers`\n * object. Only deletes the file when `mcpServers` is the sole top-level key\n * and `glasstrace` is the only server entry. When other top-level keys exist\n * (e.g., `$schema`, metadata), the `mcpServers` key is removed (if empty)\n * and the file is preserved.\n *\n * @returns `\"removed-key\"` if the key was removed (other data remains),\n * `\"deleted\"` if the file should be deleted (no other data),\n * or `\"skipped\"` if no glasstrace config was found.\n * @internal Exported for unit testing only.\n */\nexport function processJsonMcpConfig(content: string): {\n action: \"removed-key\" | \"deleted\" | \"skipped\";\n content?: string;\n} {\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(content) as Record<string, unknown>;\n } catch {\n return { action: \"skipped\" };\n }\n\n const mcpServers = parsed[\"mcpServers\"] as Record<string, unknown> | undefined;\n if (!mcpServers || typeof mcpServers !== \"object\" || !(\"glasstrace\" in mcpServers)) {\n return { action: \"skipped\" };\n }\n\n const remainingServers = Object.keys(mcpServers).filter((k) => k !== \"glasstrace\");\n const otherTopLevelKeys = Object.keys(parsed).filter((k) => k !== \"mcpServers\");\n\n if (remainingServers.length === 0 && otherTopLevelKeys.length === 0) {\n // mcpServers.glasstrace is the only data in the file — safe to delete\n return { action: \"deleted\" };\n }\n\n // Remove the glasstrace key, keep other servers\n const { glasstrace: _, ...rest } = mcpServers;\n // Suppress unused variable lint — the destructuring intentionally discards glasstrace\n void _;\n\n if (remainingServers.length > 0) {\n // Other servers remain — keep mcpServers with glasstrace removed\n parsed[\"mcpServers\"] = rest;\n } else {\n // No servers remain but other top-level keys exist — remove mcpServers entirely\n delete parsed[\"mcpServers\"];\n }\n\n return { action: \"removed-key\", content: JSON.stringify(parsed, null, 2) + \"\\n\" };\n}\n\n/**\n * Removes the `[mcp_servers.glasstrace]` section from a TOML config file.\n * Since TOML parsing without a dependency is complex, this uses a line-based\n * approach that handles the standard format written by init.\n *\n * @returns `\"removed-section\"` if the glasstrace section was removed,\n * `\"deleted\"` if the entire file should be deleted (only contained\n * glasstrace config), or `\"skipped\"` if no glasstrace config found.\n * @internal Exported for unit testing only.\n */\nexport function processTomlMcpConfig(content: string): {\n action: \"removed-section\" | \"deleted\" | \"skipped\";\n content?: string;\n} {\n if (!content.includes(\"[mcp_servers.glasstrace]\")) {\n return { action: \"skipped\" };\n }\n\n const lines = content.split(\"\\n\");\n const startIdx = lines.findIndex(\n (l) => l.trim() === \"[mcp_servers.glasstrace]\",\n );\n if (startIdx === -1) {\n return { action: \"skipped\" };\n }\n\n // Find the end of the glasstrace section: next section header or end of file\n let endIdx = lines.length;\n for (let i = startIdx + 1; i < lines.length; i++) {\n if (/^\\s*\\[/.test(lines[i])) {\n endIdx = i;\n break;\n }\n }\n\n // Remove the section and any trailing blank lines\n const before = lines.slice(0, startIdx);\n const after = lines.slice(endIdx);\n\n // Trim trailing blank lines from the before section\n while (before.length > 0 && before[before.length - 1].trim() === \"\") {\n before.pop();\n }\n\n const result = [...before, ...after].join(\"\\n\").trimEnd();\n\n // Check if there are any remaining sections\n if (result.trim().length === 0) {\n return { action: \"deleted\" };\n }\n\n return { action: \"removed-section\", content: result + \"\\n\" };\n}\n\n/**\n * Writes the `.glasstrace/shutdown-requested` marker file atomically so\n * that a running SDK heartbeat tick (or equivalent lifecycle hook) can\n * detect that uninit has been invoked and trigger shutdown (DISC-1247\n * Scenario 1).\n *\n * Uses write-temp + rename semantics so a mid-write crash cannot leave\n * a truncated marker that the running process might misread.\n *\n * Best-effort: if `.glasstrace/` does not exist or the write fails, the\n * marker is silently skipped — uninit's cleanup is not blocked by a\n * missing running process.\n *\n * @internal Exported for unit testing only.\n */\nexport function writeShutdownMarker(projectRoot: string): boolean {\n const dirPath = path.join(projectRoot, \".glasstrace\");\n if (!fs.existsSync(dirPath)) {\n // No .glasstrace/ directory means no running SDK state is tracked —\n // nothing to signal. The filesystem removal step will handle any\n // stray artifacts.\n return false;\n }\n const markerPath = path.join(dirPath, \"shutdown-requested\");\n const tmpPath = `${markerPath}.tmp`;\n const body = JSON.stringify({ requestedAt: new Date().toISOString() });\n try {\n fs.writeFileSync(tmpPath, body, { encoding: \"utf-8\", mode: 0o600 });\n try {\n fs.chmodSync(tmpPath, 0o600);\n } catch {\n // chmod may be unsupported on some filesystems; proceed with rename.\n }\n fs.renameSync(tmpPath, markerPath);\n return true;\n } catch {\n // Best-effort cleanup of the temp file; swallow errors so uninit\n // itself never fails because of a signal-side-channel write.\n try {\n fs.unlinkSync(tmpPath);\n } catch {\n // Ignore — the marker was best-effort to begin with.\n }\n return false;\n }\n}\n\n/**\n * Simple TTY prompt used when `UninitOptions.prompt` is not provided.\n * Returns `defaultValue` when stdin is not a TTY.\n */\nasync function defaultPrompt(question: string, defaultValue: boolean): Promise<boolean> {\n if (!process.stdin.isTTY) return defaultValue;\n const readline = await import(\"node:readline\");\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return new Promise<boolean>((resolve) => {\n const suffix = defaultValue ? \" [Y/n] \" : \" [y/N] \";\n rl.question(question + suffix, (answer) => {\n rl.close();\n const trimmed = answer.trim().toLowerCase();\n if (trimmed === \"\") {\n resolve(defaultValue);\n return;\n }\n resolve(trimmed === \"y\" || trimmed === \"yes\");\n });\n });\n}\n\n/**\n * Reverses every step of `glasstrace init`, cleanly removing all SDK artifacts\n * from a project.\n *\n * Steps (in order):\n * 1. Write `.glasstrace/shutdown-requested` marker so a running SDK can\n * drain and exit cleanly (DISC-1247 Scenario 1)\n * 2. Unwrap `withGlasstraceConfig` from next.config\n * 3. Remove `registerGlasstrace` from instrumentation.ts (or delete if init-created)\n * 4. Remove `.glasstrace/` directory\n * 5. Remove `GLASSTRACE_*` entries from `.env.local` (with dev-key confirmation)\n * 6. Remove `.glasstrace/` from `.gitignore`\n * 7. Remove MCP config entries\n * 8. Remove info sections from agent files\n *\n * @param options - Configuration for the uninit command.\n * @returns A structured result describing what actions were taken.\n */\nexport async function runUninit(options: UninitOptions): Promise<UninitResult> {\n const { projectRoot, dryRun } = options;\n const force = options.force === true;\n const prompt = options.prompt ?? defaultPrompt;\n const summary: string[] = [];\n const warnings: string[] = [];\n const errors: string[] = [];\n const prefix = dryRun ? \"[dry run] \" : \"\";\n\n // Step 0: Signal any running SDK to shut down via a marker file.\n // Placed first so the running process has maximum time to observe\n // the marker while the remaining cleanup steps execute.\n try {\n if (!dryRun) {\n const markerWritten = writeShutdownMarker(projectRoot);\n if (markerWritten) {\n summary.push(\"Wrote .glasstrace/shutdown-requested marker\");\n }\n } else {\n const dirPath = path.join(projectRoot, \".glasstrace\");\n if (fs.existsSync(dirPath)) {\n summary.push(`${prefix}Would write .glasstrace/shutdown-requested marker`);\n }\n }\n } catch (err) {\n // Marker is best-effort; failure is not an error for uninit.\n warnings.push(\n `Shutdown marker write failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Step 1: Unwrap withGlasstraceConfig from next.config\n try {\n let configHandled = false;\n for (const name of NEXT_CONFIG_NAMES) {\n const configPath = path.join(projectRoot, name);\n if (!fs.existsSync(configPath)) {\n continue;\n }\n\n const content = fs.readFileSync(configPath, \"utf-8\");\n if (!content.includes(\"withGlasstraceConfig\")) {\n continue;\n }\n\n const isESM = name.endsWith(\".ts\") || name.endsWith(\".mjs\");\n const unwrapResult = isESM\n ? unwrapExport(content)\n : unwrapCJSExport(content);\n\n if (unwrapResult.unwrapped) {\n const cleaned = removeGlasstraceConfigImport(unwrapResult.content);\n const final = cleanLeadingBlankLines(cleaned);\n if (!dryRun) {\n fs.writeFileSync(configPath, final, \"utf-8\");\n }\n summary.push(`${prefix}Unwrapped withGlasstraceConfig from ${name}`);\n configHandled = true;\n break;\n } else {\n warnings.push(\n `${name} contains withGlasstraceConfig but could not be automatically unwrapped. ` +\n \"Please remove withGlasstraceConfig() manually.\",\n );\n configHandled = true;\n break;\n }\n }\n if (!configHandled) {\n // No next.config with withGlasstraceConfig found — nothing to do\n }\n } catch (err) {\n errors.push(\n `Failed to process next.config: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Step 2: Remove registerGlasstrace from instrumentation.ts\n try {\n const instrPath = path.join(projectRoot, \"instrumentation.ts\");\n if (fs.existsSync(instrPath)) {\n const content = fs.readFileSync(instrPath, \"utf-8\");\n if (content.includes(\"registerGlasstrace\") || content.includes(\"@glasstrace/sdk\")) {\n if (isInitCreatedInstrumentation(content)) {\n if (!dryRun) {\n fs.unlinkSync(instrPath);\n }\n summary.push(`${prefix}Deleted instrumentation.ts (init-created)`);\n } else {\n const cleaned = removeRegisterGlasstrace(content);\n if (cleaned !== content) {\n if (!dryRun) {\n fs.writeFileSync(instrPath, cleaned, \"utf-8\");\n }\n summary.push(\n `${prefix}Removed registerGlasstrace() from instrumentation.ts`,\n );\n }\n }\n }\n }\n } catch (err) {\n errors.push(\n `Failed to process instrumentation.ts: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Step 3: Remove .glasstrace/ directory\n try {\n const glasstraceDir = path.join(projectRoot, \".glasstrace\");\n if (fs.existsSync(glasstraceDir)) {\n if (!dryRun) {\n fs.rmSync(glasstraceDir, { recursive: true, force: true });\n }\n summary.push(`${prefix}Removed .glasstrace/ directory`);\n }\n } catch (err) {\n errors.push(\n `Failed to remove .glasstrace/: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Step 4: Remove GLASSTRACE entries from .env.local\n // DISC-1247 Scenario 6: if the file contains a claimed developer key\n // (`gt_dev_*`), require explicit confirmation before removing it so\n // users don't silently lose authentication state during uninit.\n // `--force` bypasses the prompt.\n try {\n const envPath = path.join(projectRoot, \".env.local\");\n if (fs.existsSync(envPath)) {\n const content = fs.readFileSync(envPath, \"utf-8\");\n const existingKey = readEnvLocalApiKey(content);\n const hasDevKey = isDevApiKey(existingKey);\n\n // Track how the dev-key path is resolved so the summary reflects\n // what actually happened: prompt-confirmed, force-bypassed, or\n // preview-only. Using the literal \"(dev key confirmed)\" for all\n // three paths was misleading (Copilot review).\n let proceed = true;\n let devKeyPath: \"interactive-confirmed\" | \"force-bypass\" | \"dry-run-preview\" | \"none\" = \"none\";\n if (hasDevKey) {\n if (dryRun) {\n devKeyPath = \"dry-run-preview\";\n } else if (force) {\n devKeyPath = \"force-bypass\";\n } else {\n const confirmed = await prompt(\n \".env.local contains a claimed Glasstrace developer API key (gt_dev_...). \" +\n \"Removing it will require you to re-authenticate. Continue?\",\n false,\n );\n proceed = confirmed;\n if (confirmed) devKeyPath = \"interactive-confirmed\";\n }\n }\n\n if (!proceed) {\n warnings.push(\n \"Preserved GLASSTRACE_API_KEY in .env.local (claimed dev key; re-run with --force to remove)\",\n );\n } else {\n const lines = content.split(\"\\n\");\n const filtered = lines.filter((line) => {\n const trimmed = line.trim();\n // Match both commented and uncommented GLASSTRACE_ lines\n return !(\n /^\\s*#?\\s*GLASSTRACE_API_KEY\\s*=/.test(trimmed) ||\n /^\\s*#?\\s*GLASSTRACE_COVERAGE_MAP\\s*=/.test(trimmed)\n );\n });\n\n if (filtered.length !== lines.length) {\n const result = filtered.join(\"\\n\");\n // If the file is now empty (only newlines), don't write it\n if (result.trim().length === 0) {\n if (!dryRun) {\n fs.unlinkSync(envPath);\n }\n summary.push(`${prefix}Deleted .env.local (no remaining entries)`);\n } else {\n if (!dryRun) {\n fs.writeFileSync(envPath, result, \"utf-8\");\n }\n let devKeyAnnotation = \"\";\n if (devKeyPath === \"interactive-confirmed\") {\n devKeyAnnotation = \" (dev key confirmed)\";\n } else if (devKeyPath === \"force-bypass\") {\n devKeyAnnotation = \" (dev key removed via --force)\";\n } else if (devKeyPath === \"dry-run-preview\") {\n devKeyAnnotation =\n \" (dev key would be removed; real run would require confirmation)\";\n }\n summary.push(\n `${prefix}Removed GLASSTRACE entries from .env.local${devKeyAnnotation}`,\n );\n }\n }\n }\n }\n } catch (err) {\n errors.push(\n `Failed to process .env.local: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Step 5: Remove .glasstrace/ from .gitignore\n try {\n const gitignorePath = path.join(projectRoot, \".gitignore\");\n if (fs.existsSync(gitignorePath)) {\n const content = fs.readFileSync(gitignorePath, \"utf-8\");\n const lines = content.split(\"\\n\");\n\n // Remove lines that are exactly \".glasstrace/\" or MCP config file entries\n // added by init (e.g., \".mcp.json\", \".cursor/mcp.json\", \".gemini/settings.json\",\n // \".codex/config.toml\")\n const mcpGitignoreEntries = new Set([\n \".glasstrace/\",\n \".mcp.json\",\n \".cursor/mcp.json\",\n \".gemini/settings.json\",\n \".codex/config.toml\",\n ]);\n\n const filtered = lines.filter(\n (line) => !mcpGitignoreEntries.has(line.trim()),\n );\n\n if (filtered.length !== lines.length) {\n const result = filtered.join(\"\\n\");\n if (result.trim().length === 0) {\n if (!dryRun) {\n fs.unlinkSync(gitignorePath);\n }\n summary.push(`${prefix}Deleted .gitignore (no remaining entries)`);\n } else {\n if (!dryRun) {\n fs.writeFileSync(gitignorePath, result, \"utf-8\");\n }\n summary.push(`${prefix}Removed Glasstrace entries from .gitignore`);\n }\n }\n }\n } catch (err) {\n errors.push(\n `Failed to process .gitignore: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Step 6: Remove MCP config entries\n try {\n for (const configFile of MCP_CONFIG_FILES) {\n const configPath = path.join(projectRoot, configFile);\n if (!fs.existsSync(configPath)) {\n continue;\n }\n\n const content = fs.readFileSync(configPath, \"utf-8\");\n const result = processJsonMcpConfig(content);\n\n if (result.action === \"deleted\") {\n if (!dryRun) {\n fs.unlinkSync(configPath);\n }\n summary.push(`${prefix}Deleted ${configFile}`);\n } else if (result.action === \"removed-key\" && result.content !== undefined) {\n if (!dryRun) {\n fs.writeFileSync(configPath, result.content, \"utf-8\");\n }\n summary.push(`${prefix}Removed glasstrace from ${configFile}`);\n }\n }\n // Handle Codex TOML config separately\n const codexConfigPath = path.join(projectRoot, \".codex\", \"config.toml\");\n if (fs.existsSync(codexConfigPath)) {\n const content = fs.readFileSync(codexConfigPath, \"utf-8\");\n const tomlResult = processTomlMcpConfig(content);\n\n if (tomlResult.action === \"deleted\") {\n if (!dryRun) {\n fs.unlinkSync(codexConfigPath);\n }\n summary.push(`${prefix}Deleted .codex/config.toml`);\n } else if (tomlResult.action === \"removed-section\" && tomlResult.content !== undefined) {\n if (!dryRun) {\n fs.writeFileSync(codexConfigPath, tomlResult.content, \"utf-8\");\n }\n summary.push(`${prefix}Removed glasstrace from .codex/config.toml`);\n }\n }\n\n // Handle Windsurf global config at ~/.codeium/windsurf/mcp_config.json\n // Only process if the project has Windsurf markers, to avoid touching\n // global config for non-Windsurf projects\n const hasWindsurfMarkers =\n fs.existsSync(path.join(projectRoot, \".windsurfrules\")) ||\n fs.existsSync(path.join(projectRoot, \".windsurf\"));\n if (hasWindsurfMarkers) {\n const windsurfConfigPath = path.join(\n os.homedir(),\n \".codeium\",\n \"windsurf\",\n \"mcp_config.json\",\n );\n if (fs.existsSync(windsurfConfigPath)) {\n const content = fs.readFileSync(windsurfConfigPath, \"utf-8\");\n const windsurfResult = processJsonMcpConfig(content);\n\n // Display the path with ~ for the home directory to keep output\n // readable, but derive it from the actual path for accuracy.\n const home = os.homedir();\n const displayPath = windsurfConfigPath.startsWith(home)\n ? \"~\" + windsurfConfigPath.slice(home.length)\n : windsurfConfigPath;\n\n if (windsurfResult.action === \"deleted\") {\n if (!dryRun) {\n fs.unlinkSync(windsurfConfigPath);\n }\n summary.push(\n `${prefix}Deleted global Windsurf config (${displayPath})`,\n );\n } else if (\n windsurfResult.action === \"removed-key\" &&\n windsurfResult.content !== undefined\n ) {\n if (!dryRun) {\n fs.writeFileSync(windsurfConfigPath, windsurfResult.content, \"utf-8\");\n }\n summary.push(\n `${prefix}Removed glasstrace from global Windsurf config (${displayPath})`,\n );\n }\n }\n }\n } catch (err) {\n errors.push(\n `Failed to process MCP config: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n // Step 7: Remove info sections from agent files\n try {\n for (const infoFile of AGENT_INFO_FILES) {\n const filePath = path.join(projectRoot, infoFile);\n if (!fs.existsSync(filePath)) {\n continue;\n }\n\n const content = fs.readFileSync(filePath, \"utf-8\");\n const result = removeMarkerSection(content);\n\n if (result.removed) {\n if (result.content.trim().length === 0) {\n // File is now empty after removing the marker section —\n // only delete if the file was solely glasstrace content\n if (!dryRun) {\n fs.unlinkSync(filePath);\n }\n summary.push(`${prefix}Deleted ${infoFile} (only contained Glasstrace section)`);\n } else {\n if (!dryRun) {\n fs.writeFileSync(filePath, result.content, \"utf-8\");\n }\n summary.push(`${prefix}Removed Glasstrace section from ${infoFile}`);\n }\n }\n }\n } catch (err) {\n errors.push(\n `Failed to process agent info files: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n if (summary.length === 0 && errors.length === 0) {\n summary.push(\"No Glasstrace artifacts found — nothing to do.\");\n }\n\n return { exitCode: errors.length > 0 ? 1 : 0, summary, warnings, errors };\n}\n"],"mappings":";;;;;;;;;;;;AAAA;AAAA,YAAY,QAAQ;AACpB,YAAY,QAAQ;AACpB,YAAY,UAAU;AAsCtB,IAAM,mBAAmB,CAAC,aAAa,oBAAoB,uBAAuB;AAOlF,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AACF;AAkBO,SAAS,WAAW,MAAc,OAAe,OAAuB;AAC7E,MAAI,IAAI,QAAQ;AAChB,SAAO,IAAI,KAAK,QAAQ;AACtB,QAAI,KAAK,CAAC,MAAM,MAAM;AACpB,WAAK;AACL;AAAA,IACF;AACA,QAAI,KAAK,CAAC,MAAM,OAAO;AACrB,aAAO,IAAI;AAAA,IACb;AACA;AAAA,EACF;AACA,SAAO,KAAK;AACd;AAeO,SAAS,sBACd,MACA,SACA,UACA,WACQ;AACR,MAAI,QAAQ;AACZ,MAAI,IAAI;AACR,SAAO,IAAI,KAAK,QAAQ;AACtB,UAAM,KAAK,KAAK,CAAC;AAGjB,QAAI,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK;AAC1C,UAAI,WAAW,MAAM,GAAG,EAAE;AAC1B;AAAA,IACF;AAMA,QAAI,OAAO,OAAO,KAAK,IAAI,CAAC,MAAM,KAAK;AACrC,YAAM,UAAU,KAAK,QAAQ,MAAM,CAAC;AACpC,UAAI,YAAY,IAAI;AAClB,eAAO;AAAA,MACT;AACA,UAAI,UAAU;AACd;AAAA,IACF;AAGA,QAAI,OAAO,OAAO,KAAK,IAAI,CAAC,MAAM,KAAK;AACrC,YAAM,MAAM,KAAK,QAAQ,MAAM,IAAI,CAAC;AACpC,UAAI,QAAQ,IAAI;AACd,eAAO;AAAA,MACT;AACA,UAAI,MAAM;AACV;AAAA,IACF;AAEA,QAAI,OAAO,UAAU;AACnB;AAAA,IACF,WAAW,OAAO,WAAW;AAC3B;AACA,UAAI,UAAU,GAAG;AACf,eAAO;AAAA,MACT;AAAA,IACF;AACA;AAAA,EACF;AACA,SAAO;AACT;AAYO,SAAS,kBAAkB,MAAc,SAAyB;AACvE,SAAO,sBAAsB,MAAM,SAAS,KAAK,GAAG;AACtD;AAWO,SAAS,aAAa,SAA0D;AACrF,QAAM,UAAU;AAChB,QAAM,QAAQ,QAAQ,KAAK,OAAO;AAClC,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,SAAS,WAAW,MAAM;AAAA,EACrC;AAGA,QAAM,eAAe,MAAM,QAAQ,MAAM,CAAC,EAAE,SAAS;AACrD,QAAM,gBAAgB,kBAAkB,SAAS,YAAY;AAC7D,MAAI,kBAAkB,IAAI;AACxB,WAAO,EAAE,SAAS,WAAW,MAAM;AAAA,EACrC;AAEA,QAAM,YAAY,QAAQ,MAAM,eAAe,GAAG,aAAa,EAAE,KAAK;AACtE,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO,EAAE,SAAS,WAAW,MAAM;AAAA,EACrC;AAGA,QAAM,SAAS,QAAQ,MAAM,GAAG,MAAM,KAAK;AAE3C,QAAM,aAAa,QAAQ,MAAM,gBAAgB,CAAC;AAClD,QAAM,WAAW,WAAW,QAAQ,UAAU,EAAE;AAEhD,QAAM,SAAS,SAAS,kBAAkB,SAAS;AAAA,IAAQ;AAE3D,SAAO,EAAE,SAAS,QAAQ,WAAW,KAAK;AAC5C;AAWO,SAAS,gBAAgB,SAA0D;AACxF,QAAM,UAAU;AAChB,QAAM,QAAQ,QAAQ,KAAK,OAAO;AAClC,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,SAAS,WAAW,MAAM;AAAA,EACrC;AAEA,QAAM,eAAe,MAAM,QAAQ,MAAM,CAAC,EAAE,SAAS;AACrD,QAAM,gBAAgB,kBAAkB,SAAS,YAAY;AAC7D,MAAI,kBAAkB,IAAI;AACxB,WAAO,EAAE,SAAS,WAAW,MAAM;AAAA,EACrC;AAEA,QAAM,YAAY,QAAQ,MAAM,eAAe,GAAG,aAAa,EAAE,KAAK;AACtE,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO,EAAE,SAAS,WAAW,MAAM;AAAA,EACrC;AAEA,QAAM,SAAS,QAAQ,MAAM,GAAG,MAAM,KAAK;AAC3C,QAAM,aAAa,QAAQ,MAAM,gBAAgB,CAAC;AAClD,QAAM,WAAW,WAAW,QAAQ,UAAU,EAAE;AAEhD,QAAM,SAAS,SAAS,oBAAoB,SAAS;AAAA,IAAQ;AAE7D,SAAO,EAAE,SAAS,QAAQ,WAAW,KAAK;AAC5C;AAUO,SAAS,6BAA6B,SAAyB;AAEpE,QAAM,gBACJ;AACF,MAAI,cAAc,KAAK,OAAO,GAAG;AAC/B,WAAO,QAAQ,QAAQ,eAAe,EAAE;AAAA,EAC1C;AAGA,QAAM,iBACJ;AACF,QAAM,aAAa,eAAe,KAAK,OAAO;AAC9C,MAAI,YAAY;AACd,UAAM,aAAa,WAAW,CAAC,EAC5B,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,MAAM,MAAM,MAAM,sBAAsB;AACzD,QAAI,WAAW,WAAW,GAAG;AAE3B,aAAO,QAAQ;AAAA,QACb;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM,YAAY,YAAY,WAAW,KAAK,IAAI,CAAC;AACnD,WAAO,QAAQ,QAAQ,WAAW,CAAC,GAAG,SAAS;AAAA,EACjD;AAGA,QAAM,iBACJ;AACF,MAAI,eAAe,KAAK,OAAO,GAAG;AAChC,WAAO,QAAQ,QAAQ,gBAAgB,EAAE;AAAA,EAC3C;AAGA,QAAM,kBACJ;AACF,QAAM,gBAAgB,gBAAgB,KAAK,OAAO;AAClD,MAAI,eAAe;AACjB,UAAM,aAAa,cAAc,CAAC,EAC/B,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,MAAM,MAAM,MAAM,sBAAsB;AACzD,QAAI,WAAW,WAAW,GAAG;AAC3B,aAAO,QAAQ;AAAA,QACb;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,UAAM,aAAa,WAAW,WAAW,KAAK,IAAI,CAAC;AACnD,WAAO,QAAQ,QAAQ,cAAc,CAAC,GAAG,UAAU;AAAA,EACrD;AAEA,SAAO;AACT;AAMA,SAAS,uBAAuB,SAAyB;AACvD,SAAO,QAAQ,QAAQ,WAAW,IAAI;AACxC;AAcO,SAAS,6BAA6B,SAA0B;AACrE,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAGhC,QAAM,cAAc,MAAM;AAAA,IACxB,CAAC,MAAM,eAAe,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,WAAW,IAAI;AAAA,EAC5D;AACA,QAAM,uBAAuB,YAAY;AAAA,IACvC,CAAC,MAAM,CAAC,EAAE,SAAS,iBAAiB;AAAA,EACtC;AACA,MAAI,qBAAqB,SAAS,GAAG;AACnC,WAAO;AAAA,EACT;AAIA,QAAM,kBAAkB;AACxB,QAAM,QAAQ,gBAAgB,KAAK,OAAO;AAC1C,MAAI,CAAC,OAAO;AAEV,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,QAAQ,MAAM,MAAM,QAAQ,MAAM,CAAC,EAAE,MAAM;AAC9D,QAAM,kBAAkB,kBAAkB,SAAS,MAAM,QAAQ,MAAM,CAAC,EAAE,SAAS,CAAC;AACpF,MAAI,oBAAoB,IAAI;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,WAAW,MAAM,GAAG,mBAAmB,MAAM,QAAQ,MAAM,CAAC,EAAE,OAAO;AAClF,QAAM,YAAY,KAAK,MAAM,IAAI;AAGjC,QAAM,aAAa,UAAU,OAAO,CAAC,MAAM;AACzC,UAAM,UAAU,EAAE,KAAK;AACvB,WAAO,YAAY,MAAM,CAAC,QAAQ,WAAW,IAAI;AAAA,EACnD,CAAC;AAGD,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,MAAI,CAAC,4CAA4C,KAAK,WAAW,CAAC,CAAC,GAAG;AACpE,WAAO;AAAA,EACT;AAIA,QAAM,WAAW,QAAQ,MAAM,GAAG,MAAM,KAAK;AAC7C,QAAM,UAAU,QAAQ,MAAM,kBAAkB,CAAC;AAEjD,QAAM,iBAAiB,SAAS,MAAM,IAAI,EAAE,OAAO,CAAC,MAAM;AACxD,UAAM,UAAU,EAAE,KAAK;AACvB,WACE,YAAY,MACZ,CAAC,QAAQ,WAAW,IAAI,KACxB,CAAC,QAAQ,WAAW,SAAS,KAC7B,CAAC,QAAQ,WAAW,SAAS;AAAA,EAEjC,CAAC;AAED,QAAM,gBAAgB,QAAQ,MAAM,IAAI,EAAE,OAAO,CAAC,MAAM;AACtD,UAAM,UAAU,EAAE,KAAK;AACvB,WAAO,YAAY,MAAM,CAAC,QAAQ,WAAW,IAAI;AAAA,EACnD,CAAC;AAED,SAAO,eAAe,WAAW,KAAK,cAAc,WAAW;AACjE;AAMA,SAAS,kBAAkB,MAAc,SAAyB;AAChE,SAAO,sBAAsB,MAAM,SAAS,KAAK,GAAG;AACtD;AAQO,SAAS,yBAAyB,SAAyB;AAChE,MAAI,SAAS;AASb,WAAS,OAAO;AAAA,IACd;AAAA,IACA;AAAA,EACF;AAGA,WAAS,OAAO;AAAA,IACd;AAAA,IACA;AAAA,EACF;AAIA,QAAM,oBACJ;AACF,MAAI,kBAAkB,KAAK,MAAM,GAAG;AAClC,aAAS,OAAO,QAAQ,mBAAmB,EAAE;AAAA,EAC/C,OAAO;AAEL,UAAM,qBACJ;AACF,UAAM,aAAa,mBAAmB,KAAK,MAAM;AACjD,QAAI,YAAY;AACd,YAAM,aAAa,WAAW,CAAC,EAC5B,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,MAAM,MAAM,MAAM,oBAAoB;AACvD,UAAI,WAAW,WAAW,GAAG;AAC3B,iBAAS,OAAO;AAAA,UACd;AAAA,UACA;AAAA,QACF;AAAA,MACF,OAAO;AACL,cAAM,YAAY,YAAY,WAAW,KAAK,IAAI,CAAC;AACnD,iBAAS,OAAO,QAAQ,WAAW,CAAC,GAAG,SAAS;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAEA,SAAO,uBAAuB,MAAM;AACtC;AASO,SAAS,oBAAoB,SAAwD;AAC1F,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,MAAI,WAAW;AACf,MAAI,SAAS;AAEb,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,UAAU,MAAM,CAAC,EAAE,KAAK;AAC9B,QACE,YAAY,mCACZ,YAAY,0BACZ;AACA,iBAAW;AAAA,IACb,YACG,YAAY,iCACX,YAAY,2BACd,aAAa,IACb;AACA,eAAS;AACT;AAAA,IACF;AAAA,EACF;AAEA,MAAI,aAAa,MAAM,WAAW,IAAI;AACpC,WAAO,EAAE,SAAS,SAAS,MAAM;AAAA,EACnC;AAEA,QAAM,SAAS,MAAM,MAAM,GAAG,QAAQ;AACtC,QAAM,QAAQ,MAAM,MAAM,SAAS,CAAC;AAGpC,SAAO,OAAO,SAAS,KAAK,OAAO,OAAO,SAAS,CAAC,EAAE,KAAK,MAAM,IAAI;AACnE,WAAO,IAAI;AAAA,EACb;AAEA,QAAM,SAAS,CAAC,GAAG,QAAQ,GAAG,KAAK,EAAE,KAAK,IAAI;AAE9C,QAAM,gBAAgB,OAAO,QAAQ;AACrC,SAAO;AAAA,IACL,SAAS,cAAc,SAAS,IAAI,gBAAgB,OAAO;AAAA,IAC3D,SAAS;AAAA,EACX;AACF;AAcO,SAAS,qBAAqB,SAGnC;AACA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,OAAO;AAAA,EAC7B,QAAQ;AACN,WAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B;AAEA,QAAM,aAAa,OAAO,YAAY;AACtC,MAAI,CAAC,cAAc,OAAO,eAAe,YAAY,EAAE,gBAAgB,aAAa;AAClF,WAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B;AAEA,QAAM,mBAAmB,OAAO,KAAK,UAAU,EAAE,OAAO,CAAC,MAAM,MAAM,YAAY;AACjF,QAAM,oBAAoB,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,MAAM,MAAM,YAAY;AAE9E,MAAI,iBAAiB,WAAW,KAAK,kBAAkB,WAAW,GAAG;AAEnE,WAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B;AAGA,QAAM,EAAE,YAAY,GAAG,GAAG,KAAK,IAAI;AAEnC,OAAK;AAEL,MAAI,iBAAiB,SAAS,GAAG;AAE/B,WAAO,YAAY,IAAI;AAAA,EACzB,OAAO;AAEL,WAAO,OAAO,YAAY;AAAA,EAC5B;AAEA,SAAO,EAAE,QAAQ,eAAe,SAAS,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,KAAK;AAClF;AAYO,SAAS,qBAAqB,SAGnC;AACA,MAAI,CAAC,QAAQ,SAAS,0BAA0B,GAAG;AACjD,WAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B;AAEA,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,WAAW,MAAM;AAAA,IACrB,CAAC,MAAM,EAAE,KAAK,MAAM;AAAA,EACtB;AACA,MAAI,aAAa,IAAI;AACnB,WAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B;AAGA,MAAI,SAAS,MAAM;AACnB,WAAS,IAAI,WAAW,GAAG,IAAI,MAAM,QAAQ,KAAK;AAChD,QAAI,SAAS,KAAK,MAAM,CAAC,CAAC,GAAG;AAC3B,eAAS;AACT;AAAA,IACF;AAAA,EACF;AAGA,QAAM,SAAS,MAAM,MAAM,GAAG,QAAQ;AACtC,QAAM,QAAQ,MAAM,MAAM,MAAM;AAGhC,SAAO,OAAO,SAAS,KAAK,OAAO,OAAO,SAAS,CAAC,EAAE,KAAK,MAAM,IAAI;AACnE,WAAO,IAAI;AAAA,EACb;AAEA,QAAM,SAAS,CAAC,GAAG,QAAQ,GAAG,KAAK,EAAE,KAAK,IAAI,EAAE,QAAQ;AAGxD,MAAI,OAAO,KAAK,EAAE,WAAW,GAAG;AAC9B,WAAO,EAAE,QAAQ,UAAU;AAAA,EAC7B;AAEA,SAAO,EAAE,QAAQ,mBAAmB,SAAS,SAAS,KAAK;AAC7D;AAiBO,SAAS,oBAAoB,aAA8B;AAChE,QAAM,UAAe,UAAK,aAAa,aAAa;AACpD,MAAI,CAAI,cAAW,OAAO,GAAG;AAI3B,WAAO;AAAA,EACT;AACA,QAAM,aAAkB,UAAK,SAAS,oBAAoB;AAC1D,QAAM,UAAU,GAAG,UAAU;AAC7B,QAAM,OAAO,KAAK,UAAU,EAAE,cAAa,oBAAI,KAAK,GAAE,YAAY,EAAE,CAAC;AACrE,MAAI;AACF,IAAG,iBAAc,SAAS,MAAM,EAAE,UAAU,SAAS,MAAM,IAAM,CAAC;AAClE,QAAI;AACF,MAAG,aAAU,SAAS,GAAK;AAAA,IAC7B,QAAQ;AAAA,IAER;AACA,IAAG,cAAW,SAAS,UAAU;AACjC,WAAO;AAAA,EACT,QAAQ;AAGN,QAAI;AACF,MAAG,cAAW,OAAO;AAAA,IACvB,QAAQ;AAAA,IAER;AACA,WAAO;AAAA,EACT;AACF;AAMA,eAAe,cAAc,UAAkB,cAAyC;AACtF,MAAI,CAAC,QAAQ,MAAM,MAAO,QAAO;AACjC,QAAM,WAAW,MAAM,OAAO,UAAe;AAC7C,QAAM,KAAK,SAAS,gBAAgB;AAAA,IAClC,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ;AAAA,EAClB,CAAC;AACD,SAAO,IAAI,QAAiB,CAAC,YAAY;AACvC,UAAM,SAAS,eAAe,YAAY;AAC1C,OAAG,SAAS,WAAW,QAAQ,CAAC,WAAW;AACzC,SAAG,MAAM;AACT,YAAM,UAAU,OAAO,KAAK,EAAE,YAAY;AAC1C,UAAI,YAAY,IAAI;AAClB,gBAAQ,YAAY;AACpB;AAAA,MACF;AACA,cAAQ,YAAY,OAAO,YAAY,KAAK;AAAA,IAC9C,CAAC;AAAA,EACH,CAAC;AACH;AAoBA,eAAsB,UAAU,SAA+C;AAC7E,QAAM,EAAE,aAAa,OAAO,IAAI;AAChC,QAAM,QAAQ,QAAQ,UAAU;AAChC,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,UAAoB,CAAC;AAC3B,QAAM,WAAqB,CAAC;AAC5B,QAAM,SAAmB,CAAC;AAC1B,QAAM,SAAS,SAAS,eAAe;AAKvC,MAAI;AACF,QAAI,CAAC,QAAQ;AACX,YAAM,gBAAgB,oBAAoB,WAAW;AACrD,UAAI,eAAe;AACjB,gBAAQ,KAAK,6CAA6C;AAAA,MAC5D;AAAA,IACF,OAAO;AACL,YAAM,UAAe,UAAK,aAAa,aAAa;AACpD,UAAO,cAAW,OAAO,GAAG;AAC1B,gBAAQ,KAAK,GAAG,MAAM,mDAAmD;AAAA,MAC3E;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AAEZ,aAAS;AAAA,MACP,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACnF;AAAA,EACF;AAGA,MAAI;AACF,QAAI,gBAAgB;AACpB,eAAW,QAAQ,mBAAmB;AACpC,YAAM,aAAkB,UAAK,aAAa,IAAI;AAC9C,UAAI,CAAI,cAAW,UAAU,GAAG;AAC9B;AAAA,MACF;AAEA,YAAM,UAAa,gBAAa,YAAY,OAAO;AACnD,UAAI,CAAC,QAAQ,SAAS,sBAAsB,GAAG;AAC7C;AAAA,MACF;AAEA,YAAM,QAAQ,KAAK,SAAS,KAAK,KAAK,KAAK,SAAS,MAAM;AAC1D,YAAM,eAAe,QACjB,aAAa,OAAO,IACpB,gBAAgB,OAAO;AAE3B,UAAI,aAAa,WAAW;AAC1B,cAAM,UAAU,6BAA6B,aAAa,OAAO;AACjE,cAAM,QAAQ,uBAAuB,OAAO;AAC5C,YAAI,CAAC,QAAQ;AACX,UAAG,iBAAc,YAAY,OAAO,OAAO;AAAA,QAC7C;AACA,gBAAQ,KAAK,GAAG,MAAM,uCAAuC,IAAI,EAAE;AACnE,wBAAgB;AAChB;AAAA,MACF,OAAO;AACL,iBAAS;AAAA,UACP,GAAG,IAAI;AAAA,QAET;AACA,wBAAgB;AAChB;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,eAAe;AAAA,IAEpB;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,kCAAkC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACpF;AAAA,EACF;AAGA,MAAI;AACF,UAAM,YAAiB,UAAK,aAAa,oBAAoB;AAC7D,QAAO,cAAW,SAAS,GAAG;AAC5B,YAAM,UAAa,gBAAa,WAAW,OAAO;AAClD,UAAI,QAAQ,SAAS,oBAAoB,KAAK,QAAQ,SAAS,iBAAiB,GAAG;AACjF,YAAI,6BAA6B,OAAO,GAAG;AACzC,cAAI,CAAC,QAAQ;AACX,YAAG,cAAW,SAAS;AAAA,UACzB;AACA,kBAAQ,KAAK,GAAG,MAAM,2CAA2C;AAAA,QACnE,OAAO;AACL,gBAAM,UAAU,yBAAyB,OAAO;AAChD,cAAI,YAAY,SAAS;AACvB,gBAAI,CAAC,QAAQ;AACX,cAAG,iBAAc,WAAW,SAAS,OAAO;AAAA,YAC9C;AACA,oBAAQ;AAAA,cACN,GAAG,MAAM;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,yCAAyC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC3F;AAAA,EACF;AAGA,MAAI;AACF,UAAM,gBAAqB,UAAK,aAAa,aAAa;AAC1D,QAAO,cAAW,aAAa,GAAG;AAChC,UAAI,CAAC,QAAQ;AACX,QAAG,UAAO,eAAe,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MAC3D;AACA,cAAQ,KAAK,GAAG,MAAM,gCAAgC;AAAA,IACxD;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,kCAAkC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACpF;AAAA,EACF;AAOA,MAAI;AACF,UAAM,UAAe,UAAK,aAAa,YAAY;AACnD,QAAO,cAAW,OAAO,GAAG;AAC1B,YAAM,UAAa,gBAAa,SAAS,OAAO;AAChD,YAAM,cAAc,mBAAmB,OAAO;AAC9C,YAAM,YAAY,YAAY,WAAW;AAMzC,UAAI,UAAU;AACd,UAAI,aAAoF;AACxF,UAAI,WAAW;AACb,YAAI,QAAQ;AACV,uBAAa;AAAA,QACf,WAAW,OAAO;AAChB,uBAAa;AAAA,QACf,OAAO;AACL,gBAAM,YAAY,MAAM;AAAA,YACtB;AAAA,YAEA;AAAA,UACF;AACA,oBAAU;AACV,cAAI,UAAW,cAAa;AAAA,QAC9B;AAAA,MACF;AAEA,UAAI,CAAC,SAAS;AACZ,iBAAS;AAAA,UACP;AAAA,QACF;AAAA,MACF,OAAO;AACL,cAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,cAAM,WAAW,MAAM,OAAO,CAAC,SAAS;AACtC,gBAAM,UAAU,KAAK,KAAK;AAE1B,iBAAO,EACL,kCAAkC,KAAK,OAAO,KAC9C,uCAAuC,KAAK,OAAO;AAAA,QAEvD,CAAC;AAED,YAAI,SAAS,WAAW,MAAM,QAAQ;AACpC,gBAAM,SAAS,SAAS,KAAK,IAAI;AAEjC,cAAI,OAAO,KAAK,EAAE,WAAW,GAAG;AAC9B,gBAAI,CAAC,QAAQ;AACX,cAAG,cAAW,OAAO;AAAA,YACvB;AACA,oBAAQ,KAAK,GAAG,MAAM,2CAA2C;AAAA,UACnE,OAAO;AACL,gBAAI,CAAC,QAAQ;AACX,cAAG,iBAAc,SAAS,QAAQ,OAAO;AAAA,YAC3C;AACA,gBAAI,mBAAmB;AACvB,gBAAI,eAAe,yBAAyB;AAC1C,iCAAmB;AAAA,YACrB,WAAW,eAAe,gBAAgB;AACxC,iCAAmB;AAAA,YACrB,WAAW,eAAe,mBAAmB;AAC3C,iCACE;AAAA,YACJ;AACA,oBAAQ;AAAA,cACN,GAAG,MAAM,6CAA6C,gBAAgB;AAAA,YACxE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACnF;AAAA,EACF;AAGA,MAAI;AACF,UAAM,gBAAqB,UAAK,aAAa,YAAY;AACzD,QAAO,cAAW,aAAa,GAAG;AAChC,YAAM,UAAa,gBAAa,eAAe,OAAO;AACtD,YAAM,QAAQ,QAAQ,MAAM,IAAI;AAKhC,YAAM,sBAAsB,oBAAI,IAAI;AAAA,QAClC;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,WAAW,MAAM;AAAA,QACrB,CAAC,SAAS,CAAC,oBAAoB,IAAI,KAAK,KAAK,CAAC;AAAA,MAChD;AAEA,UAAI,SAAS,WAAW,MAAM,QAAQ;AACpC,cAAM,SAAS,SAAS,KAAK,IAAI;AACjC,YAAI,OAAO,KAAK,EAAE,WAAW,GAAG;AAC9B,cAAI,CAAC,QAAQ;AACX,YAAG,cAAW,aAAa;AAAA,UAC7B;AACA,kBAAQ,KAAK,GAAG,MAAM,2CAA2C;AAAA,QACnE,OAAO;AACL,cAAI,CAAC,QAAQ;AACX,YAAG,iBAAc,eAAe,QAAQ,OAAO;AAAA,UACjD;AACA,kBAAQ,KAAK,GAAG,MAAM,4CAA4C;AAAA,QACpE;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACnF;AAAA,EACF;AAGA,MAAI;AACF,eAAW,cAAc,kBAAkB;AACzC,YAAM,aAAkB,UAAK,aAAa,UAAU;AACpD,UAAI,CAAI,cAAW,UAAU,GAAG;AAC9B;AAAA,MACF;AAEA,YAAM,UAAa,gBAAa,YAAY,OAAO;AACnD,YAAM,SAAS,qBAAqB,OAAO;AAE3C,UAAI,OAAO,WAAW,WAAW;AAC/B,YAAI,CAAC,QAAQ;AACX,UAAG,cAAW,UAAU;AAAA,QAC1B;AACA,gBAAQ,KAAK,GAAG,MAAM,WAAW,UAAU,EAAE;AAAA,MAC/C,WAAW,OAAO,WAAW,iBAAiB,OAAO,YAAY,QAAW;AAC1E,YAAI,CAAC,QAAQ;AACX,UAAG,iBAAc,YAAY,OAAO,SAAS,OAAO;AAAA,QACtD;AACA,gBAAQ,KAAK,GAAG,MAAM,2BAA2B,UAAU,EAAE;AAAA,MAC/D;AAAA,IACF;AAEA,UAAM,kBAAuB,UAAK,aAAa,UAAU,aAAa;AACtE,QAAO,cAAW,eAAe,GAAG;AAClC,YAAM,UAAa,gBAAa,iBAAiB,OAAO;AACxD,YAAM,aAAa,qBAAqB,OAAO;AAE/C,UAAI,WAAW,WAAW,WAAW;AACnC,YAAI,CAAC,QAAQ;AACX,UAAG,cAAW,eAAe;AAAA,QAC/B;AACA,gBAAQ,KAAK,GAAG,MAAM,4BAA4B;AAAA,MACpD,WAAW,WAAW,WAAW,qBAAqB,WAAW,YAAY,QAAW;AACtF,YAAI,CAAC,QAAQ;AACX,UAAG,iBAAc,iBAAiB,WAAW,SAAS,OAAO;AAAA,QAC/D;AACA,gBAAQ,KAAK,GAAG,MAAM,4CAA4C;AAAA,MACpE;AAAA,IACF;AAKA,UAAM,qBACD,cAAgB,UAAK,aAAa,gBAAgB,CAAC,KACnD,cAAgB,UAAK,aAAa,WAAW,CAAC;AACnD,QAAI,oBAAoB;AACtB,YAAM,qBAA0B;AAAA,QAC3B,WAAQ;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,UAAO,cAAW,kBAAkB,GAAG;AACrC,cAAM,UAAa,gBAAa,oBAAoB,OAAO;AAC3D,cAAM,iBAAiB,qBAAqB,OAAO;AAInD,cAAM,OAAU,WAAQ;AACxB,cAAM,cAAc,mBAAmB,WAAW,IAAI,IAClD,MAAM,mBAAmB,MAAM,KAAK,MAAM,IAC1C;AAEJ,YAAI,eAAe,WAAW,WAAW;AACvC,cAAI,CAAC,QAAQ;AACX,YAAG,cAAW,kBAAkB;AAAA,UAClC;AACA,kBAAQ;AAAA,YACN,GAAG,MAAM,mCAAmC,WAAW;AAAA,UACzD;AAAA,QACF,WACE,eAAe,WAAW,iBAC1B,eAAe,YAAY,QAC3B;AACA,cAAI,CAAC,QAAQ;AACX,YAAG,iBAAc,oBAAoB,eAAe,SAAS,OAAO;AAAA,UACtE;AACA,kBAAQ;AAAA,YACN,GAAG,MAAM,mDAAmD,WAAW;AAAA,UACzE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACnF;AAAA,EACF;AAGA,MAAI;AACF,eAAW,YAAY,kBAAkB;AACvC,YAAM,WAAgB,UAAK,aAAa,QAAQ;AAChD,UAAI,CAAI,cAAW,QAAQ,GAAG;AAC5B;AAAA,MACF;AAEA,YAAM,UAAa,gBAAa,UAAU,OAAO;AACjD,YAAM,SAAS,oBAAoB,OAAO;AAE1C,UAAI,OAAO,SAAS;AAClB,YAAI,OAAO,QAAQ,KAAK,EAAE,WAAW,GAAG;AAGtC,cAAI,CAAC,QAAQ;AACX,YAAG,cAAW,QAAQ;AAAA,UACxB;AACA,kBAAQ,KAAK,GAAG,MAAM,WAAW,QAAQ,sCAAsC;AAAA,QACjF,OAAO;AACL,cAAI,CAAC,QAAQ;AACX,YAAG,iBAAc,UAAU,OAAO,SAAS,OAAO;AAAA,UACpD;AACA,kBAAQ,KAAK,GAAG,MAAM,mCAAmC,QAAQ,EAAE;AAAA,QACrE;AAAA,MACF;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,WAAO;AAAA,MACL,uCAAuC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IACzF;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,KAAK,OAAO,WAAW,GAAG;AAC/C,YAAQ,KAAK,qDAAgD;AAAA,EAC/D;AAEA,SAAO,EAAE,UAAU,OAAO,SAAS,IAAI,IAAI,GAAG,SAAS,UAAU,OAAO;AAC1E;","names":[]}