llmist 7.0.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/constants.ts","../src/cli/program.ts","../package.json","../src/cli/agent-command.ts","../src/core/errors.ts","../src/cli/builtin-gadgets.ts","../src/cli/subagent-config.ts","../src/cli/file-utils.ts","../src/cli/gadgets.ts","../src/cli/builtins/filesystem/edit-file.ts","../src/cli/builtins/filesystem/utils.ts","../src/cli/builtins/filesystem/list-directory.ts","../src/cli/builtins/filesystem/read-file.ts","../src/cli/builtins/filesystem/write-file.ts","../src/cli/builtins/run-command.ts","../src/cli/builtins/index.ts","../src/cli/external-gadgets.ts","../src/cli/llm-logging.ts","../src/cli/utils.ts","../src/cli/ui/formatters.ts","../src/cli/option-helpers.ts","../src/cli/tui/screen.ts","../src/cli/tui/layout.ts","../src/cli/tui/status-bar.ts","../src/cli/tui/input-handler.ts","../src/cli/tui/block-renderer.ts","../src/cli/ui/block-formatters.ts","../src/cli/tui/approval-dialog.ts","../src/cli/tui/raw-viewer.ts","../src/cli/tui/index.ts","../src/cli/complete-command.ts","../src/cli/init-command.ts","../src/cli/config.ts","../src/cli/templates.ts","../src/cli/environment.ts","../src/cli/custom-command.ts","../src/cli/gadget-command.ts","../src/cli/gadget-prompts.ts","../src/cli/image-command.ts","../src/cli/models-command.ts","../src/cli/speech-command.ts","../src/cli/vision-command.ts","../src/cli.ts"],"sourcesContent":["/** CLI program name */\nexport const CLI_NAME = \"llmist\";\n\n/** CLI program description shown in --help */\nexport const CLI_DESCRIPTION = \"Command line utilities for llmist agents and direct LLM access.\";\n\n/** Available CLI commands */\nexport const COMMANDS = {\n complete: \"complete\",\n agent: \"agent\",\n models: \"models\",\n gadget: \"gadget\",\n image: \"image\",\n speech: \"speech\",\n vision: \"vision\",\n init: \"init\",\n} as const;\n\n/** Valid log level names */\nexport const LOG_LEVELS = [\"silly\", \"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"] as const;\nexport type CLILogLevel = (typeof LOG_LEVELS)[number];\n\n/** Default model used when --model is not specified */\nexport const DEFAULT_MODEL = \"openai:gpt-5-nano\";\n\n/** Command-line option flags */\nexport const OPTION_FLAGS = {\n model: \"-m, --model <identifier>\",\n systemPrompt: \"-s, --system <prompt>\",\n temperature: \"-t, --temperature <value>\",\n maxTokens: \"--max-tokens <count>\",\n maxIterations: \"-i, --max-iterations <count>\",\n gadgetModule: \"-g, --gadget <module>\",\n logLevel: \"--log-level <level>\",\n logFile: \"--log-file <path>\",\n logReset: \"--log-reset\",\n logLlmRequests: \"--log-llm-requests [dir]\",\n noBuiltins: \"--no-builtins\",\n noBuiltinInteraction: \"--no-builtin-interaction\",\n quiet: \"-q, --quiet\",\n // Multimodal input options\n inputImage: \"--image <path>\",\n inputAudio: \"--audio <path>\",\n // Image generation options\n imageSize: \"--size <size>\",\n imageQuality: \"--quality <quality>\",\n imageCount: \"-n, --count <number>\",\n imageOutput: \"-o, --output <path>\",\n // Speech generation options\n voice: \"--voice <name>\",\n speechFormat: \"--format <format>\",\n speechSpeed: \"--speed <value>\",\n speechOutput: \"-o, --output <path>\",\n} as const;\n\n/** Human-readable descriptions for command-line options */\nexport const OPTION_DESCRIPTIONS = {\n model: \"Model identifier, e.g. openai:gpt-5-nano or anthropic:claude-sonnet-4-5.\",\n systemPrompt: \"Optional system prompt prepended to the conversation.\",\n temperature: \"Sampling temperature between 0 and 2.\",\n maxTokens: \"Maximum number of output tokens requested from the model.\",\n maxIterations: \"Maximum number of agent loop iterations before exiting.\",\n gadgetModule:\n \"Path or module specifier for a gadget export. Repeat to register multiple gadgets.\",\n logLevel: \"Log level: silly, trace, debug, info, warn, error, fatal.\",\n logFile: \"Path to log file. When set, logs are written to file instead of stderr.\",\n logReset: \"Reset (truncate) the log file at session start instead of appending.\",\n logLlmRequests:\n \"Save LLM requests/responses to session directories. Optional dir, defaults to ~/.llmist/logs/requests/\",\n noBuiltins: \"Disable built-in gadgets (AskUser, TellUser).\",\n noBuiltinInteraction: \"Disable interactive gadgets (AskUser) while keeping TellUser.\",\n quiet: \"Suppress all output except content (text and TellUser messages).\",\n // Multimodal input descriptions\n inputImage: \"Image file to include with the prompt (vision models).\",\n inputAudio: \"Audio file to include with the prompt (Gemini only).\",\n // Image generation descriptions\n imageSize: \"Image size/aspect ratio, e.g. '1024x1024', '1:1', '16:9'.\",\n imageQuality: \"Image quality: 'standard', 'hd', 'low', 'medium', 'high'.\",\n imageCount: \"Number of images to generate (model dependent, usually 1-4).\",\n imageOutput: \"Output path for the generated image. Defaults to stdout if not specified.\",\n // Speech generation descriptions\n voice: \"Voice name for speech generation, e.g. 'nova', 'alloy', 'Zephyr'.\",\n speechFormat: \"Audio format: 'mp3', 'opus', 'aac', 'flac', 'wav', 'pcm'.\",\n speechSpeed: \"Speech speed multiplier (0.25 to 4.0, default 1.0).\",\n speechOutput: \"Output path for audio file. Defaults to stdout if not specified.\",\n} as const;\n\n/** Prefix for summary output written to stderr */\nexport const SUMMARY_PREFIX = \"[llmist]\";\n","import { Command, InvalidArgumentError } from \"commander\";\n\nimport packageJson from \"../../package.json\";\n\nimport { registerAgentCommand } from \"./agent-command.js\";\nimport { registerCompleteCommand } from \"./complete-command.js\";\nimport { registerInitCommand } from \"./init-command.js\";\nimport {\n type CLIConfig,\n type CustomCommandConfig,\n getCustomCommandNames,\n loadConfig,\n} from \"./config.js\";\nimport {\n CLI_DESCRIPTION,\n CLI_NAME,\n LOG_LEVELS,\n type CLILogLevel,\n OPTION_DESCRIPTIONS,\n OPTION_FLAGS,\n} from \"./constants.js\";\nimport { registerCustomCommand } from \"./custom-command.js\";\nimport type { CLIEnvironment, CLILoggerConfig } from \"./environment.js\";\nimport { createDefaultEnvironment } from \"./environment.js\";\nimport { registerGadgetCommand } from \"./gadget-command.js\";\nimport { registerImageCommand } from \"./image-command.js\";\nimport { registerModelsCommand } from \"./models-command.js\";\nimport { registerSpeechCommand } from \"./speech-command.js\";\nimport { registerVisionCommand } from \"./vision-command.js\";\n\n/**\n * Parses and validates the log level option value.\n */\nfunction parseLogLevel(value: string): CLILogLevel {\n const normalized = value.toLowerCase() as CLILogLevel;\n if (!LOG_LEVELS.includes(normalized)) {\n throw new InvalidArgumentError(`Log level must be one of: ${LOG_LEVELS.join(\", \")}`);\n }\n return normalized;\n}\n\n/**\n * Global CLI options that apply to all commands.\n */\ninterface GlobalOptions {\n logLevel?: CLILogLevel;\n logFile?: string;\n logReset?: boolean;\n}\n\n/**\n * Creates and configures the CLI program with complete and agent commands.\n *\n * @param env - CLI environment configuration for I/O and dependencies\n * @param config - Optional CLI configuration loaded from config file\n * @returns Configured Commander program ready for parsing\n */\nexport function createProgram(env: CLIEnvironment, config?: CLIConfig): Command {\n const program = new Command();\n\n program\n .name(CLI_NAME)\n .description(CLI_DESCRIPTION)\n .version(packageJson.version)\n .option(OPTION_FLAGS.logLevel, OPTION_DESCRIPTIONS.logLevel, parseLogLevel)\n .option(OPTION_FLAGS.logFile, OPTION_DESCRIPTIONS.logFile)\n .option(OPTION_FLAGS.logReset, OPTION_DESCRIPTIONS.logReset)\n .configureOutput({\n writeOut: (str) => env.stdout.write(str),\n writeErr: (str) => env.stderr.write(str),\n });\n\n // Register built-in commands with config defaults\n registerCompleteCommand(program, env, config?.complete);\n registerAgentCommand(program, env, config?.agent, config?.subagents);\n registerImageCommand(program, env, config?.image);\n registerSpeechCommand(program, env, config?.speech);\n registerVisionCommand(program, env);\n registerModelsCommand(program, env);\n registerGadgetCommand(program, env);\n registerInitCommand(program, env);\n\n // Register custom commands from config\n if (config) {\n const customNames = getCustomCommandNames(config);\n for (const name of customNames) {\n const cmdConfig = config[name] as CustomCommandConfig;\n registerCustomCommand(program, name, cmdConfig, env, config.subagents);\n }\n }\n\n return program;\n}\n\n/**\n * Options for runCLI function.\n */\nexport interface RunCLIOptions {\n /** Environment overrides for testing or customization */\n env?: Partial<CLIEnvironment>;\n /** Config override - if provided, skips loading from file. Use {} to disable config. */\n config?: CLIConfig;\n}\n\n/**\n * Main entry point for running the CLI.\n * Creates environment, parses arguments, and executes the appropriate command.\n *\n * @param overrides - Optional environment overrides or options object\n */\nexport async function runCLI(\n overrides: Partial<CLIEnvironment> | RunCLIOptions = {},\n): Promise<void> {\n // Handle both old signature (Partial<CLIEnvironment>) and new signature (RunCLIOptions)\n const opts: RunCLIOptions =\n \"env\" in overrides || \"config\" in overrides\n ? (overrides as RunCLIOptions)\n : { env: overrides as Partial<CLIEnvironment> };\n\n // Load config early (before program creation) - errors here should fail fast\n // If config is provided in options, use it instead of loading from file\n const config = opts.config !== undefined ? opts.config : loadConfig();\n const envOverrides = opts.env ?? {};\n\n // First pass: parse global options only (skip if help requested)\n const preParser = new Command();\n preParser\n .option(OPTION_FLAGS.logLevel, OPTION_DESCRIPTIONS.logLevel, parseLogLevel)\n .option(OPTION_FLAGS.logFile, OPTION_DESCRIPTIONS.logFile)\n .option(OPTION_FLAGS.logReset, OPTION_DESCRIPTIONS.logReset)\n .allowUnknownOption()\n .allowExcessArguments()\n .helpOption(false); // Don't intercept --help\n\n preParser.parse(process.argv);\n const globalOpts = preParser.opts<GlobalOptions>();\n\n // Create environment with logger config from global options\n // Priority: CLI flags > config file > defaults\n const loggerConfig: CLILoggerConfig = {\n logLevel: globalOpts.logLevel ?? config.global?.[\"log-level\"],\n logFile: globalOpts.logFile ?? config.global?.[\"log-file\"],\n logReset: globalOpts.logReset ?? config.global?.[\"log-reset\"],\n };\n\n const defaultEnv = createDefaultEnvironment(loggerConfig);\n const env: CLIEnvironment = {\n ...defaultEnv,\n ...envOverrides,\n };\n const program = createProgram(env, config);\n await program.parseAsync(env.argv);\n}\n","{\n \"name\": \"llmist\",\n \"version\": \"6.2.0\",\n \"description\": \"TypeScript LLM client with streaming tool execution. Tools fire mid-stream. Built-in function calling works with any model—no structured outputs or native tool support required.\",\n \"type\": \"module\",\n \"main\": \"dist/index.cjs\",\n \"module\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./testing\": {\n \"import\": {\n \"types\": \"./dist/testing/index.d.ts\",\n \"default\": \"./dist/testing/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/testing/index.d.cts\",\n \"default\": \"./dist/testing/index.cjs\"\n }\n }\n },\n \"scripts\": {\n \"cli\": \"bun run scripts/cli-runner.ts\",\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"biome lint .\",\n \"format\": \"biome format --write .\",\n \"check\": \"biome check --write .\",\n \"test\": \"bun test\",\n \"test:unit\": \"bun test src/agent src/core src/gadgets src/providers src/testing\",\n \"test:watch\": \"bun test --watch\",\n \"test:e2e\": \"bun test src/e2e --timeout 60000 --bail 1\",\n \"test:e2e:watch\": \"bun test src/e2e --watch --timeout 60000\",\n \"test:all\": \"bun run test && bun run test:e2e\",\n \"clean\": \"rimraf dist\",\n \"prepare\": \"node scripts/install-hooks.js || true\",\n \"release:dry\": \"bunx semantic-release --dry-run\",\n \"release:publish\": \"test \\\"$(git branch --show-current)\\\" = \\\"main\\\" && git pull origin main && bun run build && npm publish\"\n },\n \"bin\": {\n \"llmist\": \"dist/cli.js\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/zbigniewsobiecki/llmist.git\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"files\": [\n \"dist\"\n ],\n \"keywords\": [\n \"llm\",\n \"ai\",\n \"agent\",\n \"agents\",\n \"openai\",\n \"anthropic\",\n \"claude\",\n \"gemini\",\n \"gpt\",\n \"streaming\",\n \"function-calling\",\n \"tool-calling\",\n \"typescript\",\n \"universal-client\",\n \"multi-provider\",\n \"hooks\",\n \"gadgets\",\n \"chatbot\",\n \"chatgpt\",\n \"agentic\",\n \"language-model\",\n \"generative-ai\",\n \"bun\",\n \"nodejs\"\n ],\n \"author\": \"Zbigniew Sobiecki <zbigniew@sobiecki.name>\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@anthropic-ai/sdk\": \"^0.69.0\",\n \"@google/genai\": \"^1.27.0\",\n \"@unblessed/node\": \"^1.0.0-alpha.23\",\n \"chalk\": \"^5.6.2\",\n \"commander\": \"^12.1.0\",\n \"diff\": \"^8.0.2\",\n \"eta\": \"^4.4.1\",\n \"fast-deep-equal\": \"^3.1.3\",\n \"js-toml\": \"^1.0.2\",\n \"js-yaml\": \"^4.1.0\",\n \"marked\": \"^15.0.12\",\n \"marked-terminal\": \"^7.3.0\",\n \"openai\": \"^6.0.0\",\n \"tiktoken\": \"^1.0.22\",\n \"tslog\": \"^4.10.2\",\n \"zod\": \"^4.1.12\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.3.2\",\n \"@commitlint/cli\": \"^20.1.0\",\n \"@commitlint/config-conventional\": \"^20.0.0\",\n \"@semantic-release/changelog\": \"^6.0.3\",\n \"@semantic-release/git\": \"^10.0.1\",\n \"@types/diff\": \"^8.0.0\",\n \"@types/js-yaml\": \"^4.0.9\",\n \"@types/marked-terminal\": \"^6.1.1\",\n \"@types/node\": \"^20.12.7\",\n \"bun-types\": \"^1.3.2\",\n \"dotenv\": \"^17.2.3\",\n \"rimraf\": \"^5.0.5\",\n \"semantic-release\": \"^25.0.2\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.4.5\"\n }\n}\n","import chalk from \"chalk\";\nimport type { Command } from \"commander\";\nimport { AgentBuilder } from \"../agent/builder.js\";\nimport { isAbortError } from \"../core/errors.js\";\nimport type { ContentPart } from \"../core/input-content.js\";\nimport { text } from \"../core/input-content.js\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { TokenUsage } from \"../core/options.js\";\nimport { GadgetRegistry } from \"../gadgets/registry.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"../providers/constants.js\";\nimport type { ApprovalConfig } from \"./approval/index.js\";\nimport { builtinGadgets } from \"./builtin-gadgets.js\";\nimport type { AgentConfig, GlobalSubagentConfig } from \"./config.js\";\nimport { buildSubagentConfigMap } from \"./subagent-config.js\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { readAudioFile, readImageFile } from \"./file-utils.js\";\nimport { loadGadgets } from \"./gadgets.js\";\nimport {\n createSessionDir,\n formatCallNumber,\n formatLlmRequest,\n resolveLogDir,\n writeLogFile,\n} from \"./llm-logging.js\";\nimport { type CLIAgentOptions, addAgentOptions } from \"./option-helpers.js\";\nimport { TUIApp, StatusBar } from \"./tui/index.js\";\nimport { executeAction, isInteractive, resolvePrompt } from \"./utils.js\";\n\n/**\n * Executes the agent command.\n *\n * SHOWCASE: This function demonstrates how to build a production-grade CLI\n * on top of llmist's core capabilities:\n *\n * 1. **Dynamic gadget loading** - GadgetRegistry for plugin-like extensibility\n * 2. **Observer hooks** - Custom progress tracking and real-time UI updates\n * 3. **Event-driven execution** - React to agent events (text, gadget results)\n * 4. **ModelRegistry integration** - Automatic cost estimation and tracking\n * 5. **Streaming support** - Display LLM output as it's generated\n * 6. **Human-in-the-loop** - Interactive prompts during agent execution\n * 7. **Clean separation** - stdout for content, stderr for metrics/progress\n *\n * The implementation showcases llmist's flexibility: from simple scripts to\n * polished CLIs with spinners, cost tracking, and real-time feedback.\n *\n * @param promptArg - User prompt from command line argument (optional if using stdin)\n * @param options - Agent command options (model, gadgets, max iterations, etc.)\n * @param env - CLI environment for I/O operations\n */\nexport async function executeAgent(\n promptArg: string | undefined,\n options: CLIAgentOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const client = env.createClient();\n\n // Detect TUI mode early: use TUI when both stdin and stdout are TTY\n const stdinIsInteractive = isInteractive(env.stdin);\n const stdoutTTY = (env.stdout as NodeJS.WriteStream).isTTY === true;\n const useTUI = stdinIsInteractive && stdoutTTY && !options.quiet;\n\n // Resolve prompt: required for piped mode, optional for TUI mode (REPL will wait)\n let prompt: string;\n if (useTUI) {\n // TUI mode: prompt is optional (REPL will wait for input if not provided)\n prompt = promptArg ?? \"\";\n } else {\n // Piped mode: prompt is required\n prompt = await resolvePrompt(promptArg, env);\n }\n\n // SHOWCASE: llmist's GadgetRegistry for dynamic tool loading\n const registry = new GadgetRegistry();\n\n // Register built-in gadgets for basic agent interaction\n // AskUser is auto-excluded when stdin is not interactive (piped input)\n if (options.builtins !== false) {\n for (const gadget of builtinGadgets) {\n // Skip AskUser if:\n // 1. --no-builtin-interaction is set, OR\n // 2. stdin is not interactive (piped input) - AskUser can't work anyway\n if (\n gadget.name === \"AskUser\" &&\n (options.builtinInteraction === false || !stdinIsInteractive)\n ) {\n continue;\n }\n registry.registerByClass(gadget);\n }\n }\n\n // Load user-provided gadgets from file paths\n const gadgetSpecifiers = options.gadget ?? [];\n if (gadgetSpecifiers.length > 0) {\n const gadgets = await loadGadgets(gadgetSpecifiers, process.cwd());\n for (const gadget of gadgets) {\n registry.registerByClass(gadget);\n }\n }\n\n // Create TUI app if in TUI mode\n let tui: TUIApp | null = null;\n if (useTUI) {\n tui = await TUIApp.create({\n model: options.model,\n stdin: env.stdin as NodeJS.ReadStream,\n stdout: env.stdout as NodeJS.WriteStream,\n });\n }\n\n // Set up cancellation support\n const abortController = new AbortController();\n let wasCancelled = false;\n\n // Quit handler - cleanup and exit\n const handleQuit = () => {\n if (tui) {\n tui.destroy();\n }\n process.exit(130); // SIGINT convention: 128 + signal number (2)\n };\n\n // Set up TUI event handlers for ESC and Ctrl+C\n if (tui) {\n tui.onQuit(handleQuit);\n tui.onCancel(() => {\n wasCancelled = true;\n abortController.abort();\n });\n }\n\n // In piped mode, set up basic SIGINT handler\n if (!useTUI) {\n process.once(\"SIGINT\", () => process.exit(130));\n }\n\n // Set up gadget approval manager\n // Default: RunCommand, WriteFile, EditFile require approval unless overridden by config\n const DEFAULT_APPROVAL_REQUIRED = [\"RunCommand\", \"WriteFile\", \"EditFile\"];\n const userApprovals = options.gadgetApproval ?? {};\n\n // Apply defaults for dangerous gadgets if not explicitly configured\n const gadgetApprovals: Record<\n string,\n \"allowed\" | \"denied\" | \"approval-required\"\n > = {\n ...userApprovals,\n };\n for (const gadget of DEFAULT_APPROVAL_REQUIRED) {\n const normalizedGadget = gadget.toLowerCase();\n const isConfigured = Object.keys(userApprovals).some(\n (key) => key.toLowerCase() === normalizedGadget,\n );\n if (!isConfigured) {\n gadgetApprovals[gadget] = \"approval-required\";\n }\n }\n\n const approvalConfig: ApprovalConfig = {\n gadgetApprovals,\n defaultMode: \"allowed\",\n };\n // Approval is handled:\n // - TUI mode: TUI's modal dialogs (in beforeGadgetExecution controller)\n // - Piped mode: auto-deny gadgets requiring approval (can't prompt)\n\n let usage: TokenUsage | undefined;\n let iterations = 0;\n\n // Resolve LLM debug log directory (if enabled)\n const llmLogsBaseDir = resolveLogDir(options.logLlmRequests, \"requests\");\n let llmSessionDir: string | undefined;\n let llmCallCounter = 0;\n\n // Count tokens accurately using provider-specific methods\n const countMessagesTokens = async (\n model: string,\n messages: LLMMessage[],\n ): Promise<number> => {\n try {\n return await client.countTokens(model, messages);\n } catch {\n // Fallback to character-based estimation if counting fails\n const totalChars = messages.reduce(\n (sum, m) => sum + (m.content?.length ?? 0),\n 0,\n );\n return Math.round(totalChars / FALLBACK_CHARS_PER_TOKEN);\n }\n };\n\n // Count tokens for gadget output text\n const countGadgetOutputTokens = async (\n output: string | undefined,\n ): Promise<number | undefined> => {\n if (!output) return undefined;\n try {\n // Wrap gadget output as assistant message for accurate token counting\n const messages: LLMMessage[] = [{ role: \"assistant\", content: output }];\n return await client.countTokens(options.model, messages);\n } catch {\n // Fallback: return undefined to trigger byte count fallback in formatter\n return undefined;\n }\n };\n\n // Build the agent with hooks for progress tracking\n // SHOWCASE: This demonstrates llmist's observer pattern for building custom UIs\n //\n // For simpler use cases, use HookPresets.progressTracking() instead:\n // .withHooks(HookPresets.progressTracking({\n // modelRegistry: client.modelRegistry,\n // onProgress: (stats) => { /* update your UI */ }\n // }))\n //\n // The CLI uses custom hooks for fine-grained control over the spinner animation\n // and real-time updates, showcasing llmist's flexibility for building polished UIs.\n // Build resolved subagent config map for subagent gadgets to inherit settings\n const resolvedSubagentConfig = buildSubagentConfigMap(\n options.model,\n options.subagents,\n options.globalSubagents,\n );\n\n const builder = new AgentBuilder(client)\n .withModel(options.model)\n .withSubagentConfig(resolvedSubagentConfig)\n .withLogger(env.createLogger(\"llmist:cli:agent\"))\n .withHooks({\n observers: {\n // onLLMCallStart: Update TUI with LLM call info and estimated input tokens\n onLLMCallStart: async (context) => {\n if (context.subagentContext) return;\n llmCallCounter++;\n\n if (tui) {\n // Estimate input tokens from messages\n const estimatedInput = await countMessagesTokens(\n context.options.model,\n context.options.messages,\n );\n tui.showLLMCallStart(iterations + 1, context.options.model, estimatedInput);\n }\n },\n\n // onLLMCallReady: Log the exact request being sent to the LLM\n onLLMCallReady: async (context) => {\n if (context.subagentContext) return;\n\n // Store raw request in TUI for raw viewer\n if (tui) {\n tui.setLLMCallRequest(context.options.messages);\n }\n\n if (llmLogsBaseDir) {\n if (!llmSessionDir) {\n llmSessionDir = await createSessionDir(llmLogsBaseDir);\n }\n if (llmSessionDir) {\n const filename = `${formatCallNumber(llmCallCounter)}.request`;\n const content = formatLlmRequest(context.options.messages);\n await writeLogFile(llmSessionDir, filename, content);\n }\n }\n },\n\n // onStreamChunk: Update status bar with real-time output token estimate\n onStreamChunk: async (context) => {\n if (context.subagentContext) return;\n if (!tui) return;\n\n // Use accumulated text from context to estimate output tokens\n const estimatedOutputTokens = StatusBar.estimateTokens(context.accumulatedText);\n tui.updateStreamingTokens(estimatedOutputTokens);\n },\n\n // onLLMCallComplete: Update TUI with completion metrics\n onLLMCallComplete: async (context) => {\n if (context.subagentContext) return;\n\n // Capture completion metadata\n usage = context.usage;\n iterations = Math.max(iterations, context.iteration + 1);\n\n // Calculate per-call cost\n let callCost: number | undefined;\n if (context.usage && client.modelRegistry) {\n try {\n const modelName = context.options.model.includes(\":\")\n ? context.options.model.split(\":\")[1]\n : context.options.model;\n const costResult = client.modelRegistry.estimateCost(\n modelName,\n context.usage.inputTokens,\n context.usage.outputTokens,\n context.usage.cachedInputTokens ?? 0,\n context.usage.cacheCreationInputTokens ?? 0,\n );\n if (costResult) callCost = costResult.totalCost;\n } catch {\n // Ignore cost calculation errors\n }\n }\n\n if (tui) {\n tui.showLLMCallComplete({\n iteration: context.iteration + 1,\n model: context.options.model,\n inputTokens: context.usage?.inputTokens,\n outputTokens: context.usage?.outputTokens,\n cachedInputTokens: context.usage?.cachedInputTokens,\n elapsedSeconds: tui.getElapsedSeconds(),\n cost: callCost,\n finishReason: context.finishReason ?? \"stop\",\n rawResponse: context.rawResponse,\n });\n }\n\n // Write LLM response to debug log if enabled\n if (llmSessionDir) {\n const filename = `${formatCallNumber(llmCallCounter)}.response`;\n await writeLogFile(llmSessionDir, filename, context.rawResponse);\n }\n },\n },\n\n // SHOWCASE: Controller-based approval gating for gadgets\n //\n // This demonstrates how to add safety layers WITHOUT modifying gadgets.\n // The ApprovalManager handles approval flows externally via beforeGadgetExecution.\n // Approval modes are configurable via cli.toml:\n // - \"allowed\": auto-proceed\n // - \"denied\": auto-reject, return message to LLM\n // - \"approval-required\": prompt user interactively\n //\n // Default: RunCommand, WriteFile, EditFile require approval unless overridden.\n controllers: {\n beforeGadgetExecution: async (ctx) => {\n // Get approval mode from config\n const normalizedGadgetName = ctx.gadgetName.toLowerCase();\n const configuredMode = Object.entries(gadgetApprovals).find(\n ([key]) => key.toLowerCase() === normalizedGadgetName,\n )?.[1];\n const mode = configuredMode ?? approvalConfig.defaultMode;\n\n // Fast path: allowed gadgets proceed immediately\n if (mode === \"allowed\") {\n return { action: \"proceed\" };\n }\n\n // Check if we can prompt (interactive mode required for approval-required)\n const stdinTTY = isInteractive(env.stdin);\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n const canPrompt = stdinTTY && stderrTTY;\n\n // Non-interactive mode handling\n if (!canPrompt) {\n if (mode === \"approval-required\") {\n return {\n action: \"skip\",\n syntheticResult: `status=denied\\n\\n${ctx.gadgetName} requires interactive approval. Run in a terminal to approve.`,\n };\n }\n if (mode === \"denied\") {\n return {\n action: \"skip\",\n syntheticResult: `status=denied\\n\\n${ctx.gadgetName} is denied by configuration.`,\n };\n }\n return { action: \"proceed\" };\n }\n\n // TUI mode: use TUI's modal approval dialog\n if (tui) {\n const response = await tui.showApproval({\n gadgetName: ctx.gadgetName,\n parameters: ctx.parameters,\n });\n\n if (response === \"yes\" || response === \"always\") {\n // TODO: Handle \"always\" by updating gadgetApprovals\n return { action: \"proceed\" };\n }\n return {\n action: \"skip\",\n syntheticResult: `status=denied\\n\\nDenied by user`,\n };\n }\n\n // Piped mode: can't prompt for approval, deny\n return {\n action: \"skip\",\n syntheticResult: `status=denied\\n\\n${ctx.gadgetName} requires interactive approval. Run in a terminal to approve.`,\n };\n },\n },\n });\n\n // Add optional configurations\n if (options.system) {\n builder.withSystem(options.system);\n }\n if (options.maxIterations !== undefined) {\n builder.withMaxIterations(options.maxIterations);\n }\n if (options.temperature !== undefined) {\n builder.withTemperature(options.temperature);\n }\n\n // Set up human input handler (TUI mode only)\n // In piped mode, AskUser gadget is excluded (see gadget registration above)\n if (tui) {\n builder.onHumanInput(async (question: string) => {\n return tui.waitForInput(question, \"AskUser\");\n });\n }\n\n // Pass abort signal for ESC key cancellation\n builder.withSignal(abortController.signal);\n\n // Add gadgets from the registry\n const gadgets = registry.getAll();\n if (gadgets.length > 0) {\n builder.withGadgets(...gadgets);\n }\n\n // Set custom gadget markers if configured, otherwise use library defaults\n if (options.gadgetStartPrefix) {\n builder.withGadgetStartPrefix(options.gadgetStartPrefix);\n }\n if (options.gadgetEndPrefix) {\n builder.withGadgetEndPrefix(options.gadgetEndPrefix);\n }\n if (options.gadgetArgPrefix) {\n builder.withGadgetArgPrefix(options.gadgetArgPrefix);\n }\n\n // Inject synthetic heredoc example for in-context learning\n // This teaches the LLM to use heredoc syntax (<<<EOF...EOF) for multiline strings\n // by showing what \"past self\" did correctly. LLMs mimic patterns in conversation history.\n builder.withSyntheticGadgetCall(\n \"TellUser\",\n {\n message:\n \"👋 Hello! I'm ready to help.\\n\\nWhat would you like me to work on?\",\n done: false,\n type: \"info\",\n },\n \"ℹ️ 👋 Hello! I'm ready to help.\\n\\nWhat would you like me to work on?\",\n \"gc_init_1\",\n );\n\n // Continue looping when LLM responds with just text (no gadget calls)\n // This allows multi-turn conversations where the LLM may explain before acting\n builder.withTextOnlyHandler(\"acknowledge\");\n\n // Wrap text that accompanies gadget calls as TellUser gadget calls\n // This keeps conversation history consistent and gadget-oriented\n builder.withTextWithGadgetsHandler({\n gadgetName: \"TellUser\",\n parameterMapping: (text) => ({ message: text, done: false, type: \"info\" }),\n resultMapping: (text) => `ℹ️ ${text}`,\n });\n\n // Inject ephemeral trailing message to encourage parallel gadget invocations\n // This message is appended to each LLM request but NOT persisted in history\n builder.withTrailingMessage((ctx) =>\n [\n `[Iteration ${ctx.iteration + 1}/${ctx.maxIterations}]`,\n \"Think carefully in two steps: 1. what gadget invocations we should be making next? 2. how do they depend on one another so we can run all of them in the right order? Then respond with all the gadget invocations you are able to do now.\",\n ].join(\" \"),\n );\n\n // Helper to create and run an agent with a given prompt\n const runAgentWithPrompt = async (userPrompt: string) => {\n // Reset abort controller for new iteration (TUI mode)\n if (tui) {\n tui.resetAbort();\n builder.withSignal(tui.getAbortSignal());\n }\n\n // Build the agent\n let agent;\n if (options.image || options.audio) {\n const parts: ContentPart[] = [text(userPrompt)];\n if (options.image) {\n parts.push(await readImageFile(options.image));\n }\n if (options.audio) {\n parts.push(await readAudioFile(options.audio));\n }\n agent = builder.askWithContent(parts);\n } else {\n agent = builder.ask(userPrompt);\n }\n\n // Subscribe TUI to ExecutionTree for automatic block management\n // This handles nested subagent events automatically via tree events\n let unsubscribeTree: (() => void) | undefined;\n if (tui) {\n unsubscribeTree = tui.subscribeToTree(agent.getTree());\n }\n\n // Run the agent and handle events\n for await (const event of agent.run()) {\n if (tui) {\n // TUI mode: pass all events to TUI\n tui.handleEvent(event);\n\n // Track gadget costs in TUI status bar\n if (event.type === \"gadget_result\" && event.result.cost) {\n tui.addGadgetCost(event.result.cost);\n }\n } else {\n // Piped mode: output text events and TellUser messages to stdout\n if (event.type === \"text\") {\n env.stdout.write(event.content);\n } else if (\n event.type === \"gadget_result\" &&\n event.result.gadgetName === \"TellUser\" &&\n event.result.result\n ) {\n // TellUser gadget returns formatted message in result field\n env.stdout.write(`${event.result.result}\\n`);\n }\n }\n }\n\n // Flush any buffered text\n if (tui) {\n tui.flushText();\n }\n\n // Clean up tree subscription\n if (unsubscribeTree) {\n unsubscribeTree();\n }\n };\n\n // TUI mode: REPL loop - wait for input, run agent, repeat\n // Piped mode: Run once and exit\n if (tui) {\n // Get initial prompt (from CLI arg or wait for user input)\n let currentPrompt = prompt;\n if (!currentPrompt) {\n currentPrompt = await tui.waitForPrompt();\n }\n\n // REPL loop\n while (true) {\n try {\n await runAgentWithPrompt(currentPrompt);\n } catch (error) {\n // Handle abort gracefully - continue to next prompt\n if (!isAbortError(error)) {\n throw error;\n }\n }\n\n // Wait for next prompt\n currentPrompt = await tui.waitForPrompt();\n }\n } else {\n // Piped mode: run once and exit\n try {\n await runAgentWithPrompt(prompt);\n } catch (error) {\n if (!isAbortError(error)) {\n throw error;\n }\n }\n }\n}\n\n/**\n * Registers the agent command with the CLI program.\n * Configures options for model, gadgets, max iterations, temperature, and parameter format.\n *\n * @param program - Commander program to register the command with\n * @param env - CLI environment for dependencies and I/O\n * @param config - Optional configuration defaults from config file\n */\nexport function registerAgentCommand(\n program: Command,\n env: CLIEnvironment,\n config?: AgentConfig,\n globalSubagents?: GlobalSubagentConfig,\n): void {\n const cmd = program\n .command(COMMANDS.agent)\n .description(\"Run the llmist agent loop with optional gadgets.\")\n .argument(\n \"[prompt]\",\n \"Prompt for the agent loop. Falls back to stdin when available.\",\n );\n\n addAgentOptions(cmd, config);\n\n cmd.action((prompt, options) =>\n executeAction(() => {\n // Merge config-only options (no CLI flags) into command options\n const mergedOptions: CLIAgentOptions = {\n ...(options as CLIAgentOptions),\n gadgetApproval: config?.[\"gadget-approval\"],\n subagents: config?.subagents,\n globalSubagents,\n };\n return executeAgent(prompt, mergedOptions, env);\n }, env),\n );\n}\n","/**\n * Error utilities for llmist.\n */\n\n/**\n * Detects if an error is an abort/cancellation error from any provider.\n *\n * Different providers throw different error types when a request is aborted:\n * - Standard: `AbortError` (name) - from fetch/AbortController\n * - Anthropic SDK: `APIConnectionAbortedError`\n * - OpenAI SDK: `APIUserAbortError`\n * - Generic: errors with \"abort\", \"cancelled\", or \"canceled\" in the message\n *\n * @param error - The error to check\n * @returns `true` if the error is an abort-related error, `false` otherwise\n *\n * @example\n * ```typescript\n * import { isAbortError } from \"@llmist/core/errors\";\n *\n * const controller = new AbortController();\n *\n * try {\n * for await (const chunk of client.stream({ signal: controller.signal, ... })) {\n * // Process chunks...\n * }\n * } catch (error) {\n * if (isAbortError(error)) {\n * console.log(\"Request was cancelled - this is expected\");\n * return; // Graceful exit\n * }\n * // Re-throw unexpected errors\n * throw error;\n * }\n * ```\n */\nexport function isAbortError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n\n // Standard AbortError (from fetch/AbortController)\n if (error.name === \"AbortError\") return true;\n\n // Anthropic SDK\n if (error.name === \"APIConnectionAbortedError\") return true;\n\n // OpenAI SDK\n if (error.name === \"APIUserAbortError\") return true;\n\n // Message-based detection (fallback for edge cases)\n const message = error.message.toLowerCase();\n if (message.includes(\"abort\")) return true;\n if (message.includes(\"cancelled\")) return true;\n if (message.includes(\"canceled\")) return true;\n\n return false;\n}\n","/**\n * Built-in gadgets for CLI agent command.\n * These gadgets provide basic communication capabilities out-of-the-box.\n */\nimport { z } from \"zod\";\n\nimport { createGadget } from \"../gadgets/create-gadget.js\";\nimport { TaskCompletionSignal, HumanInputRequiredException } from \"../gadgets/exceptions.js\";\n\n/**\n * AskUser gadget - Asks the user a question and waits for their response.\n *\n * Use this when you need more information or clarification from the user.\n */\nexport const askUser = createGadget({\n name: \"AskUser\",\n description:\n \"Ask the user a question when you need more information or clarification. The user's response will be provided back to you.\",\n schema: z.object({\n question: z.string().describe(\"The question to ask the user in plain-text or Markdown\"),\n }),\n examples: [\n {\n comment: \"Ask for clarification about the task\",\n params: { question: \"Which file would you like me to modify?\" },\n },\n {\n comment: \"Ask user to choose between options\",\n params: {\n question:\n \"I found multiple matches. Which one should I use?\\n- src/utils/helper.ts\\n- src/lib/helper.ts\",\n },\n },\n ],\n execute: ({ question }) => {\n throw new HumanInputRequiredException(question);\n },\n});\n\n/**\n * TellUser gadget - Outputs a message to the user.\n *\n * Use this for key results, warnings, or structured output that should stand out\n * from regular streamed text.\n */\nexport const tellUser = createGadget({\n name: \"TellUser\",\n description: \"Tell the user something important.\",\n schema: z.object({\n message: z.string().optional().describe(\"The message to display to the user in Markdown\"),\n type: z\n .enum([\"info\", \"success\", \"warning\", \"error\"])\n .default(\"info\")\n .describe(\"Message type: info, success, warning, or error\"),\n }),\n examples: [\n {\n comment: \"Warn the user about something\",\n params: {\n message: \"Found 3 files with potential issues. Continuing analysis...\",\n type: \"warning\",\n },\n },\n {\n comment: \"Share detailed analysis with bullet points (use heredoc for multiline)\",\n params: {\n message:\n \"Here's what I found in the codebase:\\n\\n1. **Main entry point**: `src/index.ts` exports all public APIs\\n2. **Core logic**: Located in `src/core/` with 5 modules\\n3. **Tests**: Good coverage in `src/__tests__/`\\n\\nI'll continue exploring the core modules.\",\n type: \"info\",\n },\n },\n ],\n execute: ({ message, type }) => {\n // Handle empty or missing message gracefully\n // This happens when LLM sends malformed parameters that fail to parse the message field\n if (!message || message.trim() === \"\") {\n return \"⚠️ TellUser was called without a message. Please provide content in the 'message' field.\";\n }\n\n // Format message for display, but return plain text for LLM context\n // This prevents ANSI color codes from polluting the conversation\n const prefixes = {\n info: \"ℹ️ \",\n success: \"✅ \",\n warning: \"⚠️ \",\n error: \"❌ \",\n };\n return prefixes[type] + message;\n },\n});\n\n/**\n * Finish gadget - Signals that the task is complete.\n *\n * Use this when you have completed all requested work and want to end the conversation.\n */\nexport const finish = createGadget({\n name: \"Finish\",\n description: \"Signal that you have completed your task. Call this when your work is done.\",\n schema: z.object({}),\n examples: [\n {\n comment: \"Signal task completion\",\n params: {},\n },\n ],\n execute: () => {\n throw new TaskCompletionSignal(\"Task completed\");\n },\n});\n\n/**\n * All built-in gadgets as an array for easy registration.\n */\nexport const builtinGadgets = [askUser, tellUser, finish];\n","/**\n * Subagent configuration resolution.\n *\n * Handles merging and resolving subagent configurations from multiple sources:\n * - Global `[subagents]` section\n * - Profile-level `[profile.subagents]` sections\n * - \"inherit\" keyword for model inheritance\n */\n\nimport type { SubagentConfig, SubagentConfigMap } from \"../gadgets/types.js\";\n\n/**\n * Special model value indicating the subagent should inherit from parent agent.\n */\nexport const INHERIT_MODEL = \"inherit\";\n\n/**\n * Global subagent configuration section from cli.toml.\n * Contains default-model and per-subagent configs.\n */\nexport interface GlobalSubagentConfig {\n /** Default model for all subagents (\"inherit\" or specific model) */\n \"default-model\"?: string;\n /** Per-subagent configurations */\n [subagentName: string]: SubagentConfig | string | undefined;\n}\n\n/**\n * Resolves a subagent's configuration by merging global and profile-level configs.\n *\n * Resolution priority (highest to lowest):\n * 1. Profile-level subagent config (`[profile.subagents.Name]`)\n * 2. Global subagent config (`[subagents.Name]`)\n * 3. Global default-model (`[subagents] default-model`)\n * 4. \"inherit\" (use parent model)\n *\n * @param subagentName - Name of the subagent (e.g., \"BrowseWeb\")\n * @param parentModel - Model used by the parent agent\n * @param profileConfig - Profile-level subagent config (from `[profile.subagents]`)\n * @param globalConfig - Global subagent config (from `[subagents]`)\n * @returns Resolved configuration with model resolved to actual value\n *\n * @example\n * ```typescript\n * const config = resolveSubagentConfig(\n * \"BrowseWeb\",\n * \"gemini-2.5-flash\",\n * { BrowseWeb: { maxIterations: 30 } },\n * { BrowseWeb: { model: \"inherit\", headless: true } }\n * );\n * // Result: { model: \"gemini-2.5-flash\", maxIterations: 30, headless: true }\n * ```\n */\nexport function resolveSubagentConfig(\n subagentName: string,\n parentModel: string,\n profileConfig?: SubagentConfigMap,\n globalConfig?: GlobalSubagentConfig,\n): SubagentConfig {\n const resolved: SubagentConfig = {};\n\n // Get global defaults\n const globalDefaultModel = globalConfig?.[\"default-model\"];\n const globalSubagent = extractSubagentConfig(globalConfig, subagentName);\n const profileSubagent = profileConfig?.[subagentName] ?? {};\n\n // Merge configs (profile overrides global)\n const merged = { ...globalSubagent, ...profileSubagent };\n\n // Resolve model with priority: merged > globalDefault > \"inherit\"\n const configModel = merged.model ?? globalDefaultModel ?? INHERIT_MODEL;\n\n // Apply \"inherit\" resolution\n resolved.model = configModel === INHERIT_MODEL ? parentModel : configModel;\n\n // Copy all other options (excluding model which we just resolved)\n for (const [key, value] of Object.entries(merged)) {\n if (key !== \"model\") {\n resolved[key] = value;\n }\n }\n\n return resolved;\n}\n\n/**\n * Builds a complete SubagentConfigMap with all subagents resolved.\n *\n * @param parentModel - Model used by the parent agent\n * @param profileConfig - Profile-level subagent configs\n * @param globalConfig - Global subagent configs\n * @returns Map of all resolved subagent configurations\n */\nexport function buildSubagentConfigMap(\n parentModel: string,\n profileConfig?: SubagentConfigMap,\n globalConfig?: GlobalSubagentConfig,\n): SubagentConfigMap {\n // Collect all subagent names from both sources\n const subagentNames = new Set<string>();\n\n if (globalConfig) {\n for (const key of Object.keys(globalConfig)) {\n if (key !== \"default-model\" && typeof globalConfig[key] === \"object\") {\n subagentNames.add(key);\n }\n }\n }\n\n if (profileConfig) {\n for (const key of Object.keys(profileConfig)) {\n subagentNames.add(key);\n }\n }\n\n // Resolve each subagent\n const result: SubagentConfigMap = {};\n for (const name of subagentNames) {\n result[name] = resolveSubagentConfig(name, parentModel, profileConfig, globalConfig);\n }\n\n return result;\n}\n\n/**\n * Extracts SubagentConfig from GlobalSubagentConfig for a specific subagent.\n * Handles the fact that GlobalSubagentConfig has mixed types (string for default-model).\n */\nfunction extractSubagentConfig(\n globalConfig: GlobalSubagentConfig | undefined,\n subagentName: string,\n): SubagentConfig {\n if (!globalConfig) {\n return {};\n }\n\n const value = globalConfig[subagentName];\n if (typeof value === \"object\" && value !== null) {\n return value as SubagentConfig;\n }\n\n return {};\n}\n","/**\n * File utilities for CLI multimodal input support.\n *\n * Provides functions to read and validate image and audio files\n * for use with multimodal LLM requests.\n */\n\nimport { readFile, stat } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\n\nimport {\n type AudioContentPart,\n type AudioMimeType,\n audioFromBuffer,\n detectAudioMimeType,\n detectImageMimeType,\n type ImageContentPart,\n type ImageMimeType,\n imageFromBuffer,\n} from \"../core/input-content.js\";\n\n/**\n * Default maximum file size: 50MB\n * This prevents accidentally loading very large files into memory.\n */\nexport const DEFAULT_MAX_FILE_SIZE = 50 * 1024 * 1024;\n\n/**\n * Options for file reading operations.\n */\nexport interface FileReadOptions {\n /**\n * Maximum allowed file size in bytes.\n * Files larger than this will throw an error.\n * Default: 50MB (DEFAULT_MAX_FILE_SIZE)\n */\n maxFileSize?: number;\n}\n\n/**\n * Format file size as human-readable string.\n */\nfunction formatFileSize(bytes: number): string {\n if (bytes < 1024) return `${bytes} bytes`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;\n}\n\n/**\n * Check file size before reading to prevent memory issues.\n */\nasync function checkFileSize(\n absolutePath: string,\n filePath: string,\n maxSize: number,\n): Promise<void> {\n const stats = await stat(absolutePath);\n if (stats.size > maxSize) {\n throw new Error(\n `File \"${filePath}\" is too large (${formatFileSize(stats.size)}). ` +\n `Maximum allowed size is ${formatFileSize(maxSize)}. ` +\n `Consider compressing the file or using a smaller version.`,\n );\n }\n}\n\n/**\n * Read and validate an image file.\n *\n * @param filePath - Path to image file (absolute or relative to cwd)\n * @param options - Optional configuration for file reading\n * @returns Image content part ready for LLM message\n * @throws Error if file doesn't exist, is too large, or isn't a valid image format\n *\n * @example\n * ```typescript\n * const imagePart = await readImageFile(\"./photo.jpg\");\n * const messages = [{ role: \"user\", content: [text(\"Describe this:\"), imagePart] }];\n * ```\n */\nexport async function readImageFile(\n filePath: string,\n options: FileReadOptions = {},\n): Promise<ImageContentPart> {\n const absolutePath = resolve(filePath);\n const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;\n\n let buffer: Buffer;\n try {\n await checkFileSize(absolutePath, filePath, maxFileSize);\n buffer = await readFile(absolutePath);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to read image file \"${filePath}\": ${message}`);\n }\n\n // Validate it's an image\n const mimeType = detectImageMimeType(buffer);\n if (!mimeType) {\n throw new Error(\n `File \"${filePath}\" is not a supported image format. ` +\n `Supported formats: JPEG, PNG, GIF, WebP`,\n );\n }\n\n return imageFromBuffer(buffer, mimeType);\n}\n\n/**\n * Read and validate an audio file.\n *\n * @param filePath - Path to audio file (absolute or relative to cwd)\n * @param options - Optional configuration for file reading\n * @returns Audio content part ready for LLM message\n * @throws Error if file doesn't exist, is too large, or isn't a valid audio format\n *\n * @example\n * ```typescript\n * const audioPart = await readAudioFile(\"./recording.mp3\");\n * const messages = [{ role: \"user\", content: [text(\"Transcribe:\"), audioPart] }];\n * ```\n */\nexport async function readAudioFile(\n filePath: string,\n options: FileReadOptions = {},\n): Promise<AudioContentPart> {\n const absolutePath = resolve(filePath);\n const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;\n\n let buffer: Buffer;\n try {\n await checkFileSize(absolutePath, filePath, maxFileSize);\n buffer = await readFile(absolutePath);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to read audio file \"${filePath}\": ${message}`);\n }\n\n // Validate it's audio\n const mimeType = detectAudioMimeType(buffer);\n if (!mimeType) {\n throw new Error(\n `File \"${filePath}\" is not a supported audio format. ` +\n `Supported formats: MP3, WAV, OGG, WebM`,\n );\n }\n\n return audioFromBuffer(buffer, mimeType);\n}\n\n/**\n * Read a file as raw buffer for multimodal input.\n * Use this when you need the raw data without converting to content parts.\n *\n * @param filePath - Path to file (absolute or relative to cwd)\n * @param options - Optional configuration for file reading\n * @returns File contents as Buffer\n * @throws Error if file doesn't exist, is too large, or can't be read\n */\nexport async function readFileBuffer(\n filePath: string,\n options: FileReadOptions = {},\n): Promise<Buffer> {\n const absolutePath = resolve(filePath);\n const maxFileSize = options.maxFileSize ?? DEFAULT_MAX_FILE_SIZE;\n\n try {\n await checkFileSize(absolutePath, filePath, maxFileSize);\n return await readFile(absolutePath);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to read file \"${filePath}\": ${message}`);\n }\n}\n\n/**\n * Validate that a file exists and has a supported image format.\n *\n * @param filePath - Path to file to validate\n * @returns Object with validation result and detected MIME type\n */\nexport async function validateImageFile(\n filePath: string,\n): Promise<{ valid: boolean; mimeType?: ImageMimeType; error?: string }> {\n try {\n const absolutePath = resolve(filePath);\n const buffer = await readFile(absolutePath);\n const mimeType = detectImageMimeType(buffer);\n\n if (!mimeType) {\n return {\n valid: false,\n error: \"Not a supported image format (JPEG, PNG, GIF, WebP)\",\n };\n }\n\n return { valid: true, mimeType };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { valid: false, error: message };\n }\n}\n\n/**\n * Validate that a file exists and has a supported audio format.\n *\n * @param filePath - Path to file to validate\n * @returns Object with validation result and detected MIME type\n */\nexport async function validateAudioFile(\n filePath: string,\n): Promise<{ valid: boolean; mimeType?: AudioMimeType; error?: string }> {\n try {\n const absolutePath = resolve(filePath);\n const buffer = await readFile(absolutePath);\n const mimeType = detectAudioMimeType(buffer);\n\n if (!mimeType) {\n return {\n valid: false,\n error: \"Not a supported audio format (MP3, WAV, OGG, WebM)\",\n };\n }\n\n return { valid: true, mimeType };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { valid: false, error: message };\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { AbstractGadget } from \"../gadgets/gadget.js\";\nimport { getBuiltinGadget, isBuiltinGadgetName } from \"./builtins/index.js\";\nimport { isExternalPackageSpecifier, loadExternalGadgets } from \"./external-gadgets.js\";\n\n/**\n * Function type for importing modules dynamically.\n */\nexport type GadgetImportFunction = (specifier: string) => Promise<unknown>;\n\nconst PATH_PREFIXES = [\".\", \"/\", \"~\"];\nconst BUILTIN_PREFIX = \"builtin:\";\n\n/**\n * Duck-type check if a value looks like a Gadget instance.\n * This avoids instanceof issues when gadgets are loaded from external files\n * that import from the 'llmist' npm package (different class instance).\n */\nfunction isGadgetLike(value: unknown): value is AbstractGadget {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n const obj = value as Record<string, unknown>;\n return (\n typeof obj.execute === \"function\" &&\n typeof obj.description === \"string\" &&\n (\"parameterSchema\" in obj || \"schema\" in obj)\n );\n}\n\n/**\n * Type guard to check if a value is a Gadget constructor.\n * Checks if the prototype has an execute method (gadget classes created via Gadget()\n * factory put description/schema on instances, not prototype, so we just check for execute).\n *\n * @param value - Value to check\n * @returns True if value is a Gadget constructor\n */\nfunction isGadgetConstructor(value: unknown): value is new () => AbstractGadget {\n if (typeof value !== \"function\") {\n return false;\n }\n\n const prototype = value.prototype as unknown;\n if (!prototype) {\n return false;\n }\n\n // Check for AbstractGadget inheritance (works for same package)\n if (prototype instanceof AbstractGadget) {\n return true;\n }\n\n // Duck typing: check if prototype has execute method\n // Gadget classes from external packages may not pass instanceof but have execute\n const proto = prototype as Record<string, unknown>;\n if (typeof proto.execute === \"function\") {\n return true;\n }\n\n // Also check if prototype looks like a gadget (for edge cases)\n return isGadgetLike(prototype);\n}\n\n/**\n * Expands ~ to the user's home directory.\n *\n * @param input - Path that may start with ~\n * @returns Expanded path with HOME directory\n */\nfunction expandHomePath(input: string): string {\n if (!input.startsWith(\"~\")) {\n return input;\n }\n\n const home = process.env.HOME;\n if (!home) {\n return input;\n }\n\n return path.join(home, input.slice(1));\n}\n\n/**\n * Determines if a specifier is a file path vs npm module name.\n * File paths start with ., /, ~ or contain path separators.\n *\n * @param specifier - Module specifier to check\n * @returns True if specifier represents a file path\n */\nfunction isFileLikeSpecifier(specifier: string): boolean {\n return (\n PATH_PREFIXES.some((prefix) => specifier.startsWith(prefix)) || specifier.includes(path.sep)\n );\n}\n\n/**\n * Attempts to resolve a specifier as a built-in gadget.\n * Handles both explicit \"builtin:\" prefix and bare names that match built-in gadgets.\n *\n * @param specifier - The gadget specifier to check\n * @returns The built-in gadget if found, null otherwise\n * @throws Error if \"builtin:\" prefix is used but gadget doesn't exist\n */\nexport function tryResolveBuiltin(specifier: string): AbstractGadget | null {\n // Handle explicit builtin: prefix\n if (specifier.startsWith(BUILTIN_PREFIX)) {\n const name = specifier.slice(BUILTIN_PREFIX.length);\n const gadget = getBuiltinGadget(name);\n if (!gadget) {\n throw new Error(\n `Unknown builtin gadget: ${name}. Available builtins: ListDirectory, ReadFile, WriteFile, EditFile, RunCommand`,\n );\n }\n return gadget;\n }\n\n // For non-file-path specifiers, check builtins first\n if (!isFileLikeSpecifier(specifier) && isBuiltinGadgetName(specifier)) {\n return getBuiltinGadget(specifier)!;\n }\n\n return null;\n}\n\n/**\n * Resolves a gadget specifier to either a file URL or npm module name.\n * File paths are resolved relative to cwd and converted to file:// URLs.\n *\n * @param specifier - Original gadget specifier (file path or module name)\n * @param cwd - Current working directory for resolving relative paths\n * @returns Resolved specifier (file:// URL for files, module name for packages)\n * @throws Error if file path doesn't exist\n */\nexport function resolveGadgetSpecifier(specifier: string, cwd: string): string {\n if (!isFileLikeSpecifier(specifier)) {\n return specifier;\n }\n\n const expanded = expandHomePath(specifier);\n const resolvedPath = path.resolve(cwd, expanded);\n if (!fs.existsSync(resolvedPath)) {\n throw new Error(`Gadget module not found at ${resolvedPath}`);\n }\n return pathToFileURL(resolvedPath).href;\n}\n\n/**\n * Recursively extracts all Gadget instances and classes from a module's exports.\n * Searches default export, named exports, nested objects, and arrays.\n * Automatically instantiates Gadget classes.\n *\n * @param moduleExports - Module exports object to search\n * @returns Array of Gadget instances found in exports\n */\nexport function extractGadgetsFromModule(moduleExports: unknown): AbstractGadget[] {\n const results: AbstractGadget[] = [];\n const visited = new Set<unknown>();\n\n const visit = (value: unknown) => {\n if (value === undefined || value === null) {\n return;\n }\n\n if (visited.has(value)) {\n return;\n }\n visited.add(value);\n\n // Use duck typing to handle gadgets from external packages\n if (value instanceof AbstractGadget || isGadgetLike(value)) {\n results.push(value as AbstractGadget);\n return;\n }\n\n if (isGadgetConstructor(value)) {\n results.push(new value());\n return;\n }\n\n if (Array.isArray(value)) {\n for (const entry of value) {\n visit(entry);\n }\n return;\n }\n\n if (typeof value === \"object\") {\n for (const entry of Object.values(value as Record<string, unknown>)) {\n visit(entry);\n }\n }\n };\n\n visit(moduleExports);\n return results;\n}\n\n/**\n * Loads gadgets from one or more specifiers.\n * Supports built-in gadgets, file paths, npm module names, and external packages.\n *\n * Resolution order:\n * 1. \"builtin:Name\" - explicit built-in lookup (error if not found)\n * 2. Bare \"Name\" without path chars - check built-in registry first\n * 3. External packages (npm/git) - auto-install and load from cache\n * - \"webasto\" - npm package, all gadgets\n * - \"webasto@2.0.0\" - npm package with version\n * - \"webasto:minimal\" - npm package with preset\n * - \"webasto/Navigate\" - npm package with specific gadget\n * - \"git+https://...\" - git URL\n * 4. File paths (starting with ., /, ~) - resolve and import\n * 5. npm module names - dynamic import from node_modules\n *\n * @param specifiers - Array of gadget specifiers\n * @param cwd - Current working directory for resolving relative paths\n * @param importer - Function to dynamically import modules (default: native import)\n * @returns Array of loaded Gadget instances\n * @throws Error if module fails to load, contains no gadgets, or initialization fails\n */\nexport async function loadGadgets(\n specifiers: string[],\n cwd: string,\n importer: GadgetImportFunction = (specifier) => import(specifier),\n): Promise<AbstractGadget[]> {\n const gadgets: AbstractGadget[] = [];\n // Track if we're using a custom importer (for testing) - skip external package resolution\n const usingDefaultImporter = importer.toString().includes(\"import(specifier)\");\n\n for (const specifier of specifiers) {\n // Try builtin resolution first\n const builtin = tryResolveBuiltin(specifier);\n if (builtin) {\n gadgets.push(builtin);\n continue;\n }\n\n // Try external package resolution (npm/git with presets, versions, etc.)\n // Skip this when using a custom importer (for testing)\n if (usingDefaultImporter && isExternalPackageSpecifier(specifier)) {\n try {\n const externalGadgets = await loadExternalGadgets(specifier);\n gadgets.push(...externalGadgets);\n continue;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to load external package '${specifier}': ${message}`);\n }\n }\n\n // Fall back to file/npm resolution\n const resolved = resolveGadgetSpecifier(specifier, cwd);\n let exports: unknown;\n try {\n exports = await importer(resolved);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to load gadget module '${specifier}': ${message}`);\n }\n\n let extracted: AbstractGadget[];\n try {\n extracted = extractGadgetsFromModule(exports);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to initialize gadgets from module '${specifier}': ${message}`);\n }\n if (extracted.length === 0) {\n throw new Error(`Module '${specifier}' does not export any Gadget instances.`);\n }\n gadgets.push(...extracted);\n }\n\n return gadgets;\n}\n","import { z } from \"zod\";\nimport { createGadget } from \"../../../index.js\";\nimport { validatePathIsWithinCwd } from \"./utils.js\";\n\n/**\n * EditFile gadget - Edit files using ed commands.\n * Shell escape commands (!) are filtered for security.\n */\nfunction filterDangerousCommands(commands: string): string {\n return commands\n .split(\"\\n\")\n .filter((line) => !line.trimStart().startsWith(\"!\"))\n .join(\"\\n\");\n}\n\nexport const editFile = createGadget({\n name: \"EditFile\",\n description:\n \"Edit a file using ed commands. Ed is a line-oriented text editor - pipe commands to it for precise file modifications. Commands are executed in sequence. Remember to end with 'w' (write) and 'q' (quit). Shell escape commands (!) are filtered for security.\",\n schema: z.object({\n filePath: z.string().describe(\"Path to the file to edit (relative or absolute)\"),\n commands: z.string().describe(\"Ed commands to execute, one per line\"),\n }),\n examples: [\n {\n params: {\n filePath: \"config.txt\",\n commands: `1,$p\nq`,\n },\n output: \"path=config.txt\\n\\n32\\nkey=value\\noption=true\",\n comment: \"Print entire file contents (ed shows byte count, then content)\",\n },\n {\n params: {\n filePath: \"data.txt\",\n commands: `1,$s/foo/bar/g\nw\nq`,\n },\n output: \"path=data.txt\\n\\n42\\n42\",\n comment: \"Replace all 'foo' with 'bar' (ed shows bytes read, then bytes written)\",\n },\n {\n params: {\n filePath: \"list.txt\",\n commands: `3d\nw\nq`,\n },\n output: \"path=list.txt\\n\\n45\\n28\",\n comment: \"Delete line 3, save and quit\",\n },\n {\n params: {\n filePath: \"readme.txt\",\n commands: `$a\nNew last line\n.\nw\nq`,\n },\n output: \"path=readme.txt\\n\\n40\\n56\",\n comment: \"Append text after last line ($ = last line, . = end input mode)\",\n },\n ],\n timeoutMs: 30000,\n execute: async ({ filePath, commands }) => {\n const validatedPath = validatePathIsWithinCwd(filePath);\n const safeCommands = filterDangerousCommands(commands);\n\n try {\n const proc = Bun.spawn([\"ed\", validatedPath], {\n stdin: \"pipe\",\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n\n // Write commands to ed's stdin\n proc.stdin.write(`${safeCommands}\\n`);\n proc.stdin.end();\n\n // Create timeout promise (30 seconds) with cleanup capability\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n proc.kill();\n reject(new Error(\"ed command timed out after 30000ms\"));\n }, 30000);\n });\n\n // Wait for process and consume streams concurrently to prevent deadlock.\n // If we await proc.exited first, large output can fill pipe buffers,\n // causing the process to block on write while we block on exit.\n const [exitCode, stdout, stderr] = await Promise.race([\n Promise.all([\n proc.exited,\n new Response(proc.stdout).text(),\n new Response(proc.stderr).text(),\n ]),\n timeoutPromise,\n ]);\n\n // Clear timeout on normal exit to prevent dangling timer\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n const output = [stdout, stderr].filter(Boolean).join(\"\\n\").trim();\n\n if (exitCode !== 0) {\n return `path=${filePath}\\n\\n${output || \"ed exited with non-zero status\"}`;\n }\n\n return `path=${filePath}\\n\\n${output || \"(no output)\"}`;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return `path=${filePath}\\n\\nerror: ${message}`;\n }\n },\n});\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\n/**\n * Exception thrown when a path validation fails due to sandbox constraints.\n * This ensures all file operations are restricted to the current working directory.\n */\nexport class PathSandboxException extends Error {\n constructor(inputPath: string, reason: string) {\n super(`Path access denied: ${inputPath}. ${reason}`);\n this.name = \"PathSandboxException\";\n }\n}\n\n/**\n * Validates that a given path is within the current working directory.\n * This prevents directory traversal attacks and ensures all file operations\n * are sandboxed to the CWD and its subdirectories.\n *\n * @param inputPath - Path to validate (can be relative or absolute)\n * @returns The validated absolute path\n * @throws PathSandboxException if the path is outside the CWD\n * @throws Error for other file system errors\n */\nexport function validatePathIsWithinCwd(inputPath: string): string {\n const cwd = process.cwd();\n const resolvedPath = path.resolve(cwd, inputPath);\n\n // Try to get the real path to handle symlinks securely\n let finalPath: string;\n try {\n finalPath = fs.realpathSync(resolvedPath);\n } catch (error) {\n // If path doesn't exist, use the resolved path for validation\n const nodeError = error as NodeJS.ErrnoException;\n if (nodeError.code === \"ENOENT\") {\n finalPath = resolvedPath;\n } else {\n // Re-throw other errors (permission denied, etc.)\n throw error;\n }\n }\n\n // Ensure the path is within CWD or is CWD itself\n // Use path.sep to prevent matching partial directory names\n const cwdWithSep = cwd + path.sep;\n if (!finalPath.startsWith(cwdWithSep) && finalPath !== cwd) {\n throw new PathSandboxException(inputPath, \"Path is outside the current working directory\");\n }\n\n return finalPath;\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { createGadget } from \"../../../index.js\";\nimport { validatePathIsWithinCwd } from \"./utils.js\";\n\n/**\n * Represents metadata for a file system entry\n */\ninterface FileEntry {\n name: string;\n relativePath: string;\n type: \"file\" | \"directory\" | \"symlink\";\n size: number;\n modified: number; // Unix epoch seconds\n}\n\n/**\n * Lists all files and directories in a given path with optional recursion.\n * Skips entries that cannot be accessed due to permissions.\n *\n * @param dirPath - Absolute path to the directory\n * @param basePath - Base path for calculating relative paths (defaults to dirPath)\n * @param maxDepth - Maximum depth to recurse (1 = immediate children only)\n * @param currentDepth - Current recursion depth (internal use)\n * @returns Array of file entries with metadata\n */\nfunction listFiles(\n dirPath: string,\n basePath: string = dirPath,\n maxDepth: number = 1,\n currentDepth: number = 1,\n): FileEntry[] {\n const entries: FileEntry[] = [];\n\n try {\n const items = fs.readdirSync(dirPath);\n\n for (const item of items) {\n const fullPath = path.join(dirPath, item);\n const relativePath = path.relative(basePath, fullPath);\n\n try {\n const stats = fs.lstatSync(fullPath);\n let type: \"file\" | \"directory\" | \"symlink\";\n let size: number;\n\n if (stats.isSymbolicLink()) {\n type = \"symlink\";\n size = 0;\n } else if (stats.isDirectory()) {\n type = \"directory\";\n size = 0;\n } else {\n type = \"file\";\n size = stats.size;\n }\n\n entries.push({\n name: item,\n relativePath,\n type,\n size,\n modified: Math.floor(stats.mtime.getTime() / 1000),\n });\n\n // Recurse into directories if we haven't reached max depth\n if (type === \"directory\" && currentDepth < maxDepth) {\n // Validate subdirectory is still within CWD (security check)\n try {\n validatePathIsWithinCwd(fullPath);\n const subEntries = listFiles(fullPath, basePath, maxDepth, currentDepth + 1);\n entries.push(...subEntries);\n } catch {\n // Skip directories outside CWD or inaccessible\n }\n }\n } catch {\n // Skip entries that can't be accessed (permission denied, etc.)\n }\n }\n } catch {\n // If we can't read the directory, return empty array\n return [];\n }\n\n return entries;\n}\n\n/**\n * Formats age from Unix epoch timestamp to human-readable string.\n * Uses compact format: 5m, 2h, 3d, 2w, 4mo, 1y\n *\n * @param epochSeconds - Unix timestamp in seconds\n * @returns Compact age string\n */\nfunction formatAge(epochSeconds: number): string {\n const now = Math.floor(Date.now() / 1000);\n const seconds = now - epochSeconds;\n\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h`;\n const days = Math.floor(hours / 24);\n if (days < 7) return `${days}d`;\n const weeks = Math.floor(days / 7);\n if (weeks < 4) return `${weeks}w`;\n const months = Math.floor(days / 30);\n if (months < 12) return `${months}mo`;\n const years = Math.floor(days / 365);\n return `${years}y`;\n}\n\n/**\n * Formats file entries as a compact pipe-separated DSL.\n * Format: #T|N|S|A header (Type, Name, Size, Age)\n * Optimized for LLM token efficiency (~70% savings vs table format).\n *\n * @param entries - Array of file entries to format\n * @returns Compact DSL string\n */\nfunction formatEntriesAsString(entries: FileEntry[]): string {\n if (entries.length === 0) {\n return \"#empty\";\n }\n\n // Sort: directories first, then files, then symlinks, alphabetically within each\n const sortedEntries = [...entries].sort((a, b) => {\n const typeOrder = { directory: 0, file: 1, symlink: 2 };\n const typeCompare = typeOrder[a.type] - typeOrder[b.type];\n if (typeCompare !== 0) return typeCompare;\n return a.relativePath.localeCompare(b.relativePath);\n });\n\n // Type code mapping\n const typeCode: Record<FileEntry[\"type\"], string> = {\n directory: \"D\",\n file: \"F\",\n symlink: \"L\",\n };\n\n // URL-encode special chars that would break parsing\n const encodeName = (name: string) => name.replace(/\\|/g, \"%7C\").replace(/\\n/g, \"%0A\");\n\n // Build compact output\n const header = \"#T|N|S|A\";\n const rows = sortedEntries.map(\n (e) => `${typeCode[e.type]}|${encodeName(e.relativePath)}|${e.size}|${formatAge(e.modified)}`,\n );\n\n return [header, ...rows].join(\"\\n\");\n}\n\n/**\n * ListDirectory gadget - Lists files and directories with full metadata.\n * All directory paths are validated to be within the current working directory.\n */\nexport const listDirectory = createGadget({\n name: \"ListDirectory\",\n description:\n \"List files and directories in a directory with full details (names, types, sizes, modification dates). Use maxDepth to explore subdirectories recursively. The directory path must be within the current working directory or its subdirectories.\",\n schema: z.object({\n directoryPath: z.string().default(\".\").describe(\"Path to the directory to list\"),\n maxDepth: z\n .number()\n .int()\n .min(1)\n .max(10)\n .default(1)\n .describe(\n \"Maximum depth to recurse (1 = immediate children only, 2 = include grandchildren, etc.)\",\n ),\n }),\n examples: [\n {\n params: { directoryPath: \".\", maxDepth: 1 },\n output: \"path=. maxDepth=1\\n\\n#T|N|S|A\\nD|src|0|2h\\nD|tests|0|1d\\nF|package.json|2841|3h\",\n comment: \"List current directory\",\n },\n {\n params: { directoryPath: \"src\", maxDepth: 2 },\n output:\n \"path=src maxDepth=2\\n\\n#T|N|S|A\\nD|components|0|1d\\nD|utils|0|2d\\nF|index.ts|512|1h\\nF|components/Button.tsx|1024|3h\",\n comment: \"List src directory recursively\",\n },\n ],\n execute: ({ directoryPath, maxDepth }) => {\n // Validate path is within CWD\n const validatedPath = validatePathIsWithinCwd(directoryPath);\n\n // Verify it's actually a directory\n const stats = fs.statSync(validatedPath);\n if (!stats.isDirectory()) {\n throw new Error(`Path is not a directory: ${directoryPath}`);\n }\n\n // List files and format output\n const entries = listFiles(validatedPath, validatedPath, maxDepth);\n const formattedList = formatEntriesAsString(entries);\n\n // Show params on first line, listing follows\n return `path=${directoryPath} maxDepth=${maxDepth}\\n\\n${formattedList}`;\n },\n});\n","import fs from \"node:fs\";\nimport { z } from \"zod\";\nimport { createGadget } from \"../../../index.js\";\nimport { validatePathIsWithinCwd } from \"./utils.js\";\n\n/**\n * ReadFile gadget - Reads the entire content of a file and returns it as text.\n * All file paths are validated to be within the current working directory.\n */\nexport const readFile = createGadget({\n name: \"ReadFile\",\n description:\n \"Read the entire content of a file and return it as text. The file path must be within the current working directory or its subdirectories.\",\n schema: z.object({\n filePath: z.string().describe(\"Path to the file to read (relative or absolute)\"),\n }),\n examples: [\n {\n params: { filePath: \"package.json\" },\n output: 'path=package.json\\n\\n{\\n \"name\": \"my-project\",\\n \"version\": \"1.0.0\"\\n ...\\n}',\n comment: \"Read a JSON config file\",\n },\n {\n params: { filePath: \"src/index.ts\" },\n output: \"path=src/index.ts\\n\\nexport function main() { ... }\",\n comment: \"Read a source file\",\n },\n ],\n execute: ({ filePath }) => {\n // Validate path is within CWD\n const validatedPath = validatePathIsWithinCwd(filePath);\n\n // Read and return file content\n const content = fs.readFileSync(validatedPath, \"utf-8\");\n\n // Show params on first line, content follows\n return `path=${filePath}\\n\\n${content}`;\n },\n});\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { z } from \"zod\";\nimport { createGadget } from \"../../../index.js\";\nimport { validatePathIsWithinCwd } from \"./utils.js\";\n\n/**\n * WriteFile gadget - Writes content to a file.\n * Creates parent directories if needed. Overwrites existing files.\n * All file paths are validated to be within the current working directory.\n */\nexport const writeFile = createGadget({\n name: \"WriteFile\",\n description:\n \"Write content to a file. Creates parent directories if needed. Overwrites existing files. The file path must be within the current working directory or its subdirectories.\",\n schema: z.object({\n filePath: z.string().describe(\"Path to the file to write (relative or absolute)\"),\n content: z.string().describe(\"Content to write to the file\"),\n }),\n examples: [\n {\n params: { filePath: \"output.txt\", content: \"Hello, World!\" },\n output: \"path=output.txt\\n\\nWrote 13 bytes\",\n comment: \"Write a simple text file\",\n },\n {\n params: {\n filePath: \"src/server.ts\",\n content: `import { serve } from \"bun\";\n\nconst port = 3000;\n\nserve({\n port,\n fetch: (req) => new Response(\\`Hello from \\${req.url}\\`),\n});\n\nconsole.log(\\`Server running on http://localhost:\\${port}\\`);`,\n },\n output: \"path=src/server.ts\\n\\nWrote 198 bytes (created directory: src)\",\n comment:\n \"Write code with template literals - NO escaping needed inside heredoc (use <<<EOF...EOF)\",\n },\n ],\n execute: ({ filePath, content }) => {\n // Validate path is within CWD\n const validatedPath = validatePathIsWithinCwd(filePath);\n\n // Ensure parent directory exists (create if needed)\n const parentDir = path.dirname(validatedPath);\n let createdDir = false;\n if (!fs.existsSync(parentDir)) {\n // Validate parent dir is also within CWD before creating\n validatePathIsWithinCwd(parentDir);\n fs.mkdirSync(parentDir, { recursive: true });\n createdDir = true;\n }\n\n // Write the file\n fs.writeFileSync(validatedPath, content, \"utf-8\");\n const bytesWritten = Buffer.byteLength(content, \"utf-8\");\n\n // Format output following the established pattern\n const dirNote = createdDir ? ` (created directory: ${path.dirname(filePath)})` : \"\";\n return `path=${filePath}\\n\\nWrote ${bytesWritten} bytes${dirNote}`;\n },\n});\n","import { z } from \"zod\";\nimport { createGadget } from \"../../index.js\";\n\n/**\n * RunCommand gadget - Executes a command with arguments and returns its output.\n *\n * Uses argv array to bypass shell interpretation entirely - arguments are\n * passed directly to the process without any escaping or shell expansion.\n * This allows special characters (quotes, backticks, newlines) to work correctly.\n *\n * Safety should be added externally via the hook system (see example 10).\n *\n * Output format follows the established pattern: `status=N\\n\\n<output>`\n */\nexport const runCommand = createGadget({\n name: \"RunCommand\",\n description:\n \"Execute a command with arguments and return its output. Uses argv array to bypass shell - arguments are passed directly without interpretation. Returns stdout/stderr combined with exit status.\",\n schema: z.object({\n argv: z\n .array(z.string())\n .describe(\"Command and arguments as array (e.g., ['git', 'commit', '-m', 'message'])\"),\n cwd: z\n .string()\n .optional()\n .describe(\"Working directory for the command (default: current directory)\"),\n timeout: z.number().default(30000).describe(\"Timeout in milliseconds (default: 30000)\"),\n }),\n examples: [\n {\n params: { argv: [\"ls\", \"-la\"], timeout: 30000 },\n output:\n \"status=0\\n\\ntotal 24\\ndrwxr-xr-x 5 user staff 160 Nov 27 10:00 .\\ndrwxr-xr-x 3 user staff 96 Nov 27 09:00 ..\\n-rw-r--r-- 1 user staff 1024 Nov 27 10:00 package.json\",\n comment: \"List directory contents with details\",\n },\n {\n params: { argv: [\"echo\", \"Hello World\"], timeout: 30000 },\n output: \"status=0\\n\\nHello World\",\n comment: \"Echo without shell - argument passed directly\",\n },\n {\n params: { argv: [\"cat\", \"nonexistent.txt\"], timeout: 30000 },\n output: \"status=1\\n\\ncat: nonexistent.txt: No such file or directory\",\n comment: \"Command that fails returns non-zero status\",\n },\n {\n params: { argv: [\"pwd\"], cwd: \"/tmp\", timeout: 30000 },\n output: \"status=0\\n\\n/tmp\",\n comment: \"Execute command in a specific directory\",\n },\n {\n params: {\n argv: [\n \"gh\",\n \"pr\",\n \"review\",\n \"123\",\n \"--comment\",\n \"--body\",\n \"Review with `backticks` and 'quotes'\",\n ],\n timeout: 30000,\n },\n output: \"status=0\\n\\n(no output)\",\n comment: \"Complex arguments with special characters - no escaping needed\",\n },\n {\n params: {\n argv: [\n \"gh\",\n \"pr\",\n \"review\",\n \"123\",\n \"--approve\",\n \"--body\",\n \"## Review Summary\\n\\n**Looks good!**\\n\\n- Clean code\\n- Tests pass\",\n ],\n timeout: 30000,\n },\n output: \"status=0\\n\\nApproving pull request #123\",\n comment: \"Multiline body: --body flag and content must be SEPARATE array elements\",\n },\n ],\n execute: async ({ argv, cwd, timeout }) => {\n const workingDir = cwd ?? process.cwd();\n\n if (argv.length === 0) {\n return \"status=1\\n\\nerror: argv array cannot be empty\";\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n try {\n // Spawn process directly without shell - arguments passed as-is\n const proc = Bun.spawn(argv, {\n cwd: workingDir,\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n\n // Create a timeout promise with cleanup\n const timeoutPromise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n proc.kill();\n reject(new Error(`Command timed out after ${timeout}ms`));\n }, timeout);\n });\n\n // Wait for process and consume streams concurrently to prevent deadlock.\n // If we await proc.exited first, large output can fill pipe buffers,\n // causing the process to block on write while we block on exit.\n const [exitCode, stdout, stderr] = await Promise.race([\n Promise.all([\n proc.exited,\n new Response(proc.stdout).text(),\n new Response(proc.stderr).text(),\n ]),\n timeoutPromise,\n ]);\n\n // Clear timeout on normal exit to prevent dangling timer\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n // Combine output (stdout first, then stderr if any)\n const output = [stdout, stderr].filter(Boolean).join(\"\\n\").trim();\n\n return `status=${exitCode}\\n\\n${output || \"(no output)\"}`;\n } catch (error) {\n // Clear timeout on error path too\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n const message = error instanceof Error ? error.message : String(error);\n return `status=1\\n\\nerror: ${message}`;\n }\n },\n});\n","/**\n * Built-in gadgets registry.\n * These gadgets can be referenced by name (e.g., \"ListDirectory\") or\n * with the explicit \"builtin:\" prefix (e.g., \"builtin:ListDirectory\").\n */\n\nimport type { AbstractGadget } from \"../../gadgets/gadget.js\";\nimport { editFile } from \"./filesystem/edit-file.js\";\nimport { listDirectory } from \"./filesystem/list-directory.js\";\nimport { readFile } from \"./filesystem/read-file.js\";\nimport { writeFile } from \"./filesystem/write-file.js\";\nimport { runCommand } from \"./run-command.js\";\n\n/**\n * Registry mapping gadget names to their instances.\n * Names are case-sensitive and match the gadget's declared name.\n */\nexport const builtinGadgetRegistry: Record<string, AbstractGadget> = {\n ListDirectory: listDirectory,\n ReadFile: readFile,\n WriteFile: writeFile,\n EditFile: editFile,\n RunCommand: runCommand,\n};\n\n/**\n * Gets a built-in gadget by name.\n *\n * @param name - The gadget name (e.g., \"ListDirectory\")\n * @returns The gadget instance, or undefined if not found\n */\nexport function getBuiltinGadget(name: string): AbstractGadget | undefined {\n return builtinGadgetRegistry[name];\n}\n\n/**\n * Checks if a name corresponds to a built-in gadget.\n *\n * @param name - The name to check\n * @returns True if the name is a registered built-in gadget\n */\nexport function isBuiltinGadgetName(name: string): boolean {\n return name in builtinGadgetRegistry;\n}\n\n/**\n * Gets all available built-in gadget names.\n *\n * @returns Array of built-in gadget names\n */\nexport function getBuiltinGadgetNames(): string[] {\n return Object.keys(builtinGadgetRegistry);\n}\n\n// Re-export individual gadgets for direct imports\nexport { listDirectory, readFile, writeFile, editFile, runCommand };\n","/**\n * External gadget loader for llmist CLI.\n *\n * Supports loading gadgets from:\n * - npm packages (with auto-installation)\n * - git URLs\n * - Manifest-based presets and individual gadget selection\n *\n * @module cli/external-gadgets\n */\n\nimport { execSync, spawnSync } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { pathToFileURL } from \"node:url\";\n\nimport type { AbstractGadget } from \"../gadgets/gadget.js\";\nimport { extractGadgetsFromModule } from \"./gadgets.js\";\n\n/**\n * Cache directory for external gadget packages.\n */\nconst CACHE_DIR = path.join(os.homedir(), \".llmist\", \"gadget-cache\");\n\n/**\n * Parsed gadget specifier.\n */\nexport interface GadgetSpecifier {\n type: \"npm\" | \"git\";\n /** Package name (npm) or URL (git) */\n package: string;\n /** Version or git ref */\n version?: string;\n /** Preset name (e.g., \"minimal\", \"readonly\") */\n preset?: string;\n /** Individual gadget name (e.g., \"Navigate\") */\n gadgetName?: string;\n}\n\n/**\n * Manifest structure from package.json llmist field.\n */\nexport interface LlmistManifest {\n /** Entry point for all gadgets */\n gadgets?: string;\n /** Factory function entry point */\n factory?: string;\n /** Subagent definitions */\n subagents?: Record<\n string,\n {\n entryPoint: string;\n export: string;\n description?: string;\n uses?: string[];\n defaultModel?: string;\n maxIterations?: number;\n }\n >;\n /** Preset definitions */\n presets?: Record<string, string[] | \"*\">;\n /** Session factory info */\n session?: {\n factory: string;\n type: string;\n };\n}\n\n/**\n * Check if a specifier is an external package (npm or git).\n */\nexport function isExternalPackageSpecifier(specifier: string): boolean {\n // npm package patterns\n if (/^@?[a-z0-9][\\w.-]*(?:@[\\w.-]+)?(?::[a-z]+)?(?:\\/\\w+)?$/i.test(specifier)) {\n return true;\n }\n // git URL patterns\n if (specifier.startsWith(\"git+\")) {\n return true;\n }\n return false;\n}\n\n/**\n * Parse a gadget specifier into its components.\n *\n * Supported formats:\n * - `webasto` - npm package, all gadgets\n * - `webasto@2.0.0` - npm package with version\n * - `webasto:minimal` - npm package with preset\n * - `webasto/Navigate` - npm package with specific gadget\n * - `webasto@2.0.0:minimal` - all combined\n * - `git+https://github.com/user/repo` - git URL\n * - `git+https://github.com/user/repo#v1.0.0` - git URL with ref\n */\nexport function parseGadgetSpecifier(specifier: string): GadgetSpecifier | null {\n // Git URL\n if (specifier.startsWith(\"git+\")) {\n const url = specifier.slice(4);\n const [baseUrl, ref] = url.split(\"#\");\n return {\n type: \"git\",\n package: baseUrl,\n version: ref,\n };\n }\n\n // npm package with optional version, preset, and gadget name\n // Format: package[@version][:preset][/gadgetName]\n const npmMatch = specifier.match(\n /^(@?[a-z0-9][\\w.-]*)(?:@([\\w.-]+))?(?::([a-z]+))?(?:\\/(\\w+))?$/i,\n );\n\n if (npmMatch) {\n const [, pkg, version, preset, gadgetName] = npmMatch;\n return {\n type: \"npm\",\n package: pkg,\n version,\n preset,\n gadgetName,\n };\n }\n\n return null;\n}\n\n/**\n * Get the cache directory for a package.\n */\nfunction getCacheDir(spec: GadgetSpecifier): string {\n const versionSuffix = spec.version ? `@${spec.version}` : \"@latest\";\n\n if (spec.type === \"npm\") {\n return path.join(CACHE_DIR, \"npm\", `${spec.package}${versionSuffix}`);\n }\n // git: sanitize URL for filesystem\n const sanitizedUrl = spec.package.replace(/[/:]/g, \"-\").replace(/^-+|-+$/g, \"\");\n return path.join(CACHE_DIR, \"git\", `${sanitizedUrl}${versionSuffix}`);\n}\n\n/**\n * Check if a package is already cached and up to date.\n */\nfunction isCached(cacheDir: string): boolean {\n const packageJsonPath = path.join(cacheDir, \"package.json\");\n if (!fs.existsSync(packageJsonPath)) {\n return false;\n }\n\n // Always check if entry point exists (regardless of build script)\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n const entryPoint = packageJson.llmist?.gadgets || \"./dist/index.js\";\n const entryPointPath = path.join(cacheDir, entryPoint);\n if (!fs.existsSync(entryPointPath)) {\n return false; // Entry point missing, needs install/build\n }\n } catch {\n // If we can't parse package.json, assume not cached\n return false;\n }\n\n return true;\n}\n\n/**\n * Install an npm package to the cache directory.\n */\nasync function installNpmPackage(spec: GadgetSpecifier, cacheDir: string): Promise<void> {\n // Create cache directory\n fs.mkdirSync(cacheDir, { recursive: true });\n\n // Create minimal package.json\n const packageJson = {\n name: \"llmist-gadget-cache\",\n private: true,\n type: \"module\",\n };\n fs.writeFileSync(path.join(cacheDir, \"package.json\"), JSON.stringify(packageJson, null, 2));\n\n // Install the package\n const packageSpec = spec.version ? `${spec.package}@${spec.version}` : spec.package;\n\n try {\n // Use bun add for isolated install (works in Docker containers that only have bun)\n execSync(`bun add \"${packageSpec}\"`, {\n stdio: \"pipe\",\n cwd: cacheDir,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install npm package '${packageSpec}': ${message}`);\n }\n}\n\n/**\n * Clone/fetch a git repository to the cache directory.\n */\nasync function installGitPackage(spec: GadgetSpecifier, cacheDir: string): Promise<void> {\n // Create parent directory\n fs.mkdirSync(path.dirname(cacheDir), { recursive: true });\n\n if (fs.existsSync(cacheDir)) {\n // Update existing repo\n try {\n execSync(\"git fetch\", { cwd: cacheDir, stdio: \"pipe\" });\n if (spec.version) {\n execSync(`git checkout ${spec.version}`, { cwd: cacheDir, stdio: \"pipe\" });\n }\n } catch (error) {\n // If update fails, remove and re-clone\n fs.rmSync(cacheDir, { recursive: true, force: true });\n }\n }\n\n if (!fs.existsSync(cacheDir)) {\n try {\n const cloneCmd = spec.version\n ? `git clone --branch ${spec.version} \"${spec.package}\" \"${cacheDir}\"`\n : `git clone \"${spec.package}\" \"${cacheDir}\"`;\n execSync(cloneCmd, { stdio: \"pipe\" });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to clone git repository '${spec.package}': ${message}`);\n }\n\n // Install dependencies and build\n if (fs.existsSync(path.join(cacheDir, \"package.json\"))) {\n try {\n execSync(\"bun install\", { cwd: cacheDir, stdio: \"inherit\" });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to install dependencies for '${spec.package}': ${message}`);\n }\n\n // Run build if available (git packages need to be built)\n try {\n const packageJson = JSON.parse(fs.readFileSync(path.join(cacheDir, \"package.json\"), \"utf-8\"));\n if (packageJson.scripts?.build) {\n execSync(\"bun run build\", { cwd: cacheDir, stdio: \"inherit\" });\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to build package '${spec.package}': ${message}`);\n }\n }\n }\n}\n\n/**\n * Read the llmist manifest from a package.\n */\nfunction readManifest(packageDir: string): LlmistManifest | null {\n const packageJsonPath = path.join(packageDir, \"package.json\");\n if (!fs.existsSync(packageJsonPath)) {\n return null;\n }\n\n try {\n const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, \"utf-8\"));\n return packageJson.llmist || null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the path to the installed package.\n */\nfunction getPackagePath(cacheDir: string, packageName: string): string {\n // For npm packages, the actual package is in node_modules\n const nodeModulesPath = path.join(cacheDir, \"node_modules\", packageName);\n if (fs.existsSync(nodeModulesPath)) {\n return nodeModulesPath;\n }\n // For git packages, it's the cache dir itself\n return cacheDir;\n}\n\n/**\n * Load gadgets from an external package.\n *\n * @param specifier - External package specifier\n * @param forceInstall - Force reinstall even if cached\n * @returns Array of loaded gadgets\n */\nexport async function loadExternalGadgets(\n specifier: string,\n forceInstall = false,\n): Promise<AbstractGadget[]> {\n const spec = parseGadgetSpecifier(specifier);\n if (!spec) {\n throw new Error(`Invalid external package specifier: ${specifier}`);\n }\n\n const cacheDir = getCacheDir(spec);\n\n // Install if not cached or force install\n if (!isCached(cacheDir) || forceInstall) {\n if (spec.type === \"npm\") {\n await installNpmPackage(spec, cacheDir);\n } else {\n await installGitPackage(spec, cacheDir);\n }\n }\n\n // Get the actual package path\n const packagePath = getPackagePath(cacheDir, spec.package);\n\n // Read manifest\n const manifest = readManifest(packagePath);\n\n // Determine what to load\n let entryPoint: string;\n let gadgetNames: string[] | null = null;\n\n if (spec.gadgetName) {\n // Single gadget requested\n gadgetNames = [spec.gadgetName];\n // Check if it's a subagent\n if (manifest?.subagents?.[spec.gadgetName]) {\n entryPoint = manifest.subagents[spec.gadgetName].entryPoint;\n } else {\n entryPoint = manifest?.gadgets || \"./dist/index.js\";\n }\n } else if (spec.preset) {\n // Preset requested\n if (!manifest?.presets?.[spec.preset]) {\n throw new Error(`Unknown preset '${spec.preset}' in package '${spec.package}'`);\n }\n const preset = manifest.presets[spec.preset];\n if (preset === \"*\") {\n // All gadgets\n gadgetNames = null;\n } else {\n gadgetNames = preset;\n }\n entryPoint = manifest?.gadgets || \"./dist/index.js\";\n } else {\n // All gadgets (default)\n entryPoint = manifest?.gadgets || \"./dist/index.js\";\n }\n\n // Resolve entry point\n const resolvedEntryPoint = path.resolve(packagePath, entryPoint);\n if (!fs.existsSync(resolvedEntryPoint)) {\n throw new Error(\n `Entry point not found: ${resolvedEntryPoint}. ` +\n \"Make sure the package is built (run 'npm run build' in the package directory).\",\n );\n }\n\n // Import the module\n const moduleUrl = pathToFileURL(resolvedEntryPoint).href;\n let exports: unknown;\n try {\n exports = await import(moduleUrl);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to import '${specifier}': ${message}`);\n }\n\n // Extract gadgets\n let gadgets = extractGadgetsFromModule(exports);\n\n // Filter by name if specific gadgets requested\n if (gadgetNames) {\n const gadgetSet = new Set(gadgetNames.map((n) => n.toLowerCase()));\n gadgets = gadgets.filter((g) => {\n const name = g.name?.toLowerCase() || \"\";\n return gadgetSet.has(name);\n });\n\n // Check if all requested gadgets were found\n const foundNames = new Set(gadgets.map((g) => g.name?.toLowerCase() || \"\"));\n for (const requested of gadgetNames) {\n if (!foundNames.has(requested.toLowerCase())) {\n throw new Error(`Gadget '${requested}' not found in package '${spec.package}'`);\n }\n }\n }\n\n if (gadgets.length === 0) {\n throw new Error(`No gadgets found in package '${spec.package}'`);\n }\n\n return gadgets;\n}\n\n/**\n * List available gadgets from an external package.\n *\n * @param specifier - External package specifier\n * @returns Object with gadget info\n */\nexport async function listExternalGadgets(specifier: string): Promise<{\n packageName: string;\n gadgets: Array<{ name: string; description: string }>;\n subagents: Array<{ name: string; description: string }>;\n presets: string[];\n}> {\n const spec = parseGadgetSpecifier(specifier);\n if (!spec) {\n throw new Error(`Invalid external package specifier: ${specifier}`);\n }\n\n const cacheDir = getCacheDir(spec);\n\n // Install if not cached\n if (!isCached(cacheDir)) {\n if (spec.type === \"npm\") {\n await installNpmPackage(spec, cacheDir);\n } else {\n await installGitPackage(spec, cacheDir);\n }\n }\n\n const packagePath = getPackagePath(cacheDir, spec.package);\n const manifest = readManifest(packagePath);\n\n // Load gadgets to get their info\n const entryPoint = manifest?.gadgets || \"./dist/index.js\";\n const resolvedEntryPoint = path.resolve(packagePath, entryPoint);\n\n let gadgetInfo: Array<{ name: string; description: string }> = [];\n\n if (fs.existsSync(resolvedEntryPoint)) {\n try {\n const moduleUrl = pathToFileURL(resolvedEntryPoint).href;\n const exports = await import(moduleUrl);\n const gadgets = extractGadgetsFromModule(exports);\n gadgetInfo = gadgets.map((g) => ({\n name: g.name || \"unnamed\",\n description: g.description || \"\",\n }));\n } catch {\n // Ignore import errors for listing\n }\n }\n\n // Get subagent info from manifest\n const subagentInfo = Object.entries(manifest?.subagents || {}).map(([name, info]) => ({\n name,\n description: info.description || \"\",\n }));\n\n return {\n packageName: spec.package,\n gadgets: gadgetInfo,\n subagents: subagentInfo,\n presets: Object.keys(manifest?.presets || {}),\n };\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { extractMessageText, type LLMMessage } from \"../core/messages.js\";\n\n/**\n * Default directory for LLM debug logs.\n */\nexport const DEFAULT_LLM_LOG_DIR = join(homedir(), \".llmist\", \"logs\");\n\n/**\n * Resolves the log directory from a boolean or string option.\n * - true: use default directory with subdir\n * - string: use the provided path\n * - undefined/false: disabled\n */\nexport function resolveLogDir(\n option: string | boolean | undefined,\n subdir: string,\n): string | undefined {\n if (option === true) {\n return join(DEFAULT_LLM_LOG_DIR, subdir);\n }\n if (typeof option === \"string\") {\n return option;\n }\n return undefined;\n}\n\n/**\n * Formats LLM messages as plain text for debugging.\n */\nexport function formatLlmRequest(messages: LLMMessage[]): string {\n const lines: string[] = [];\n for (const msg of messages) {\n lines.push(`=== ${msg.role.toUpperCase()} ===`);\n // Handle undefined content (for incomplete/malformed messages)\n lines.push(msg.content ? extractMessageText(msg.content) : \"\");\n lines.push(\"\");\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Writes a debug log file, creating the directory if needed.\n */\nexport async function writeLogFile(dir: string, filename: string, content: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n await writeFile(join(dir, filename), content, \"utf-8\");\n}\n\n/**\n * Formats a timestamp for session directory naming.\n * Returns format: \"YYYY-MM-DD_HH-MM-SS\" (e.g., \"2025-12-09_14-30-45\")\n */\nexport function formatSessionTimestamp(date: Date = new Date()): string {\n const pad = (n: number) => n.toString().padStart(2, \"0\");\n const year = date.getFullYear();\n const month = pad(date.getMonth() + 1);\n const day = pad(date.getDate());\n const hours = pad(date.getHours());\n const minutes = pad(date.getMinutes());\n const seconds = pad(date.getSeconds());\n return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;\n}\n\n/**\n * Creates a session directory with a timestamped name.\n * Returns the full path to the created directory, or undefined if creation fails.\n */\nexport async function createSessionDir(baseDir: string): Promise<string | undefined> {\n const timestamp = formatSessionTimestamp();\n const sessionDir = join(baseDir, timestamp);\n try {\n await mkdir(sessionDir, { recursive: true });\n return sessionDir;\n } catch (error) {\n console.warn(`[llmist] Failed to create log session directory: ${sessionDir}`, error);\n return undefined;\n }\n}\n\n/**\n * Formats a call number as a zero-padded 4-digit string.\n * E.g., 1 → \"0001\", 42 → \"0042\"\n */\nexport function formatCallNumber(n: number): string {\n return n.toString().padStart(4, \"0\");\n}\n","import chalk from \"chalk\";\nimport { InvalidArgumentError } from \"commander\";\n\nimport type { ModelRegistry } from \"../core/model-registry.js\";\nimport type { TokenUsage } from \"../core/options.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"../providers/constants.js\";\nimport type { CLIEnvironment, TTYAwareStream } from \"./environment.js\";\n\n/**\n * Options for creating a numeric value parser.\n */\nexport interface NumericParserOptions {\n label: string;\n integer?: boolean;\n min?: number;\n max?: number;\n}\n\n/**\n * Creates a parser function for numeric command-line options with validation.\n * Validates that values are numbers, optionally integers, and within min/max bounds.\n *\n * @param options - Parser configuration (label, integer, min, max)\n * @returns Parser function that validates and returns the numeric value\n * @throws InvalidArgumentError if validation fails\n */\nexport function createNumericParser({\n label,\n integer = false,\n min,\n max,\n}: NumericParserOptions): (value: string) => number {\n return (value: string) => {\n const parsed = Number(value);\n if (Number.isNaN(parsed)) {\n throw new InvalidArgumentError(`${label} must be a number.`);\n }\n\n if (integer && !Number.isInteger(parsed)) {\n throw new InvalidArgumentError(`${label} must be an integer.`);\n }\n\n if (min !== undefined && parsed < min) {\n throw new InvalidArgumentError(`${label} must be greater than or equal to ${min}.`);\n }\n\n if (max !== undefined && parsed > max) {\n throw new InvalidArgumentError(`${label} must be less than or equal to ${max}.`);\n }\n\n return parsed;\n };\n}\n\n/**\n * Helper class for writing text to a stream while tracking newline state.\n * Ensures output ends with a newline for proper terminal formatting.\n */\nexport class StreamPrinter {\n private endedWithNewline = true;\n\n constructor(private readonly target: NodeJS.WritableStream) {}\n\n /**\n * Writes text to the target stream and tracks newline state.\n *\n * @param text - Text to write\n */\n write(text: string): void {\n if (!text) {\n return;\n }\n this.target.write(text);\n this.endedWithNewline = text.endsWith(\"\\n\");\n }\n\n /**\n * Ensures output ends with a newline by writing one if needed.\n */\n ensureNewline(): void {\n if (!this.endedWithNewline) {\n this.target.write(\"\\n\");\n this.endedWithNewline = true;\n }\n }\n}\n\n/**\n * Checks if a stream is a TTY (terminal) for interactive input.\n *\n * @param stream - Stream to check\n * @returns True if stream is a TTY\n */\nexport function isInteractive(stream: TTYAwareStream): boolean {\n return Boolean(stream.isTTY);\n}\n\n/** ESC key byte code */\nconst ESC_KEY = 0x1b;\n\n/**\n * Timeout in milliseconds to distinguish standalone ESC key from escape sequences.\n *\n * When a user presses the ESC key alone, only byte 0x1B is sent. However, arrow keys\n * and other special keys send escape sequences that START with 0x1B followed by\n * additional bytes (e.g., `ESC[A` for up arrow, `ESC[B` for down arrow).\n *\n * These additional bytes typically arrive within 10-20ms on most terminals and SSH\n * connections. The 50ms timeout provides a safe buffer to detect escape sequences\n * while keeping the standalone ESC key responsive to user input.\n *\n * If no additional bytes arrive within this window after an initial ESC byte,\n * we treat it as a standalone ESC key press.\n */\nconst ESC_TIMEOUT_MS = 50;\nconst CTRL_C = 0x03; // ETX - End of Text (Ctrl+C in raw mode)\n\n/**\n * Creates a keyboard listener for ESC key and Ctrl+C detection in TTY mode.\n *\n * Uses a timeout to distinguish standalone ESC from escape sequences (like arrow keys).\n * Arrow keys start with ESC byte (0x1B) followed by additional bytes, so we wait briefly\n * to see if more bytes arrive before triggering the callback.\n *\n * When stdin is in raw mode, Ctrl+C is received as byte 0x03 instead of generating\n * a SIGINT signal. This function handles Ctrl+C explicitly via the onCtrlC callback.\n *\n * @param stdin - The stdin stream (must be TTY with setRawMode support)\n * @param onEsc - Callback when ESC is pressed\n * @param onCtrlC - Optional callback when Ctrl+C is pressed in raw mode\n * @returns Cleanup function to restore normal mode, or null if not supported\n */\nexport function createEscKeyListener(\n stdin: NodeJS.ReadStream,\n onEsc: () => void,\n onCtrlC?: () => void,\n): (() => void) | null {\n // Check both isTTY and setRawMode availability (mock streams may have isTTY but no setRawMode)\n if (!stdin.isTTY || typeof stdin.setRawMode !== \"function\") {\n return null;\n }\n\n let escTimeout: NodeJS.Timeout | null = null;\n\n const handleData = (data: Buffer) => {\n // Handle Ctrl+C in raw mode (since SIGINT won't be generated)\n if (data[0] === CTRL_C && onCtrlC) {\n // Clear any pending ESC timeout before handling Ctrl+C\n if (escTimeout) {\n clearTimeout(escTimeout);\n escTimeout = null;\n }\n onCtrlC();\n return;\n }\n\n if (data[0] === ESC_KEY) {\n if (data.length === 1) {\n // Could be standalone ESC or start of sequence - use timeout\n escTimeout = setTimeout(() => {\n onEsc();\n }, ESC_TIMEOUT_MS);\n } else {\n // Part of escape sequence (arrow key, etc.) - clear any pending timeout\n if (escTimeout) {\n clearTimeout(escTimeout);\n escTimeout = null;\n }\n }\n } else {\n // Other key - clear any pending ESC timeout\n if (escTimeout) {\n clearTimeout(escTimeout);\n escTimeout = null;\n }\n }\n };\n\n // Enable raw mode to get individual keystrokes\n stdin.setRawMode(true);\n stdin.resume();\n stdin.on(\"data\", handleData);\n\n // Return cleanup function\n return () => {\n if (escTimeout) {\n clearTimeout(escTimeout);\n }\n stdin.removeListener(\"data\", handleData);\n stdin.setRawMode(false);\n stdin.pause();\n };\n}\n\n/**\n * Timeout window for detecting double Ctrl+C press (in milliseconds).\n *\n * When no operation is active, pressing Ctrl+C once shows a hint message.\n * If a second Ctrl+C is pressed within this window, the CLI exits gracefully.\n * This pattern is familiar from many CLI tools (npm, vim, etc.).\n */\nconst SIGINT_DOUBLE_PRESS_MS = 1000;\n\n/**\n * Creates a SIGINT (Ctrl+C) listener with double-press detection.\n *\n * Behavior:\n * - If an operation is active: cancels the operation via `onCancel`\n * - If no operation active and first press: shows hint message\n * - If no operation active and second press within 1 second: calls `onQuit`\n *\n * @param onCancel - Callback when Ctrl+C pressed during an active operation\n * @param onQuit - Callback when double Ctrl+C pressed (quit CLI)\n * @param isOperationActive - Function that returns true if an operation is in progress\n * @param stderr - Stream to write hint messages to (defaults to process.stderr)\n * @returns Cleanup function to remove the listener\n *\n * @example\n * ```typescript\n * const cleanup = createSigintListener(\n * () => abortController.abort(),\n * () => process.exit(0),\n * () => isStreaming,\n * );\n *\n * // When done:\n * cleanup();\n * ```\n */\nexport function createSigintListener(\n onCancel: () => void,\n onQuit: () => void,\n isOperationActive: () => boolean,\n stderr: NodeJS.WritableStream = process.stderr,\n): () => void {\n let lastSigintTime = 0;\n\n const handler = () => {\n const now = Date.now();\n\n if (isOperationActive()) {\n // Cancel the current operation\n onCancel();\n // Set timer to now so that a second Ctrl+C within 1 second will trigger quit\n lastSigintTime = now;\n return;\n }\n\n // Check for double-press\n if (now - lastSigintTime < SIGINT_DOUBLE_PRESS_MS) {\n onQuit();\n return;\n }\n\n // First press when no operation is active\n lastSigintTime = now;\n stderr.write(chalk.dim(\"\\n[Press Ctrl+C again to quit]\\n\"));\n };\n\n process.on(\"SIGINT\", handler);\n\n return () => {\n process.removeListener(\"SIGINT\", handler);\n };\n}\n\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\nconst SPINNER_DELAY_MS = 500; // Don't show spinner for fast responses\n\ntype ProgressMode = \"streaming\" | \"cumulative\";\n\n// Import formatters from centralized formatting module\n// This showcases llmist's clean code organization\nimport { formatCost, formatGadgetLine, formatLLMCallLine, formatTokens } from \"./ui/formatters.js\";\n\n/**\n * Progress indicator shown while waiting for LLM response.\n * Two modes:\n * - streaming: Shows current LLM call stats (out/in tokens, call time)\n * - cumulative: Shows total stats across all calls (total tokens, iterations, total time)\n * Only displays on TTY (interactive terminal), silent when piped.\n */\nexport class StreamProgress {\n // Animation state\n private frameIndex = 0;\n private interval: ReturnType<typeof setInterval> | null = null;\n private delayTimeout: ReturnType<typeof setTimeout> | null = null;\n private isRunning = false;\n private hasRendered = false;\n private lastRenderLineCount = 0; // Track lines rendered for multi-line clearing\n\n // Current call stats (streaming mode)\n private mode: ProgressMode = \"cumulative\";\n private model = \"\";\n private callStartTime = Date.now();\n private callInputTokens = 0;\n private callInputTokensEstimated = true;\n private callOutputTokens = 0;\n private callOutputTokensEstimated = true;\n private callOutputChars = 0;\n private isStreaming = false;\n // Cache token tracking for live cost estimation during streaming\n private callCachedInputTokens = 0;\n private callCacheCreationInputTokens = 0;\n\n // Cumulative stats (cumulative mode)\n private totalStartTime = Date.now();\n private totalTokens = 0;\n private totalCost = 0;\n private iterations = 0;\n private currentIteration = 0;\n\n // In-flight gadget tracking for concurrent status display\n private inFlightGadgets: Map<\n string,\n {\n name: string;\n params?: Record<string, unknown>;\n startTime: number;\n completed?: boolean;\n completedTime?: number;\n }\n > = new Map();\n\n // Nested agent tracking for hierarchical subagent display\n private nestedAgents: Map<\n string,\n {\n parentInvocationId: string;\n depth: number;\n model: string;\n iteration: number;\n /** Parent call number for hierarchical display (e.g., #1.2) */\n parentCallNumber?: number;\n /** Gadget invocation ID for unique subagent identification (e.g., #6.browse_web_1.2) */\n gadgetInvocationId?: string;\n startTime: number;\n inputTokens?: number;\n outputTokens?: number;\n // First-class subagent metrics (cached tokens, cost, finish reason)\n cachedInputTokens?: number;\n cacheCreationInputTokens?: number;\n finishReason?: string;\n cost?: number;\n completed?: boolean;\n completedTime?: number;\n }\n > = new Map();\n\n // Nested gadget tracking for hierarchical subagent display\n private nestedGadgets: Map<\n string,\n {\n depth: number;\n parentInvocationId: string;\n name: string;\n parameters?: Record<string, unknown>;\n startTime: number;\n completed?: boolean;\n completedTime?: number;\n }\n > = new Map();\n\n constructor(\n private readonly target: NodeJS.WritableStream,\n private readonly isTTY: boolean,\n private readonly modelRegistry?: ModelRegistry,\n ) {}\n\n /**\n * Add a gadget to the in-flight tracking (called when gadget_call event received).\n * Triggers re-render to show the gadget in the status display.\n */\n addGadget(invocationId: string, name: string, params?: Record<string, unknown>): void {\n this.inFlightGadgets.set(invocationId, { name, params, startTime: Date.now() });\n // Re-render immediately to show the new gadget\n if (this.isRunning && this.isTTY) {\n this.render();\n }\n }\n\n /**\n * Remove a gadget from in-flight tracking (called when gadget_result event received).\n * Triggers re-render to update the status display.\n */\n removeGadget(invocationId: string): void {\n this.inFlightGadgets.delete(invocationId);\n // Re-render immediately to remove the gadget from display\n if (this.isRunning && this.isTTY) {\n this.render();\n }\n }\n\n /**\n * Check if there are any gadgets currently in flight.\n */\n hasInFlightGadgets(): boolean {\n return this.inFlightGadgets.size > 0;\n }\n\n /**\n * Get a gadget by ID (for accessing name, params, etc.).\n */\n getGadget(invocationId: string) {\n return this.inFlightGadgets.get(invocationId);\n }\n\n /**\n * Mark a gadget as completed (keeps it visible with ✓ indicator).\n * Records completion time to freeze the elapsed timer.\n * The gadget and its nested operations remain visible until clearCompletedGadgets() is called.\n */\n completeGadget(invocationId: string): void {\n const gadget = this.inFlightGadgets.get(invocationId);\n if (gadget) {\n gadget.completed = true;\n gadget.completedTime = Date.now();\n if (this.isRunning && this.isTTY) {\n this.render();\n }\n }\n }\n\n /**\n * Clear all completed gadgets from the display.\n * Called when new text output arrives to clean up the finished gadget section.\n */\n clearCompletedGadgets(): void {\n for (const [id, gadget] of this.inFlightGadgets) {\n if (gadget.completed) {\n this.inFlightGadgets.delete(id);\n // Also clean up nested operations for this gadget\n for (const [nestedId, nested] of this.nestedAgents) {\n if (nested.parentInvocationId === id) {\n this.nestedAgents.delete(nestedId);\n }\n }\n for (const [nestedId, nested] of this.nestedGadgets) {\n if (nested.parentInvocationId === id) {\n this.nestedGadgets.delete(nestedId);\n }\n }\n }\n }\n if (this.isRunning && this.isTTY) {\n this.render();\n }\n }\n\n /**\n * Add a nested agent LLM call (called when nested llm_call_start event received).\n * Used to display hierarchical progress for subagent gadgets.\n * @param parentCallNumber - Top-level call number for hierarchical display (e.g., #1.2)\n * @param gadgetInvocationId - Gadget invocation ID for unique subagent identification\n */\n addNestedAgent(\n id: string,\n parentInvocationId: string,\n depth: number,\n model: string,\n iteration: number,\n info?: {\n inputTokens?: number;\n cachedInputTokens?: number;\n },\n parentCallNumber?: number,\n gadgetInvocationId?: string,\n ): void {\n this.nestedAgents.set(id, {\n parentInvocationId,\n depth,\n model,\n iteration,\n parentCallNumber,\n gadgetInvocationId,\n startTime: Date.now(),\n inputTokens: info?.inputTokens,\n cachedInputTokens: info?.cachedInputTokens,\n });\n if (this.isRunning && this.isTTY) {\n this.render();\n }\n }\n\n /**\n * Update a nested agent with completion info (called when nested llm_call_end event received).\n * Records completion time to freeze the elapsed timer.\n * @param info - Full LLM call info including tokens, cache details, and cost\n */\n updateNestedAgent(\n id: string,\n info: {\n inputTokens?: number;\n outputTokens?: number;\n cachedInputTokens?: number;\n cacheCreationInputTokens?: number;\n finishReason?: string;\n cost?: number;\n },\n ): void {\n const agent = this.nestedAgents.get(id);\n if (agent) {\n // Only update if new value is defined - preserve initial values from addNestedAgent()\n if (info.inputTokens !== undefined) agent.inputTokens = info.inputTokens;\n if (info.outputTokens !== undefined) agent.outputTokens = info.outputTokens;\n if (info.cachedInputTokens !== undefined) agent.cachedInputTokens = info.cachedInputTokens;\n if (info.cacheCreationInputTokens !== undefined)\n agent.cacheCreationInputTokens = info.cacheCreationInputTokens;\n if (info.finishReason !== undefined) agent.finishReason = info.finishReason;\n\n // Calculate cost if not provided and we have model registry\n if (info.cost !== undefined) {\n agent.cost = info.cost;\n } else if (this.modelRegistry && agent.model && agent.outputTokens) {\n // Calculate cost using model registry (first-class subagent metric)\n // Use agent.* values which include preserved initial values from addNestedAgent()\n try {\n const modelName = agent.model.includes(\":\") ? agent.model.split(\":\")[1] : agent.model;\n const costResult = this.modelRegistry.estimateCost(\n modelName,\n agent.inputTokens ?? 0,\n agent.outputTokens,\n agent.cachedInputTokens,\n agent.cacheCreationInputTokens,\n );\n agent.cost = costResult?.totalCost;\n } catch {\n // Ignore cost calculation errors\n }\n }\n\n agent.completed = true;\n agent.completedTime = Date.now();\n if (this.isRunning && this.isTTY) {\n this.render();\n }\n }\n }\n\n /**\n * Remove a nested agent (called when the nested LLM call completes).\n */\n removeNestedAgent(id: string): void {\n this.nestedAgents.delete(id);\n if (this.isRunning && this.isTTY) {\n this.render();\n }\n }\n\n /**\n * Get a nested agent by ID (for accessing startTime, etc.).\n */\n getNestedAgent(id: string) {\n return this.nestedAgents.get(id);\n }\n\n /**\n * Get aggregated metrics from all nested agents for a parent gadget.\n * Used to show total token counts and cost for subagent gadgets like BrowseWeb.\n */\n getAggregatedSubagentMetrics(parentInvocationId: string): {\n inputTokens: number;\n outputTokens: number;\n cachedInputTokens: number;\n cost: number;\n callCount: number;\n } {\n let inputTokens = 0;\n let outputTokens = 0;\n let cachedInputTokens = 0;\n let cost = 0;\n let callCount = 0;\n\n for (const [, nested] of this.nestedAgents) {\n if (nested.parentInvocationId === parentInvocationId) {\n inputTokens += nested.inputTokens ?? 0;\n outputTokens += nested.outputTokens ?? 0;\n cachedInputTokens += nested.cachedInputTokens ?? 0;\n cost += nested.cost ?? 0;\n callCount++;\n }\n }\n\n return { inputTokens, outputTokens, cachedInputTokens, cost, callCount };\n }\n\n /**\n * Add a nested gadget call (called when nested gadget_call event received).\n */\n addNestedGadget(\n id: string,\n depth: number,\n parentInvocationId: string,\n name: string,\n parameters?: Record<string, unknown>,\n ): void {\n this.nestedGadgets.set(id, {\n depth,\n parentInvocationId,\n name,\n parameters,\n startTime: Date.now(),\n });\n if (this.isRunning && this.isTTY) {\n this.render();\n }\n }\n\n /**\n * Remove a nested gadget (called when nested gadget_result event received).\n */\n removeNestedGadget(id: string): void {\n this.nestedGadgets.delete(id);\n if (this.isRunning && this.isTTY) {\n this.render();\n }\n }\n\n /**\n * Get a nested gadget by ID (for accessing startTime, name, etc.).\n */\n getNestedGadget(id: string) {\n return this.nestedGadgets.get(id);\n }\n\n /**\n * Mark a nested gadget as completed (keeps it visible with ✓ indicator).\n * Records completion time to freeze the elapsed timer.\n */\n completeNestedGadget(id: string): void {\n const gadget = this.nestedGadgets.get(id);\n if (gadget) {\n gadget.completed = true;\n gadget.completedTime = Date.now();\n if (this.isRunning && this.isTTY) {\n this.render();\n }\n }\n }\n\n /**\n * Starts a new LLM call. Switches to streaming mode.\n * @param model - Model name being used\n * @param estimatedInputTokens - Initial input token count. Should come from\n * client.countTokens() for accuracy (provider-specific counting), not\n * character-based estimation. Will be updated with provider-returned counts\n * via setInputTokens() during streaming if available.\n */\n startCall(model: string, estimatedInputTokens?: number): void {\n this.mode = \"streaming\";\n this.model = model;\n this.callStartTime = Date.now();\n this.currentIteration++;\n this.callInputTokens = estimatedInputTokens ?? 0;\n this.callInputTokensEstimated = true;\n this.callOutputTokens = 0;\n this.callOutputTokensEstimated = true;\n this.callOutputChars = 0;\n this.isStreaming = false;\n // Reset cache tracking for new call\n this.callCachedInputTokens = 0;\n this.callCacheCreationInputTokens = 0;\n this.start();\n }\n\n /**\n * Ends the current LLM call. Updates cumulative stats and switches to cumulative mode.\n * @param usage - Final token usage from the call (including cached tokens if available)\n */\n endCall(usage?: TokenUsage): void {\n this.iterations++;\n if (usage) {\n this.totalTokens += usage.totalTokens;\n\n // Calculate and accumulate cost if model registry is available\n if (this.modelRegistry && this.model) {\n try {\n // Strip provider prefix if present (e.g., \"openai:gpt-5-nano\" -> \"gpt-5-nano\")\n const modelName = this.model.includes(\":\") ? this.model.split(\":\")[1] : this.model;\n\n const cost = this.modelRegistry.estimateCost(\n modelName,\n usage.inputTokens,\n usage.outputTokens,\n usage.cachedInputTokens ?? 0,\n usage.cacheCreationInputTokens ?? 0,\n );\n if (cost) {\n this.totalCost += cost.totalCost;\n }\n } catch {\n // Ignore errors (e.g., unknown model) - just don't add to cost\n }\n }\n }\n this.pause();\n this.mode = \"cumulative\";\n }\n\n /**\n * Adds gadget execution cost to the total.\n * Called when gadgets complete to include their costs (direct + subagent) in the total.\n */\n addGadgetCost(cost: number): void {\n if (cost > 0) {\n this.totalCost += cost;\n }\n }\n\n /**\n * Sets the input token count for current call (from stream metadata).\n * @param tokens - Token count from provider or client.countTokens()\n * @param estimated - If true, this is a fallback estimate (character-based).\n * If false, this is an accurate count from the provider API or client.countTokens().\n * Display shows ~ prefix only when estimated=true.\n */\n setInputTokens(tokens: number, estimated = false): void {\n // Don't overwrite actual count with a new estimate\n if (estimated && !this.callInputTokensEstimated) {\n return;\n }\n this.callInputTokens = tokens;\n this.callInputTokensEstimated = estimated;\n }\n\n /**\n * Sets the output token count for current call (from stream metadata).\n * @param tokens - Token count from provider streaming response\n * @param estimated - If true, this is a fallback estimate (character-based).\n * If false, this is an accurate count from the provider's streaming metadata.\n * Display shows ~ prefix only when estimated=true.\n */\n setOutputTokens(tokens: number, estimated = false): void {\n // Don't overwrite actual count with a new estimate\n if (estimated && !this.callOutputTokensEstimated) {\n return;\n }\n this.callOutputTokens = tokens;\n this.callOutputTokensEstimated = estimated;\n }\n\n /**\n * Sets cached token counts for the current call (from stream metadata).\n * Used for live cost estimation during streaming.\n * @param cachedInputTokens - Number of tokens read from cache (cheaper)\n * @param cacheCreationInputTokens - Number of tokens written to cache (more expensive)\n */\n setCachedTokens(cachedInputTokens: number, cacheCreationInputTokens: number): void {\n this.callCachedInputTokens = cachedInputTokens;\n this.callCacheCreationInputTokens = cacheCreationInputTokens;\n }\n\n /**\n * Get total elapsed time in seconds since the first call started.\n * @returns Elapsed time in seconds with 1 decimal place\n */\n getTotalElapsedSeconds(): number {\n if (this.totalStartTime === 0) return 0;\n return Number(((Date.now() - this.totalStartTime) / 1000).toFixed(1));\n }\n\n /**\n * Get elapsed time in seconds for the current call.\n * @returns Elapsed time in seconds with 1 decimal place\n */\n getCallElapsedSeconds(): number {\n return Number(((Date.now() - this.callStartTime) / 1000).toFixed(1));\n }\n\n /**\n * Starts the progress indicator animation after a brief delay.\n */\n start(): void {\n if (!this.isTTY || this.isRunning) return;\n this.isRunning = true;\n\n // Delay showing spinner to avoid flicker for fast responses\n this.delayTimeout = setTimeout(() => {\n if (this.isRunning) {\n this.interval = setInterval(() => this.render(), 80);\n this.render();\n }\n }, SPINNER_DELAY_MS);\n }\n\n /**\n * Updates output character count for current call and marks streaming as active.\n * @param totalChars - Total accumulated character count\n */\n update(totalChars: number): void {\n this.callOutputChars = totalChars;\n this.isStreaming = true;\n }\n\n private render(): void {\n // Clear previous multi-line render before drawing new content\n this.clearRenderedLines();\n\n const spinner = SPINNER_FRAMES[this.frameIndex++ % SPINNER_FRAMES.length];\n const lines: string[] = [];\n\n // Collect actively streaming nested agents (to show at bottom, not in hierarchy)\n const activeNestedStreams: Array<{\n depth: number;\n iteration: number;\n parentCallNumber?: number;\n gadgetInvocationId?: string;\n model: string;\n inputTokens?: number;\n cachedInputTokens?: number;\n outputTokens?: number;\n cost?: number;\n startTime: number;\n parentGadgetName: string; // For prefixing nested operation lines\n }> = [];\n\n // In-flight gadgets - ONLY show gadgets that are still running\n // Completed gadgets are printed inline when they finish (via completeGadget)\n if (this.isTTY) {\n for (const [gadgetId, gadget] of this.inFlightGadgets) {\n // Skip completed gadgets - they were already printed inline\n if (gadget.completed) {\n continue;\n }\n const elapsedSeconds = (Date.now() - gadget.startTime) / 1000;\n\n // Get aggregated subagent metrics for realtime display\n const subagentMetrics = this.getAggregatedSubagentMetrics(gadgetId);\n\n // Use shared formatGadgetLine for consistent formatting with parameters\n // Pass maxWidth adjusted for 2-space indent\n const termWidth = process.stdout.columns ?? 80;\n const gadgetIndent = \" \";\n const line = formatGadgetLine(\n {\n name: gadget.name,\n parameters: gadget.params,\n elapsedSeconds,\n isComplete: false, // We only show running gadgets here\n // Pass realtime subagent metrics\n subagentInputTokens: subagentMetrics.inputTokens,\n subagentOutputTokens: subagentMetrics.outputTokens,\n subagentCachedTokens: subagentMetrics.cachedInputTokens,\n subagentCost: subagentMetrics.cost,\n },\n termWidth - gadgetIndent.length,\n );\n // Add indent to EACH line of multi-line output\n const gadgetLine = line\n .split(\"\\n\")\n .map((l) => gadgetIndent + l)\n .join(\"\\n\");\n lines.push(gadgetLine);\n\n // Build unified timeline of nested operations sorted by startTime\n // This fixes the display ordering bug where agents were grouped above gadgets\n const nestedOps: Array<{\n type: \"agent\" | \"gadget\";\n startTime: number;\n depth: number;\n // Agent-specific fields\n iteration?: number;\n parentCallNumber?: number;\n gadgetInvocationId?: string;\n model?: string;\n inputTokens?: number;\n cachedInputTokens?: number;\n outputTokens?: number;\n cost?: number;\n finishReason?: string;\n completed?: boolean;\n completedTime?: number;\n // Gadget-specific fields\n id?: string; // For metrics aggregation\n name?: string;\n parameters?: Record<string, unknown>;\n }> = [];\n\n // Collect nested agents for this parent\n for (const [_agentId, nested] of this.nestedAgents) {\n if (nested.parentInvocationId === gadgetId) {\n nestedOps.push({\n type: \"agent\",\n startTime: nested.startTime,\n depth: nested.depth,\n iteration: nested.iteration,\n parentCallNumber: nested.parentCallNumber,\n gadgetInvocationId: nested.gadgetInvocationId,\n model: nested.model,\n inputTokens: nested.inputTokens,\n cachedInputTokens: nested.cachedInputTokens,\n outputTokens: nested.outputTokens,\n cost: nested.cost,\n finishReason: nested.finishReason,\n completed: nested.completed,\n completedTime: nested.completedTime,\n });\n\n // Collect actively streaming agents for bottom section\n if (!nested.completed) {\n activeNestedStreams.push({\n depth: nested.depth,\n iteration: nested.iteration,\n parentCallNumber: nested.parentCallNumber,\n gadgetInvocationId: nested.gadgetInvocationId,\n model: nested.model,\n inputTokens: nested.inputTokens,\n cachedInputTokens: nested.cachedInputTokens,\n outputTokens: nested.outputTokens,\n cost: nested.cost,\n startTime: nested.startTime,\n parentGadgetName: gadget.name, // Track parent for prefixing\n });\n }\n }\n }\n\n // Collect nested gadgets for this parent\n for (const [nestedId, nestedGadget] of this.nestedGadgets) {\n if (nestedGadget.parentInvocationId === gadgetId) {\n nestedOps.push({\n type: \"gadget\",\n id: nestedId, // Preserve ID for metrics aggregation\n startTime: nestedGadget.startTime,\n depth: nestedGadget.depth,\n name: nestedGadget.name,\n parameters: nestedGadget.parameters,\n completed: nestedGadget.completed,\n completedTime: nestedGadget.completedTime,\n });\n }\n }\n\n // Sort by startTime for chronological display\n nestedOps.sort((a, b) => a.startTime - b.startTime);\n\n // Render in chronological order using shared formatting functions\n // Nested operations are indented under parent gadget (which has 2-space indent)\n // So base indent is 4 spaces, plus 2 more for each depth level\n // SKIP completed ops (printed inline) and streaming agents (shown at bottom)\n for (const op of nestedOps) {\n // Skip ALL completed operations - they were printed inline when they finished\n if (op.completed) {\n continue;\n }\n\n // Skip in-progress agents - they're shown in active streams section at bottom\n if (op.type === \"agent\") {\n continue;\n }\n\n // Only in-progress GADGETS reach here - render them\n const indent = \" \".repeat(op.depth + 2);\n const elapsedSeconds = (Date.now() - op.startTime) / 1000;\n\n // Get aggregated subagent metrics (for nested gadgets that run LLM calls)\n const nestedMetrics = op.id ? this.getAggregatedSubagentMetrics(op.id) : { inputTokens: 0, outputTokens: 0, cachedInputTokens: 0, cost: 0, callCount: 0 };\n\n // Use shared formatGadgetLine for consistent formatting\n // Pass maxWidth adjusted for indent to prevent line overflow\n const termWidth = process.stdout.columns ?? 80;\n // Parent gadget prefix for nested operations\n const parentPrefix = `${chalk.dim(`${gadget.name}:`)} `;\n const line = formatGadgetLine(\n {\n name: op.name ?? \"\",\n parameters: op.parameters,\n elapsedSeconds,\n isComplete: false, // Only in-progress gadgets reach here\n // Pass realtime subagent metrics\n subagentInputTokens: nestedMetrics.inputTokens,\n subagentOutputTokens: nestedMetrics.outputTokens,\n subagentCachedTokens: nestedMetrics.cachedInputTokens,\n subagentCost: nestedMetrics.cost,\n },\n termWidth - indent.length - parentPrefix.length,\n );\n // Add indent and parent prefix to EACH line of multi-line output\n const indentedLine = line\n .split(\"\\n\")\n .map((l) => indent + parentPrefix + l)\n .join(\"\\n\");\n lines.push(indentedLine);\n }\n }\n }\n\n // ACTIVE STREAMS SECTION: Show all actively streaming LLM calls at bottom\n // Ordered from innermost (top) to outermost (bottom) - like a call stack\n // This shows nested streams first, then the main agent line below them\n\n // Nested active streams FIRST (they are \"inside\" the main agent context)\n for (const stream of activeNestedStreams) {\n // Use depth-based indent to align with completed nested agents in hierarchy\n const indent = \" \".repeat(stream.depth + 2);\n // Parent gadget prefix for nested operations\n const parentPrefix = `${chalk.dim(`${stream.parentGadgetName}:`)} `;\n const elapsedSeconds = (Date.now() - stream.startTime) / 1000;\n const line = formatLLMCallLine({\n iteration: stream.iteration,\n parentCallNumber: stream.parentCallNumber,\n gadgetInvocationId: stream.gadgetInvocationId,\n model: stream.model,\n inputTokens: stream.inputTokens,\n cachedInputTokens: stream.cachedInputTokens,\n outputTokens: stream.outputTokens,\n elapsedSeconds,\n cost: stream.cost,\n isStreaming: true,\n spinner,\n });\n lines.push(`${indent}${parentPrefix}${line}`);\n }\n\n // Main progress line LAST (it's the outer/root context)\n if (this.mode === \"streaming\") {\n lines.push(this.formatStreamingLine(spinner));\n } else {\n lines.push(this.formatCumulativeLine(spinner));\n }\n\n // Write all lines and track count for clearing\n const output = lines.join(\"\\n\");\n // Count actual terminal lines (some elements may contain \\n for multi-line gadgets)\n this.lastRenderLineCount = (output.match(/\\n/g) || []).length + 1;\n // Use \\r to return to start of first line, then join with newlines\n // Each line ends implicitly, cursor stays at end of last line\n this.target.write(\"\\r\" + output);\n this.hasRendered = true;\n }\n\n /**\n * Clears the previously rendered lines (for multi-line status display).\n */\n private clearRenderedLines(): void {\n if (!this.hasRendered || this.lastRenderLineCount === 0) return;\n\n // First, clear the current line\n this.target.write(\"\\r\\x1b[K\");\n\n // Then move up and clear each additional line\n for (let i = 1; i < this.lastRenderLineCount; i++) {\n // Move up one line and clear it\n this.target.write(\"\\x1b[1A\\x1b[K\");\n }\n\n // Return cursor to start\n this.target.write(\"\\r\");\n }\n\n /**\n * Clear rendered lines and reset counter.\n * Call this before printing static output that should remain visible\n * above the render zone (e.g., opening/closing lines for nested operations).\n */\n clearAndReset(): void {\n if (this.isTTY) {\n this.clearRenderedLines();\n }\n this.lastRenderLineCount = 0;\n this.hasRendered = false;\n }\n\n /**\n * Format the streaming mode progress line (returns string, doesn't write).\n * Uses the shared formatLLMCallLine() function for consistent formatting\n * between main agent and nested subagent displays.\n */\n private formatStreamingLine(spinner: string): string {\n // Output tokens: use actual if available, otherwise estimate from chars\n const outTokens = this.callOutputTokensEstimated\n ? Math.round(this.callOutputChars / FALLBACK_CHARS_PER_TOKEN)\n : this.callOutputTokens;\n\n // Use shared formatting function for consistent display\n return formatLLMCallLine({\n iteration: this.currentIteration,\n model: this.model ?? \"\",\n inputTokens: this.callInputTokens,\n cachedInputTokens: this.callCachedInputTokens,\n outputTokens: outTokens,\n elapsedSeconds: (Date.now() - this.callStartTime) / 1000,\n cost: this.calculateCurrentCallCost(outTokens),\n isStreaming: true,\n spinner,\n contextPercent: this.getContextUsagePercent(),\n estimated: {\n input: this.callInputTokensEstimated,\n output: this.callOutputTokensEstimated,\n },\n });\n }\n\n /**\n * Calculates live cost estimate for the current streaming call.\n * Uses current input/output tokens and cached token counts.\n */\n private calculateCurrentCallCost(outputTokens: number): number {\n if (!this.modelRegistry || !this.model) return 0;\n\n try {\n // Strip provider prefix if present (e.g., \"anthropic:claude-sonnet-4-5\" -> \"claude-sonnet-4-5\")\n const modelName = this.model.includes(\":\") ? this.model.split(\":\")[1] : this.model;\n\n const cost = this.modelRegistry.estimateCost(\n modelName,\n this.callInputTokens,\n outputTokens,\n this.callCachedInputTokens,\n this.callCacheCreationInputTokens,\n );\n\n return cost?.totalCost ?? 0;\n } catch {\n return 0;\n }\n }\n\n /**\n * Calculates context window usage percentage.\n * Returns null if model is unknown or context window unavailable.\n */\n private getContextUsagePercent(): number | null {\n if (!this.modelRegistry || !this.model || this.callInputTokens === 0) {\n return null;\n }\n\n // Strip provider prefix if present (e.g., \"anthropic:claude-sonnet-4-5\" -> \"claude-sonnet-4-5\")\n const modelName = this.model.includes(\":\") ? this.model.split(\":\")[1] : this.model;\n\n const limits = this.modelRegistry.getModelLimits(modelName);\n if (!limits?.contextWindow) {\n return null;\n }\n\n return (this.callInputTokens / limits.contextWindow) * 100;\n }\n\n /**\n * Format the cumulative mode progress line (returns string, doesn't write).\n */\n private formatCumulativeLine(spinner: string): string {\n const elapsed = ((Date.now() - this.totalStartTime) / 1000).toFixed(1);\n\n // Build status parts: model, total tokens, iterations, cost, total time\n const parts: string[] = [];\n if (this.model) {\n parts.push(chalk.cyan(this.model));\n }\n if (this.totalTokens > 0) {\n parts.push(chalk.dim(\"total:\") + chalk.magenta(` ${this.totalTokens}`));\n }\n if (this.iterations > 0) {\n parts.push(chalk.dim(\"iter:\") + chalk.blue(` ${this.iterations}`));\n }\n if (this.totalCost > 0) {\n parts.push(chalk.dim(\"cost:\") + chalk.cyan(` $${formatCost(this.totalCost)}`));\n }\n parts.push(chalk.dim(`${elapsed}s`));\n\n return `${parts.join(chalk.dim(\" | \"))} ${chalk.cyan(spinner)}`;\n }\n\n /**\n * Pauses the progress indicator and clears all rendered lines.\n * Can be resumed with start().\n */\n pause(): void {\n if (!this.isTTY || !this.isRunning) return;\n\n if (this.delayTimeout) {\n clearTimeout(this.delayTimeout);\n this.delayTimeout = null;\n }\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n this.isRunning = false;\n\n // Clear all rendered lines (multi-line status display)\n this.clearRenderedLines();\n this.hasRendered = false;\n this.lastRenderLineCount = 0;\n }\n\n /**\n * Completes the progress indicator and clears the line.\n */\n complete(): void {\n this.pause();\n }\n\n /**\n * Returns the total accumulated cost across all calls.\n */\n getTotalCost(): number {\n return this.totalCost;\n }\n\n /**\n * Returns a formatted stats string for cancellation messages.\n * Format: \"↑ 1.2k | ↓ 300 | 5.0s\"\n */\n formatStats(): string {\n const parts: string[] = [];\n const elapsed = ((Date.now() - this.callStartTime) / 1000).toFixed(1);\n\n // Output tokens: use actual if available, otherwise estimate from chars\n const outTokens = this.callOutputTokensEstimated\n ? Math.round(this.callOutputChars / FALLBACK_CHARS_PER_TOKEN)\n : this.callOutputTokens;\n\n if (this.callInputTokens > 0) {\n const prefix = this.callInputTokensEstimated ? \"~\" : \"\";\n parts.push(`↑ ${prefix}${formatTokens(this.callInputTokens)}`);\n }\n\n if (outTokens > 0) {\n const prefix = this.callOutputTokensEstimated ? \"~\" : \"\";\n parts.push(`↓ ${prefix}${formatTokens(outTokens)}`);\n }\n\n parts.push(`${elapsed}s`);\n\n return parts.join(\" | \");\n }\n\n /**\n * Returns a formatted prompt string with stats (like bash PS1).\n * Shows current call stats during streaming, cumulative stats otherwise.\n * Format: \"out: 1.2k │ in: ~300 │ 5s > \" or \"3.6k │ i2 │ 34s > \"\n */\n formatPrompt(): string {\n const parts: string[] = [];\n\n if (this.mode === \"streaming\") {\n // During a call: show current call stats\n const elapsed = Math.round((Date.now() - this.callStartTime) / 1000);\n\n // Output tokens: use actual if available, otherwise estimate from chars\n const outTokens = this.callOutputTokensEstimated\n ? Math.round(this.callOutputChars / FALLBACK_CHARS_PER_TOKEN)\n : this.callOutputTokens;\n const outEstimated = this.callOutputTokensEstimated;\n\n if (this.callInputTokens > 0) {\n const prefix = this.callInputTokensEstimated ? \"~\" : \"\";\n parts.push(\n chalk.dim(\"↑\") + chalk.yellow(` ${prefix}${formatTokens(this.callInputTokens)}`),\n );\n }\n if (outTokens > 0) {\n const prefix = outEstimated ? \"~\" : \"\";\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${prefix}${formatTokens(outTokens)}`));\n }\n parts.push(chalk.dim(`${elapsed}s`));\n } else {\n // Between calls: show cumulative stats\n const elapsed = Math.round((Date.now() - this.totalStartTime) / 1000);\n\n if (this.totalTokens > 0) {\n parts.push(chalk.magenta(formatTokens(this.totalTokens)));\n }\n if (this.iterations > 0) {\n parts.push(chalk.blue(`i${this.iterations}`));\n }\n if (this.totalCost > 0) {\n parts.push(chalk.cyan(`$${formatCost(this.totalCost)}`));\n }\n parts.push(chalk.dim(`${elapsed}s`));\n }\n\n return `${parts.join(chalk.dim(\" | \"))} ${chalk.green(\">\")} `;\n }\n}\n\n/**\n * Reads all data from a readable stream into a string.\n *\n * @param stream - Stream to read from\n * @returns Complete stream contents as string\n */\nasync function readStream(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: string[] = [];\n for await (const chunk of stream) {\n if (typeof chunk === \"string\") {\n chunks.push(chunk);\n } else {\n chunks.push(chunk.toString(\"utf8\"));\n }\n }\n return chunks.join(\"\");\n}\n\n/**\n * Normalizes a prompt by trimming whitespace.\n *\n * @param value - Prompt to normalize\n * @returns Trimmed prompt\n */\nfunction normalizePrompt(value: string): string {\n return value.trim();\n}\n\n/**\n * Resolves the user prompt from either command-line argument or stdin.\n * Priority: 1) promptArg if provided, 2) stdin if piped, 3) error if neither.\n *\n * @param promptArg - Optional prompt from command-line argument\n * @param env - CLI environment for accessing stdin\n * @returns Resolved and normalized prompt\n * @throws Error if no prompt available or stdin is empty\n */\nexport async function resolvePrompt(\n promptArg: string | undefined,\n env: CLIEnvironment,\n): Promise<string> {\n if (promptArg?.trim()) {\n return normalizePrompt(promptArg);\n }\n\n if (isInteractive(env.stdin)) {\n throw new Error(\"Prompt is required. Provide an argument or pipe content via stdin.\");\n }\n\n const pipedInput = normalizePrompt(await readStream(env.stdin));\n if (!pipedInput) {\n throw new Error(\"Received empty stdin payload. Provide a prompt to continue.\");\n }\n\n return pipedInput;\n}\n\n// Re-export summary rendering from formatters module\n// This maintains backward compatibility while organizing code better\nexport { renderSummary, type SummaryMetadata } from \"./ui/formatters.js\";\n\n/**\n * Executes a CLI action with error handling.\n * Catches errors, writes to stderr, and sets exit code 1 on failure.\n *\n * @param action - Async action to execute\n * @param env - CLI environment for error output and exit code\n */\nexport async function executeAction(\n action: () => Promise<void>,\n env: CLIEnvironment,\n): Promise<void> {\n try {\n await action();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n env.stderr.write(`${chalk.red.bold(\"Error:\")} ${message}\\n`);\n env.setExitCode(1);\n }\n}\n","/**\n * CLI output formatting utilities.\n *\n * This module provides formatting functions for displaying metrics, summaries,\n * and gadget results in a clean, consistent format across the llmist CLI.\n *\n * **Design principles:**\n * - Consistent formatting across all commands (agent, complete, models)\n * - Human-readable output with appropriate precision\n * - Color-coded for visual clarity (using chalk)\n * - Compact format optimized for terminal display\n *\n * **SHOWCASE:** Demonstrates how to build a polished CLI on top of llmist's core.\n */\n\nimport chalk from \"chalk\";\nimport { type MarkedExtension, marked } from \"marked\";\nimport { markedTerminal } from \"marked-terminal\";\nimport type { TokenUsage } from \"../../core/options.js\";\nimport type { StoredMedia } from \"../../gadgets/types.js\";\n\n/**\n * Lazy-initialized flag for marked-terminal configuration.\n *\n * We defer `marked.use(markedTerminal())` until first render because:\n * - markedTerminal() captures chalk's color level at call time\n * - At module import time, TTY detection may not be complete\n * - Lazy init ensures colors work in interactive terminals\n */\nlet markedConfigured = false;\n\n/**\n * Configure marked for terminal output (lazy initialization).\n *\n * Uses marked-terminal to convert markdown to ANSI-styled terminal output.\n * This enables rich formatting in TellUser messages and AskUser questions.\n *\n * We override marked-terminal's style functions with our own chalk instance\n * because marked-terminal bundles its own chalk that detects colors at module\n * load time. Bun's broken TTY detection causes that bundled chalk to detect\n * level 0 (no colors). See: https://github.com/oven-sh/bun/issues/1322\n *\n * By forcing `chalk.level = 3` on our imported chalk and passing custom style\n * functions, we ensure colors work regardless of TTY detection.\n *\n * Respects the NO_COLOR environment variable for accessibility.\n *\n * Note: Type assertion needed due to @types/marked-terminal lag behind the runtime API.\n */\nfunction ensureMarkedConfigured(): void {\n if (!markedConfigured) {\n // Respect NO_COLOR env var, otherwise force truecolor (level 3)\n chalk.level = process.env.NO_COLOR ? 0 : 3;\n\n // Override marked-terminal's style functions with our chalk instance\n // to work around Bun's broken TTY detection\n marked.use(\n markedTerminal({\n // Text styling\n strong: chalk.bold,\n em: chalk.italic,\n del: chalk.dim.gray.strikethrough,\n\n // Code styling\n code: chalk.yellow,\n codespan: chalk.yellow,\n\n // Headings\n heading: chalk.green.bold,\n firstHeading: chalk.magenta.underline.bold,\n\n // Links\n link: chalk.blue,\n href: chalk.blue.underline,\n\n // Block elements\n blockquote: chalk.gray.italic,\n\n // List formatting - reduce indentation and add bullet styling\n tab: 2, // Reduce from default 4 to 2 spaces\n listitem: chalk.reset, // Keep items readable (no dim)\n }) as unknown as MarkedExtension,\n );\n markedConfigured = true;\n }\n}\n\n/**\n * Renders markdown text as styled terminal output.\n *\n * Converts markdown syntax to ANSI escape codes for terminal display:\n * - **bold** and *italic* text\n * - `inline code` and code blocks\n * - Lists (bulleted and numbered)\n * - Headers\n * - Links (clickable in supported terminals)\n *\n * @param text - Markdown text to render\n * @returns ANSI-styled string for terminal output\n *\n * @example\n * ```typescript\n * renderMarkdown(\"**Important:** Check the `config.json` file\");\n * // Returns styled text with bold \"Important:\" and code-styled \"config.json\"\n * ```\n */\nexport function renderMarkdown(text: string): string {\n ensureMarkedConfigured();\n let rendered = marked.parse(text) as string;\n\n // Workaround for marked-terminal bug: inline markdown in list items\n // is not processed. Post-process to handle **bold** and *italic*.\n // See: https://github.com/mikaelbr/marked-terminal/issues\n rendered = rendered\n .replace(/\\*\\*(.+?)\\*\\*/g, (_, content) => chalk.bold(content))\n // Italic: require non-space after * to avoid matching bullet points ( * )\n .replace(/(?<!\\*)\\*(\\S[^*]*)\\*(?!\\*)/g, (_, content) => chalk.italic(content));\n\n // Remove trailing newlines that marked adds\n return rendered.trimEnd();\n}\n\n/**\n * Creates a rainbow-colored horizontal line for visual emphasis.\n * Cycles through colors for each character segment.\n * Uses the full terminal width for a complete visual separator.\n *\n * @returns Rainbow-colored separator string spanning the terminal width\n */\nfunction createRainbowSeparator(): string {\n const colors = [chalk.red, chalk.yellow, chalk.green, chalk.cyan, chalk.blue, chalk.magenta];\n const char = \"─\";\n // Use terminal width, fallback to 80 if not available (e.g., piped output)\n const width = process.stdout.columns || 80;\n let result = \"\";\n for (let i = 0; i < width; i++) {\n result += colors[i % colors.length](char);\n }\n return result;\n}\n\n/**\n * Renders markdown with colorful rainbow horizontal line separators above and below.\n * Use this for prominent markdown content that should stand out visually.\n *\n * @param text - Markdown text to render\n * @returns Rendered markdown with rainbow separators\n *\n * @example\n * ```typescript\n * renderMarkdownWithSeparators(\"**Hello** world!\");\n * // Returns rainbow line + styled markdown + rainbow line\n * ```\n */\nexport function renderMarkdownWithSeparators(text: string): string {\n const rendered = renderMarkdown(text);\n const separator = createRainbowSeparator();\n return `\\n${separator}\\n${rendered}\\n${separator}\\n`;\n}\n\n/**\n * Formats token count with 'k' suffix for thousands.\n *\n * Uses compact notation to save terminal space while maintaining readability.\n * Numbers below 1000 are shown as-is, larger numbers use 'k' suffix with one decimal.\n *\n * @param tokens - Number of tokens\n * @returns Formatted string (e.g., \"896\" or \"11.5k\")\n *\n * @example\n * ```typescript\n * formatTokens(896) // \"896\"\n * formatTokens(11500) // \"11.5k\"\n * formatTokens(1234) // \"1.2k\"\n * ```\n */\nexport function formatTokens(tokens: number): string {\n return tokens >= 1000 ? `${(tokens / 1000).toFixed(1)}k` : `${tokens}`;\n}\n\n/**\n * Formats cost with appropriate precision based on magnitude.\n *\n * Uses variable precision to balance readability and accuracy:\n * - Very small costs (<$0.001): 5 decimal places to show meaningful value\n * - Small costs (<$0.01): 4 decimal places for precision\n * - Medium costs (<$1): 3 decimal places for clarity\n * - Larger costs (≥$1): 2 decimal places (standard currency format)\n *\n * @param cost - Cost in USD\n * @returns Formatted cost string without currency symbol (e.g., \"0.0123\")\n *\n * @example\n * ```typescript\n * formatCost(0.00012) // \"0.00012\"\n * formatCost(0.0056) // \"0.0056\"\n * formatCost(0.123) // \"0.123\"\n * formatCost(1.5) // \"1.50\"\n * ```\n */\nexport function formatCost(cost: number): string {\n if (cost < 0.001) {\n return cost.toFixed(5);\n }\n if (cost < 0.01) {\n return cost.toFixed(4);\n }\n if (cost < 1) {\n return cost.toFixed(3);\n }\n return cost.toFixed(2);\n}\n\n/**\n * Display information for formatting an LLM call progress line.\n *\n * Used by both main agent display and nested subagent display.\n * This enables consistent formatting across all LLM call displays.\n */\nexport interface LLMCallDisplayInfo {\n /** Iteration number (0-indexed for subagents, 1-indexed for main) */\n iteration: number;\n /** Parent call number for hierarchical display (e.g., parent=1, iteration=2 → #1.2) */\n parentCallNumber?: number;\n /** Gadget invocation ID for unique subagent identification (e.g., #6.browse_web_1.2) */\n gadgetInvocationId?: string;\n /** Model name/ID */\n model: string;\n /** Input tokens sent to LLM */\n inputTokens?: number;\n /** Cached input tokens (prompt cache hit) */\n cachedInputTokens?: number;\n /** Output tokens received from LLM */\n outputTokens?: number;\n /** Elapsed time in seconds */\n elapsedSeconds: number;\n /** Cost in USD */\n cost?: number;\n /** Finish reason (null/undefined while streaming, string when done) */\n finishReason?: string | null;\n /** Whether the call is still streaming */\n isStreaming?: boolean;\n /** Spinner character for streaming display */\n spinner?: string;\n /** Context window usage percentage (optional, main agent only) */\n contextPercent?: number | null;\n /** Token estimation flags (when counts are estimated, not exact) */\n estimated?: { input?: boolean; output?: boolean };\n}\n\n/**\n * Formats an LLM call opening line for display.\n *\n * This is printed once when an LLM call starts, before streaming begins.\n * The opening line is static and never refreshed.\n *\n * **Format:** `→ #N model` (main agent) or `→ #N.gadgetId.M model` (subagent)\n *\n * @param iteration - Iteration/call number\n * @param model - Model name/ID\n * @param parentCallNumber - Parent call number for nested calls\n * @param gadgetInvocationId - Gadget invocation ID for unique subagent identification\n * @returns Formatted opening line string with ANSI colors\n *\n * @example\n * ```typescript\n * formatLLMCallOpening(1, \"gemini:gemini-2.5-flash\");\n * // Output: \"→ #1 gemini:gemini-2.5-flash\"\n *\n * formatLLMCallOpening(2, \"gemini:gemini-2.5-flash\", 1, \"browse_web_1\");\n * // Output: \"→ #1.browse_web_1.2 gemini:gemini-2.5-flash\"\n * ```\n */\nexport function formatLLMCallOpening(\n iteration: number,\n model: string,\n parentCallNumber?: number,\n gadgetInvocationId?: string,\n): string {\n let callNumber: string;\n if (parentCallNumber !== undefined && gadgetInvocationId) {\n // Subagent with full context: #parent.gadgetId.iteration\n callNumber = `#${parentCallNumber}.${gadgetInvocationId}.${iteration}`;\n } else if (parentCallNumber !== undefined) {\n // Subagent without gadget ID (legacy): #parent.iteration\n callNumber = `#${parentCallNumber}.${iteration}`;\n } else {\n // Main agent: #iteration\n callNumber = `#${iteration}`;\n }\n return `${chalk.dim(\"→\")} ${chalk.cyan(callNumber)} ${chalk.magenta(model)}`;\n}\n\n/**\n * Formats an LLM call progress line for display.\n *\n * This is the **shared formatting function** used by both main agent and\n * nested subagent displays. Using a single function eliminates code\n * duplication and ensures consistent formatting.\n *\n * **Format:** `#N model | %ctx | ↑ input | ⟳ cached | ↓ output | time | $cost | status`\n *\n * **Color scheme:**\n * - Cyan: Iteration number, cost, spinner\n * - Magenta: Model name\n * - Yellow: Input tokens\n * - Blue: Cached tokens\n * - Green: Output tokens, success checkmark\n *\n * @param info - Display information for the LLM call\n * @returns Formatted progress line string\n *\n * @example\n * ```typescript\n * // Streaming call\n * formatLLMCallLine({\n * iteration: 1,\n * model: \"claude-sonnet-4-20250514\",\n * inputTokens: 10400,\n * outputTokens: 49,\n * elapsedSeconds: 24.8,\n * cost: 0.0032,\n * isStreaming: true,\n * spinner: \"⠧\",\n * contextPercent: 1,\n * });\n * // Output: \"#1 claude-sonnet-4-20250514 | 1% | ↑ 10.4k | ↓ 49 | 24.8s | $0.0032 | ⠧\"\n *\n * // Completed call\n * formatLLMCallLine({\n * iteration: 0,\n * model: \"gemini-2.5-flash\",\n * inputTokens: 5200,\n * cachedInputTokens: 3000,\n * outputTokens: 36,\n * elapsedSeconds: 3.7,\n * cost: 0.00009,\n * finishReason: \"stop\",\n * });\n * // Output: \"#0 gemini-2.5-flash | ↑ 5.2k | ⟳ 3.0k | ↓ 36 | 3.7s | $0.00009 | ✓\"\n * ```\n */\nexport function formatLLMCallLine(info: LLMCallDisplayInfo): string {\n const parts: string[] = [];\n\n // #N or #N.gadgetId.M model (iteration number + model name) - combined as one unit\n // Hierarchical format: parent.gadgetId.child (e.g., #1.browse_web_1.2 for 2nd call of gadget browse_web_1 in parent #1)\n let callNumber: string;\n if (info.parentCallNumber !== undefined && info.gadgetInvocationId) {\n // Subagent with full context: #parent.gadgetId.iteration\n callNumber = `#${info.parentCallNumber}.${info.gadgetInvocationId}.${info.iteration}`;\n } else if (info.parentCallNumber !== undefined) {\n // Subagent without gadget ID (legacy): #parent.iteration\n callNumber = `#${info.parentCallNumber}.${info.iteration}`;\n } else {\n // Main agent: #iteration\n callNumber = `#${info.iteration}`;\n }\n parts.push(`${chalk.cyan(callNumber)} ${chalk.magenta(info.model)}`);\n\n // Context usage percentage (color-coded by usage level, main agent only)\n if (info.contextPercent !== undefined && info.contextPercent !== null) {\n const formatted = `${Math.round(info.contextPercent)}%`;\n if (info.contextPercent >= 80) {\n parts.push(chalk.red(formatted)); // Danger zone\n } else if (info.contextPercent >= 50) {\n parts.push(chalk.yellow(formatted)); // Warning zone\n } else {\n parts.push(chalk.green(formatted)); // Safe zone\n }\n }\n\n // ↑ input tokens\n if (info.inputTokens && info.inputTokens > 0) {\n const prefix = info.estimated?.input ? \"~\" : \"\";\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${prefix}${formatTokens(info.inputTokens)}`));\n }\n\n // ⟳ cached tokens\n if (info.cachedInputTokens && info.cachedInputTokens > 0) {\n parts.push(chalk.dim(\"⟳\") + chalk.blue(` ${formatTokens(info.cachedInputTokens)}`));\n }\n\n // ↓ output tokens\n if (info.outputTokens !== undefined && info.outputTokens > 0 || info.isStreaming) {\n const prefix = info.estimated?.output ? \"~\" : \"\";\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${prefix}${formatTokens(info.outputTokens ?? 0)}`));\n }\n\n // Time\n parts.push(chalk.dim(`${info.elapsedSeconds.toFixed(1)}s`));\n\n // Cost\n if (info.cost !== undefined && info.cost > 0) {\n parts.push(chalk.cyan(`$${formatCost(info.cost)}`));\n }\n\n // Finish reason at the END when completed (not streaming)\n // Always show the actual finish reason (STOP, end_turn, etc.)\n if (!info.isStreaming && info.finishReason !== undefined) {\n const reason = info.finishReason || \"stop\";\n // Uppercase for visibility, green for normal completion, yellow for others\n if (reason === \"stop\" || reason === \"end_turn\") {\n parts.push(chalk.green(reason.toUpperCase()));\n } else {\n parts.push(chalk.yellow(reason.toUpperCase()));\n }\n }\n\n const line = parts.join(chalk.dim(\" | \"));\n\n // Prepend spinner when streaming, ✓ when completed\n if (info.isStreaming && info.spinner) {\n return `${chalk.cyan(info.spinner)} ${line}`;\n }\n\n // Completed calls get ✓ prefix like gadgets\n if (!info.isStreaming) {\n return `${chalk.green(\"✓\")} ${line}`;\n }\n\n return line;\n}\n\n/**\n * Metadata for generating execution summaries.\n *\n * Contains optional metrics collected during agent/LLM execution.\n * All fields are optional to allow partial summaries when data isn't available.\n */\nexport interface SummaryMetadata {\n /** LLM finish reason (e.g., \"stop\", \"length\", \"tool_calls\") */\n finishReason?: string | null;\n\n /** Token usage statistics from LLM provider */\n usage?: TokenUsage;\n\n /** Number of agent iterations (LLM calls) */\n iterations?: number;\n\n /** Model name/ID being used */\n model?: string;\n\n /** Total cost in USD (calculated via ModelRegistry) */\n cost?: number;\n\n /** Elapsed time in seconds */\n elapsedSeconds?: number;\n}\n\n/**\n * Renders execution metadata as a compact, color-coded summary line.\n *\n * Formats agent/LLM execution metrics in a consistent format used across CLI commands.\n * Only includes fields that have values, making the output clean and concise.\n *\n * **Format:** `#N | ↑ input │ ↓ output │ time | cost | finish`\n *\n * **Color scheme:**\n * - Cyan: Iteration number and cost (highlights key metrics)\n * - Yellow: Input tokens (shows what you sent)\n * - Green: Output tokens (shows what you received)\n * - Dim: Separators and finish reason (de-emphasize metadata)\n *\n * @param metadata - Summary metadata to format\n * @returns Formatted summary string, or null if no fields are populated\n *\n * @example\n * ```typescript\n * // Full summary with all fields (including cached tokens)\n * renderSummary({\n * iterations: 3,\n * usage: { inputTokens: 896, outputTokens: 11500, totalTokens: 12396, cachedInputTokens: 500 },\n * elapsedSeconds: 9,\n * cost: 0.0123,\n * finishReason: \"stop\"\n * });\n * // Output: \"#3 | ↑ 896 | ⟳ 500 | ↓ 11.5k | 9s | $0.0123 | stop\"\n *\n * // Partial summary (only tokens, no cache hit)\n * renderSummary({\n * usage: { inputTokens: 500, outputTokens: 200, totalTokens: 700 }\n * });\n * // Output: \"↑ 500 | ↓ 200\"\n * ```\n */\nexport function renderSummary(metadata: SummaryMetadata): string | null {\n const parts: string[] = [];\n\n // Iteration number and model (#N modelname) - shown first for context\n if (metadata.iterations !== undefined) {\n const iterPart = chalk.cyan(`#${metadata.iterations}`);\n if (metadata.model) {\n parts.push(`${iterPart} ${chalk.magenta(metadata.model)}`);\n } else {\n parts.push(iterPart);\n }\n } else if (metadata.model) {\n // Model without iteration number\n parts.push(chalk.magenta(metadata.model));\n }\n\n // Token usage (↑ input │ ⟳ cached │ ✎ cache-write │ ↓ output) - core metrics\n if (metadata.usage) {\n const { inputTokens, outputTokens, cachedInputTokens, cacheCreationInputTokens } =\n metadata.usage;\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${formatTokens(inputTokens)}`));\n // Show cached tokens if present (indicates prompt caching hit - 0.1x cost)\n if (cachedInputTokens && cachedInputTokens > 0) {\n parts.push(chalk.dim(\"⟳\") + chalk.blue(` ${formatTokens(cachedInputTokens)}`));\n }\n // Show cache creation tokens if present (Anthropic cache writes - 1.25x cost)\n if (cacheCreationInputTokens && cacheCreationInputTokens > 0) {\n parts.push(chalk.dim(\"✎\") + chalk.magenta(` ${formatTokens(cacheCreationInputTokens)}`));\n }\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${formatTokens(outputTokens)}`));\n }\n\n // Elapsed time - performance metric\n if (metadata.elapsedSeconds !== undefined && metadata.elapsedSeconds > 0) {\n parts.push(chalk.dim(`${metadata.elapsedSeconds}s`));\n }\n\n // Cost - financial tracking (showcases ModelRegistry integration)\n if (metadata.cost !== undefined && metadata.cost > 0) {\n parts.push(chalk.cyan(`$${formatCost(metadata.cost)}`));\n }\n\n // Finish reason - completion status (shown last for context)\n if (metadata.finishReason) {\n parts.push(chalk.dim(metadata.finishReason));\n }\n\n // Return null if no fields populated (cleaner than empty string)\n if (parts.length === 0) {\n return null;\n }\n\n // Join with \" | \" separator for visual clarity\n return parts.join(chalk.dim(\" | \"));\n}\n\n/**\n * Metadata for generating overall execution summaries.\n *\n * Used for the final accumulated summary at the end of agent execution.\n */\nexport interface OverallSummaryMetadata {\n /** Total tokens across all calls */\n totalTokens?: number;\n\n /** Number of agent iterations (LLM calls) */\n iterations?: number;\n\n /** Total elapsed time in seconds */\n elapsedSeconds?: number;\n\n /** Total cost in USD */\n cost?: number;\n}\n\n/**\n * Renders overall accumulated execution summary as a distinct styled line.\n *\n * This is displayed at the end of agent execution to show total metrics.\n * Uses a \"total:\" prefix to distinguish from per-call summaries.\n *\n * **Format:** `total: 3.5k | #2 | 19s | $0.0021`\n *\n * @param metadata - Overall summary metadata\n * @returns Formatted summary string, or null if no fields are populated\n *\n * @example\n * ```typescript\n * renderOverallSummary({\n * totalTokens: 3500,\n * iterations: 2,\n * elapsedSeconds: 19,\n * cost: 0.0021\n * });\n * // Output: \"total: 3.5k | #2 | 19s | $0.0021\"\n * ```\n */\nexport function renderOverallSummary(metadata: OverallSummaryMetadata): string | null {\n const parts: string[] = [];\n\n // Total tokens - primary metric for overall summary\n if (metadata.totalTokens !== undefined && metadata.totalTokens > 0) {\n parts.push(chalk.dim(\"total:\") + chalk.magenta(` ${formatTokens(metadata.totalTokens)}`));\n }\n\n // Iteration count (#N)\n if (metadata.iterations !== undefined && metadata.iterations > 0) {\n parts.push(chalk.cyan(`#${metadata.iterations}`));\n }\n\n // Total elapsed time\n if (metadata.elapsedSeconds !== undefined && metadata.elapsedSeconds > 0) {\n parts.push(chalk.dim(`${metadata.elapsedSeconds}s`));\n }\n\n // Total cost\n if (metadata.cost !== undefined && metadata.cost > 0) {\n parts.push(chalk.cyan(`$${formatCost(metadata.cost)}`));\n }\n\n if (parts.length === 0) {\n return null;\n }\n\n return parts.join(chalk.dim(\" | \"));\n}\n\n/**\n * Aggregated metrics from subagent LLM calls.\n *\n * These metrics are collected from all nested LLM calls that occur during\n * gadget execution (e.g., BrowseWeb spawns multiple LLM calls internally).\n */\nexport interface SubagentMetrics {\n /** Total input tokens across all subagent calls */\n inputTokens: number;\n /** Total output tokens across all subagent calls */\n outputTokens: number;\n /** Total cached input tokens across all subagent calls */\n cachedInputTokens: number;\n /** Total cost in USD across all subagent calls */\n cost: number;\n /** Number of LLM calls made by the subagent */\n callCount: number;\n}\n\n/**\n * Gadget execution result for formatting.\n *\n * Contains metadata about a single gadget invocation during agent execution.\n */\nexport interface GadgetResult {\n /** Name of the gadget that was executed */\n gadgetName: string;\n\n /** Execution time in milliseconds */\n executionTimeMs: number;\n\n /** Error message if gadget failed */\n error?: string;\n\n /** Result value from successful gadget execution */\n result?: string;\n\n /** Whether this gadget execution ended the agent loop */\n breaksLoop?: boolean;\n\n /** Parameters passed to the gadget */\n parameters?: Record<string, unknown>;\n\n /** Token count for output (calculated via provider API) */\n tokenCount?: number;\n\n /** Media outputs (images, audio, etc.) produced by the gadget */\n media?: StoredMedia[];\n\n /** Aggregated metrics from subagent LLM calls (if gadget spawned a subagent) */\n subagentMetrics?: SubagentMetrics;\n}\n\n/**\n * Formats a gadget execution result as a 2-line output for stderr.\n *\n * Provides visual feedback for gadget execution during agent runs.\n *\n * **Format (2 lines):**\n * - Line 1 (call): `→ GadgetName(param=value, ...)` - shows \"was called\"\n * - Line 2 (result): ` ✓ GadgetName ↓ 248 4ms: preview` - shows execution result\n * - Error: Line 2 becomes ` ✗ GadgetName error: message 2ms`\n *\n * **Design:**\n * - All parameters shown inline (truncated if too long)\n * - Output shown as token count (via provider API) or bytes as fallback\n * - Execution time always shown at the end\n *\n * @param result - Gadget execution result with timing and output info\n * @returns Formatted 2-line string with ANSI colors\n *\n * @example\n * ```typescript\n * // Successful gadget execution with token count\n * formatGadgetSummary({\n * gadgetName: \"ListDirectory\",\n * executionTimeMs: 4,\n * parameters: { path: \".\", recursive: true },\n * result: \"Type | Name | Size...\",\n * tokenCount: 248\n * });\n * // Output: \"→ ListDirectory(path=., recursive=true)\\n ✓ ListDirectory ↓ 248 4ms: ...\"\n *\n * // Error case\n * formatGadgetSummary({\n * gadgetName: \"ReadFile\",\n * executionTimeMs: 2,\n * parameters: { path: \"/missing.txt\" },\n * error: \"File not found\"\n * });\n * // Output: \"→ ReadFile(path=/missing.txt)\\n ✗ ReadFile error: File not found 2ms\"\n * ```\n */\n/**\n * Gets the raw string value for a parameter (without truncation or colors).\n */\nfunction getRawValue(value: unknown): string {\n if (typeof value === \"string\") {\n return value;\n }\n if (typeof value === \"boolean\" || typeof value === \"number\") {\n return String(value);\n }\n return JSON.stringify(value);\n}\n\n/**\n * Truncates a string to maxLen characters with ellipsis if needed.\n * The ellipsis is included in the maxLen budget (result is always <= maxLen chars).\n * @internal Exported for testing\n */\nexport function truncateValue(str: string, maxLen: number): string {\n if (maxLen <= 0) return \"\";\n if (str.length <= maxLen) return str;\n // Account for ellipsis taking 1 char of the budget\n return `${str.slice(0, maxLen - 1)}…`;\n}\n\n/**\n * Formats parameters as a compact inline string with color-coded keys and values.\n * Expands to fit available terminal width when maxWidth is provided.\n *\n * @param params - Parameter key-value pairs\n * @param maxWidth - Optional maximum width for the entire parameters string (excluding parentheses)\n * @returns Formatted string with dim keys and cyan values, e.g., \"path=., recursive=true\"\n */\nexport function formatParametersInline(\n params: Record<string, unknown> | undefined,\n maxWidth?: number,\n): string {\n if (!params || Object.keys(params).length === 0) {\n return \"\";\n }\n\n const entries = Object.entries(params);\n const defaultLimit = 30;\n\n // Get raw values for each entry\n const rawValues = entries.map(([, value]) => getRawValue(value));\n\n // Calculate overhead: \"key=\" for each entry, \", \" between entries\n const overhead = entries.reduce((sum, [key], i) => {\n return sum + key.length + 1 + (i > 0 ? 2 : 0); // \"key=\" + \", \" separator\n }, 0);\n\n // Determine limits for each value\n let limits: number[];\n\n if (maxWidth && maxWidth > overhead) {\n const availableForValues = maxWidth - overhead;\n const totalRawLength = rawValues.reduce((sum, v) => sum + v.length, 0);\n\n if (totalRawLength <= availableForValues) {\n // Everything fits - no truncation needed\n limits = rawValues.map(() => Infinity);\n } else {\n // Distribute space proportionally, with minimum of 10 chars per value\n const minPerValue = 10;\n const minTotal = entries.length * minPerValue;\n\n if (availableForValues <= minTotal) {\n // Very tight - give each value equal minimum space\n limits = rawValues.map(() => Math.max(1, Math.floor(availableForValues / entries.length)));\n } else {\n // Proportional distribution\n limits = rawValues.map((v) => {\n const proportion = v.length / totalRawLength;\n return Math.max(minPerValue, Math.floor(proportion * availableForValues));\n });\n\n // CRITICAL: Ensure total limits don't exceed budget\n // The minPerValue floor can cause sum of limits to exceed availableForValues\n const totalLimits = limits.reduce((sum, l) => sum + l, 0);\n if (totalLimits > availableForValues) {\n // Scale down proportionally to fit within budget\n const scale = availableForValues / totalLimits;\n limits = limits.map((l) => Math.max(1, Math.floor(l * scale)));\n }\n }\n }\n } else {\n // No maxWidth or too small - use default limit\n limits = rawValues.map(() => defaultLimit);\n }\n\n // Format each entry with its limit\n return entries\n .map(([key, _], i) => {\n const formatted = truncateValue(rawValues[i], limits[i]);\n return `${chalk.dim(key)}${chalk.dim(\"=\")}${chalk.cyan(formatted)}`;\n })\n .join(chalk.dim(\", \"));\n}\n\n/**\n * Formats a gadget opening line (printed once when gadget is called).\n *\n * Shows the call indicator (`→`) for static opening lines.\n *\n * Format: `→ GadgetName(param=value, ...)`\n *\n * @param gadgetName - Name of the gadget being executed\n * @param parameters - Parameters passed to the gadget\n * @returns Formatted one-liner string with ANSI colors\n */\nexport function formatGadgetOpening(\n gadgetName: string,\n parameters?: Record<string, unknown>,\n): string {\n // Get terminal width (default to 80 if not available)\n const terminalWidth = process.stdout.columns || 80;\n\n const gadgetLabel = chalk.magenta.bold(gadgetName);\n\n // Calculate fixed parts length: \"→ \" + gadgetName + \"()\"\n // Arrow=2, parens=2\n const fixedLength = 2 + gadgetName.length + 2;\n\n // Available width for parameters\n const availableForParams = Math.max(40, terminalWidth - fixedLength - 3); // -3 safety margin\n\n const paramsStr = formatParametersInline(parameters, availableForParams);\n const paramsLabel = paramsStr ? `${chalk.dim(\"(\")}${paramsStr}${chalk.dim(\")\")}` : \"\";\n\n return `${chalk.dim(\"→\")} ${gadgetLabel}${paramsLabel}`;\n}\n\n/**\n * Formats a single-line gadget result (for nested gadgets).\n *\n * Unlike `formatGadgetLine()` which returns 2 lines for completed gadgets,\n * this returns a single result line. Used for nested gadgets where the\n * opening line was already printed separately.\n *\n * Format: `✓ GadgetName [↑ in | ↓ out | $cost |] time`\n *\n * @param info - Result information\n * @returns Formatted single-line result string with ANSI colors\n */\nexport function formatNestedGadgetResult(info: {\n name: string;\n elapsedSeconds: number;\n inputTokens?: number;\n outputTokens?: number;\n cost?: number;\n error?: string;\n}): string {\n const parts: string[] = [];\n\n // Add token metrics if present\n if (info.inputTokens && info.inputTokens > 0) {\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${formatTokens(info.inputTokens)}`));\n }\n if (info.outputTokens && info.outputTokens > 0) {\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${formatTokens(info.outputTokens)}`));\n }\n if (info.cost && info.cost > 0) {\n parts.push(chalk.cyan(`$${formatCost(info.cost)}`));\n }\n\n const metricsStr = parts.length > 0 ? ` ${parts.join(chalk.dim(\" | \"))} ${chalk.dim(\"|\")}` : \"\";\n const timeStr = chalk.dim(`${info.elapsedSeconds.toFixed(1)}s`);\n const gadgetLabel = chalk.magenta.bold(info.name);\n\n // Use error indicator if failed\n const icon = info.error ? chalk.red(\"✗\") : chalk.green(\"✓\");\n\n return `${icon} ${gadgetLabel}${metricsStr} ${timeStr}`;\n}\n\n/**\n * Display information for formatting a gadget call progress line.\n *\n * Used by both main gadget display and nested subagent gadget display.\n * This enables consistent formatting across all gadget displays.\n */\nexport interface GadgetDisplayInfo {\n /** Gadget name */\n name: string;\n /** Parameters passed to the gadget */\n parameters?: Record<string, unknown>;\n /** Elapsed time in seconds */\n elapsedSeconds: number;\n /** Whether the gadget has completed */\n isComplete: boolean;\n /** Token count from output (if available) */\n tokenCount?: number;\n /** Output size in bytes (fallback if tokenCount unavailable) */\n outputBytes?: number;\n /** Error message if gadget failed */\n error?: string;\n /** Whether the gadget breaks the loop (uses ⏹ icon) */\n breaksLoop?: boolean;\n\n // Realtime subagent metrics (for gadgets that run LLM calls internally)\n /** Aggregated input tokens from nested LLM calls */\n subagentInputTokens?: number;\n /** Aggregated output tokens from nested LLM calls */\n subagentOutputTokens?: number;\n /** Aggregated cached tokens from nested LLM calls */\n subagentCachedTokens?: number;\n /** Aggregated cost from nested LLM calls */\n subagentCost?: number;\n}\n\n/**\n * Formats a gadget call progress line for display.\n *\n * This is the **shared formatting function** used by both main gadget display\n * and nested subagent gadget display. Using a single function eliminates code\n * duplication and ensures consistent formatting.\n *\n * **Format (in-progress):** `⏵ GadgetName(params)` (no time - time shown on result)\n * **Format (completed - 2 lines):**\n * Line 1: `→ GadgetName(params)` (call indicator)\n * Line 2: ` ✓ GadgetName output time` (result indicator)\n * **Format (error):** `✗ GadgetName(params) error: msg time`\n *\n * @param info - Display information for the gadget call\n * @param maxWidth - Maximum width for parameter truncation (optional)\n * @returns Formatted progress line string\n *\n * @example\n * ```typescript\n * // In-progress call (no time shown)\n * formatGadgetLine({\n * name: \"Navigate\",\n * parameters: { url: \"https://example.com\" },\n * elapsedSeconds: 2.5,\n * isComplete: false,\n * });\n * // Output: \"⏵ Navigate(url=https://example.com)\"\n *\n * // Completed call (time on result line)\n * formatGadgetLine({\n * name: \"GetPageContent\",\n * parameters: { selector: \"article\" },\n * elapsedSeconds: 1.2,\n * isComplete: true,\n * tokenCount: 248,\n * });\n * // Output: \"→ GetPageContent(selector=article)\\n ✓ GetPageContent ↓ 248 1.2s\"\n * ```\n */\nexport function formatGadgetLine(info: GadgetDisplayInfo, maxWidth?: number): string {\n // Get terminal width if not specified\n const terminalWidth = maxWidth ?? process.stdout.columns ?? 80;\n\n const gadgetLabel = chalk.magenta.bold(info.name);\n const timeStr = `${info.elapsedSeconds.toFixed(1)}s`;\n const timeLabel = chalk.dim(timeStr);\n\n // Calculate fixed parts length for parameter truncation\n // Icon may be 2 columns wide in some terminals (Unicode width varies)\n const fixedLength = 3 + info.name.length + 2 + 1 + timeStr.length;\n const availableForParams = Math.max(40, terminalWidth - fixedLength - 3); // -3 safety margin\n\n // Format parameters inline with truncation\n const paramsStr = formatParametersInline(info.parameters, availableForParams);\n const paramsLabel = paramsStr ? `${chalk.dim(\"(\")}${paramsStr}${chalk.dim(\")\")}` : \"\";\n\n // Error case\n if (info.error) {\n const errorMsg = info.error.length > 50 ? `${info.error.slice(0, 50)}…` : info.error;\n return `${chalk.red(\"✗\")} ${gadgetLabel}${paramsLabel} ${chalk.red(\"error:\")} ${errorMsg} ${timeLabel}`;\n }\n\n // In-progress case - show elapsed time and any accumulated subagent metrics\n // NO parameters here - they were already shown on the opening line (→ GadgetName(params))\n // This keeps the refreshing line compact and focused on changing metrics\n if (!info.isComplete) {\n const parts: string[] = [];\n\n // Add subagent metrics if present (for gadgets that run LLM calls internally)\n if (info.subagentInputTokens && info.subagentInputTokens > 0) {\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${formatTokens(info.subagentInputTokens)}`));\n }\n if (info.subagentOutputTokens && info.subagentOutputTokens > 0) {\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${formatTokens(info.subagentOutputTokens)}`));\n }\n if (info.subagentCost && info.subagentCost > 0) {\n parts.push(chalk.cyan(`$${formatCost(info.subagentCost)}`));\n }\n\n // Always show elapsed time\n parts.push(chalk.dim(`${info.elapsedSeconds.toFixed(1)}s`));\n\n const metricsStr = parts.length > 0 ? ` ${parts.join(chalk.dim(\" | \"))}` : \"\";\n return `${chalk.blue(\"⏵\")} ${gadgetLabel}${metricsStr}`;\n }\n\n // Completed case - 2-line format for consistency with formatGadgetSummary\n // Line 1: icon + name + params (START info)\n // Line 2: name reference + output + time (END info)\n let outputLabel: string;\n if (info.tokenCount !== undefined && info.tokenCount > 0) {\n // Use same format as LLM calls: \"↓ 1.2k\" with dim arrow and green number\n outputLabel = chalk.dim(\"↓\") + chalk.green(` ${formatTokens(info.tokenCount)} `);\n } else if (info.outputBytes !== undefined && info.outputBytes > 0) {\n outputLabel = chalk.green(formatBytes(info.outputBytes)) + \" \";\n } else {\n outputLabel = \"\"; // No output to show\n }\n\n // Line 1: → (call indicator), Line 2: ✓/⏹ (result indicator)\n const resultIcon = info.breaksLoop ? chalk.yellow(\"⏹\") : chalk.green(\"✓\");\n const nameRef = chalk.magenta(info.name); // Not bold - line 2 is for reference, not emphasis\n\n const line1 = `${chalk.dim(\"→\")} ${gadgetLabel}${paramsLabel}`;\n\n // Line 2: ensure it fits within terminal width\n // Fixed parts: \" ✓ \" + name + \" \" + output + \" \" + time\n const line2Prefix = ` ${resultIcon} ${nameRef} ${outputLabel}`;\n const line2 = `${line2Prefix}${timeLabel}`;\n\n return `${line1}\\n${line2}`;\n}\n\n/**\n * Formats byte count in human-readable form.\n *\n * @param bytes - Number of bytes\n * @returns Formatted string like \"245 bytes\" or \"1.2 KB\"\n */\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} bytes`;\n }\n if (bytes < 1024 * 1024) {\n return `${(bytes / 1024).toFixed(1)} KB`;\n }\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\n/**\n * Truncates output text for preview display.\n * Normalizes whitespace (collapses newlines/tabs to single spaces) and truncates with ellipsis.\n *\n * @param output - The output text to truncate\n * @param maxWidth - Maximum character width for the preview\n * @returns Truncated string with ellipsis if needed\n */\nfunction truncateOutputPreview(output: string, maxWidth: number): string {\n // Normalize whitespace (collapse newlines/tabs to single spaces)\n const normalized = output.replace(/\\s+/g, \" \").trim();\n if (normalized.length <= maxWidth) return normalized;\n return normalized.slice(0, maxWidth - 1) + \"…\";\n}\n\n/**\n * Get icon for media kind.\n *\n * @param kind - Media kind (image, audio, video, file)\n * @returns Emoji icon for the media kind\n */\nfunction getMediaIcon(kind: string): string {\n switch (kind) {\n case \"image\":\n return \"📷\";\n case \"audio\":\n return \"🔊\";\n case \"video\":\n return \"🎬\";\n case \"file\":\n return \"📄\";\n default:\n return \"📎\";\n }\n}\n\n/**\n * Formats a single media output for CLI display.\n *\n * Format: `[📷 media_a1b2c3 image/png 256KB] → /path/to/file.png`\n *\n * @param media - Stored media information\n * @returns Formatted media line with icon, ID, MIME type, size, and path\n */\nfunction formatMediaLine(media: StoredMedia): string {\n const icon = getMediaIcon(media.kind);\n const id = chalk.cyan(media.id);\n const mimeType = chalk.dim(media.mimeType);\n const size = chalk.yellow(formatBytes(media.sizeBytes));\n const path = chalk.dim(media.path);\n\n return `${chalk.dim(\"[\")}${icon} ${id} ${mimeType} ${size}${chalk.dim(\"]\")} ${chalk.dim(\"→\")} ${path}`;\n}\n\nexport function formatGadgetSummary(result: GadgetResult): string {\n // Get terminal width (default to 80 if not available)\n const terminalWidth = process.stdout.columns || 80;\n\n // Format gadget name\n const gadgetLabel = chalk.magenta.bold(result.gadgetName);\n\n // Show seconds for values >= 1000ms, otherwise milliseconds\n const timeStr =\n result.executionTimeMs >= 1000\n ? `${(result.executionTimeMs / 1000).toFixed(1)}s`\n : `${Math.round(result.executionTimeMs)}ms`;\n const timeLabel = chalk.dim(timeStr);\n\n // Note: Opening line (→ GadgetName(params)) is now printed separately on gadget_call\n // This function only returns the RESULT line\n\n // Result line: name reference + output metrics + time + preview\n const nameRef = chalk.magenta(result.gadgetName); // Not bold - result line is for reference, not emphasis\n\n // Calculate output metrics (tokens or bytes)\n // Use same format as LLM calls: \"↓ 1.2k\" with dim arrow and green number\n // Skip if we have subagent metrics - those provide comprehensive token info\n const hasSubagentMetrics = result.subagentMetrics && result.subagentMetrics.callCount > 0;\n let outputLabel: string;\n let outputStrRaw: string; // For preview width calculation (without ANSI codes)\n if (!hasSubagentMetrics && result.tokenCount !== undefined && result.tokenCount > 0) {\n const tokenStr = formatTokens(result.tokenCount);\n outputLabel = chalk.dim(\"↓\") + chalk.green(` ${tokenStr} `);\n outputStrRaw = `↓ ${tokenStr} `;\n } else if (!hasSubagentMetrics && result.result) {\n const outputBytes = Buffer.byteLength(result.result, \"utf-8\");\n if (outputBytes > 0) {\n const bytesStr = formatBytes(outputBytes);\n outputLabel = chalk.green(bytesStr) + \" \";\n outputStrRaw = bytesStr + \" \";\n } else {\n outputLabel = \"\";\n outputStrRaw = \"\";\n }\n } else {\n outputLabel = \"\";\n outputStrRaw = \"\";\n }\n\n // Error case: show error message with ✗ (opening line was already printed on gadget_call)\n if (result.error) {\n const errorMsg = result.error.length > 50 ? `${result.error.slice(0, 50)}…` : result.error;\n return `${chalk.red(\"✗\")} ${nameRef} ${chalk.red(\"error:\")} ${errorMsg} ${timeLabel}`;\n }\n\n // Result icon: ✓ for success, ⏹ for loop-breaking\n const resultIcon = result.breaksLoop ? chalk.yellow(\"⏹\") : chalk.green(\"✓\");\n\n // Build result line with output preview\n // Calculate available width for preview (~60% of terminal)\n const previewWidth = Math.floor(terminalWidth * 0.6);\n // Account for prefix: \"✓ \" + name + \" \" + output + time + \": \"\n const prefixLength = 2 + result.gadgetName.length + 1 + outputStrRaw.length + timeStr.length + 2;\n const availablePreview = Math.max(20, previewWidth - prefixLength);\n\n // Custom previews for specific gadgets\n let customPreview: string | undefined;\n\n // TodoUpsert: show status emoji + content instead of generic output\n if (result.gadgetName === \"TodoUpsert\" && result.parameters?.content) {\n const statusEmoji =\n result.parameters.status === \"done\"\n ? \"✅\"\n : result.parameters.status === \"in_progress\"\n ? \"🔄\"\n : \"⬜\";\n const content = String(result.parameters.content);\n customPreview = `${statusEmoji} ${truncateOutputPreview(content, availablePreview - 3)}`; // -3 for emoji+space\n }\n\n // GoogleSearch: show query and result count\n if (result.gadgetName === \"GoogleSearch\" && result.parameters?.query) {\n const query = String(result.parameters.query);\n // Parse result count from output - try multiple patterns\n const countMatch =\n result.result?.match(/\\((\\d+)\\s+of\\s+[\\d,]+\\s+results?\\)/i) || // \"(10 of 36400000 results)\"\n result.result?.match(/(\\d+)\\s+results?\\s+found/i) || // \"10 results found\"\n result.result?.match(/found\\s+(\\d+)\\s+results?/i); // \"found 10 results\"\n // Fall back to maxResults parameter if no count found in output\n const count = countMatch?.[1] ?? (result.parameters.maxResults ? String(result.parameters.maxResults) : null);\n const countStr = count ? ` → ${count} results` : \"\";\n const queryPreview = truncateOutputPreview(query, availablePreview - 5 - countStr.length); // 🔍 + space + quotes\n customPreview = `🔍 \"${queryPreview}\"${countStr}`;\n }\n\n // Build subagent metrics string if this gadget spawned a subagent\n // Format: \"↑ input | ⟳ cached | ↓ output | $cost\"\n let subagentMetricsStr = \"\";\n if (result.subagentMetrics && result.subagentMetrics.callCount > 0) {\n const parts: string[] = [];\n const m = result.subagentMetrics;\n\n // ↑ input tokens\n if (m.inputTokens > 0) {\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${formatTokens(m.inputTokens)}`));\n }\n\n // ⟳ cached tokens\n if (m.cachedInputTokens > 0) {\n parts.push(chalk.dim(\"⟳\") + chalk.blue(` ${formatTokens(m.cachedInputTokens)}`));\n }\n\n // ↓ output tokens\n if (m.outputTokens > 0) {\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${formatTokens(m.outputTokens)}`));\n }\n\n // $cost\n if (m.cost > 0) {\n parts.push(chalk.cyan(`$${formatCost(m.cost)}`));\n }\n\n if (parts.length > 0) {\n subagentMetricsStr = parts.join(chalk.dim(\" | \")) + chalk.dim(\" | \");\n }\n }\n\n // Build result line (opening line is now printed separately on gadget_call)\n let resultLine: string;\n const previewContent = customPreview ?? (result.result?.trim() ? truncateOutputPreview(result.result, availablePreview) : null);\n if (previewContent) {\n resultLine = `${resultIcon} ${nameRef} ${outputLabel}${subagentMetricsStr}${timeLabel}${chalk.dim(\":\")} ${chalk.dim(previewContent)}`;\n } else {\n // No output content\n resultLine = `${resultIcon} ${nameRef} ${outputLabel}${subagentMetricsStr}${timeLabel}`;\n }\n\n let output = resultLine;\n\n // Add media lines if present (images, audio, etc.)\n if (result.media && result.media.length > 0) {\n const mediaLines = result.media.map(formatMediaLine);\n output += \"\\n\" + mediaLines.join(\"\\n\");\n }\n\n // TellUser gadget: display full message content below (with markdown and separators)\n if (result.gadgetName === \"TellUser\" && result.parameters?.message) {\n const message = String(result.parameters.message);\n const rendered = renderMarkdownWithSeparators(message);\n return `${output}\\n${rendered}`;\n }\n\n return output;\n}\n","import type { Command } from \"commander\";\nimport type {\n AgentConfig,\n CompleteConfig,\n CustomCommandConfig,\n GadgetPermissionPolicy,\n GlobalSubagentConfig,\n SubagentConfigMap,\n} from \"./config.js\";\nimport { DEFAULT_MODEL, OPTION_DESCRIPTIONS, OPTION_FLAGS } from \"./constants.js\";\nimport { createNumericParser } from \"./utils.js\";\n\n/**\n * CLI options for the complete command (camelCase, matching Commander output).\n */\nexport interface CLICompleteOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxTokens?: number;\n quiet?: boolean;\n logLlmRequests?: string | boolean;\n /** Path to image file to include with the prompt */\n image?: string;\n /** Path to audio file to include with the prompt */\n audio?: string;\n}\n\n/**\n * CLI options for the agent command (camelCase, matching Commander output).\n */\nexport interface CLIAgentOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxIterations?: number;\n gadget?: string[];\n builtins: boolean;\n builtinInteraction: boolean;\n gadgetStartPrefix?: string;\n gadgetEndPrefix?: string;\n gadgetArgPrefix?: string;\n gadgetApproval?: GadgetPermissionPolicy;\n quiet?: boolean;\n logLlmRequests?: string | boolean;\n /** Path to image file to include with the initial prompt */\n image?: string;\n /** Path to audio file to include with the initial prompt */\n audio?: string;\n /** Profile-level subagent configuration overrides */\n subagents?: SubagentConfigMap;\n /** Global subagent configuration (from [subagents] section) */\n globalSubagents?: GlobalSubagentConfig;\n}\n\n/**\n * Adds complete command options to a Commander command.\n *\n * @param cmd - Command to add options to\n * @param defaults - Optional defaults from config file\n * @returns The command with options added\n */\nexport function addCompleteOptions(cmd: Command, defaults?: CompleteConfig): Command {\n return cmd\n .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, defaults?.model ?? DEFAULT_MODEL)\n .option(OPTION_FLAGS.systemPrompt, OPTION_DESCRIPTIONS.systemPrompt, defaults?.system)\n .option(\n OPTION_FLAGS.temperature,\n OPTION_DESCRIPTIONS.temperature,\n createNumericParser({ label: \"Temperature\", min: 0, max: 2 }),\n defaults?.temperature,\n )\n .option(\n OPTION_FLAGS.maxTokens,\n OPTION_DESCRIPTIONS.maxTokens,\n createNumericParser({ label: \"Max tokens\", integer: true, min: 1 }),\n defaults?.[\"max-tokens\"],\n )\n .option(OPTION_FLAGS.quiet, OPTION_DESCRIPTIONS.quiet, defaults?.quiet)\n .option(\n OPTION_FLAGS.logLlmRequests,\n OPTION_DESCRIPTIONS.logLlmRequests,\n defaults?.[\"log-llm-requests\"],\n )\n .option(OPTION_FLAGS.inputImage, OPTION_DESCRIPTIONS.inputImage)\n .option(OPTION_FLAGS.inputAudio, OPTION_DESCRIPTIONS.inputAudio);\n}\n\n/**\n * Adds agent command options to a Commander command.\n *\n * @param cmd - Command to add options to\n * @param defaults - Optional defaults from config file\n * @returns The command with options added\n */\nexport function addAgentOptions(cmd: Command, defaults?: AgentConfig): Command {\n // Gadget accumulator needs special handling for defaults\n const gadgetAccumulator = (value: string, previous: string[] = []): string[] => [\n ...previous,\n value,\n ];\n const defaultGadgets = defaults?.gadgets ?? defaults?.gadget ?? [];\n\n return cmd\n .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, defaults?.model ?? DEFAULT_MODEL)\n .option(OPTION_FLAGS.systemPrompt, OPTION_DESCRIPTIONS.systemPrompt, defaults?.system)\n .option(\n OPTION_FLAGS.temperature,\n OPTION_DESCRIPTIONS.temperature,\n createNumericParser({ label: \"Temperature\", min: 0, max: 2 }),\n defaults?.temperature,\n )\n .option(\n OPTION_FLAGS.maxIterations,\n OPTION_DESCRIPTIONS.maxIterations,\n createNumericParser({ label: \"Max iterations\", integer: true, min: 1 }),\n defaults?.[\"max-iterations\"],\n )\n .option(OPTION_FLAGS.gadgetModule, OPTION_DESCRIPTIONS.gadgetModule, gadgetAccumulator, [\n ...defaultGadgets,\n ])\n .option(OPTION_FLAGS.noBuiltins, OPTION_DESCRIPTIONS.noBuiltins, defaults?.builtins !== false)\n .option(\n OPTION_FLAGS.noBuiltinInteraction,\n OPTION_DESCRIPTIONS.noBuiltinInteraction,\n defaults?.[\"builtin-interaction\"] !== false,\n )\n .option(OPTION_FLAGS.quiet, OPTION_DESCRIPTIONS.quiet, defaults?.quiet)\n .option(\n OPTION_FLAGS.logLlmRequests,\n OPTION_DESCRIPTIONS.logLlmRequests,\n defaults?.[\"log-llm-requests\"],\n )\n .option(OPTION_FLAGS.inputImage, OPTION_DESCRIPTIONS.inputImage)\n .option(OPTION_FLAGS.inputAudio, OPTION_DESCRIPTIONS.inputAudio);\n}\n\n/**\n * Converts kebab-case config to camelCase command options for complete command.\n */\nexport function configToCompleteOptions(\n config: CustomCommandConfig,\n): Partial<CLICompleteOptions> {\n const result: Partial<CLICompleteOptions> = {};\n if (config.model !== undefined) result.model = config.model;\n if (config.system !== undefined) result.system = config.system;\n if (config.temperature !== undefined) result.temperature = config.temperature;\n if (config[\"max-tokens\"] !== undefined) result.maxTokens = config[\"max-tokens\"];\n if (config.quiet !== undefined) result.quiet = config.quiet;\n if (config[\"log-llm-requests\"] !== undefined) result.logLlmRequests = config[\"log-llm-requests\"];\n return result;\n}\n\n/**\n * Converts kebab-case config to camelCase command options for agent command.\n */\nexport function configToAgentOptions(config: CustomCommandConfig): Partial<CLIAgentOptions> {\n const result: Partial<CLIAgentOptions> = {};\n if (config.model !== undefined) result.model = config.model;\n if (config.system !== undefined) result.system = config.system;\n if (config.temperature !== undefined) result.temperature = config.temperature;\n if (config[\"max-iterations\"] !== undefined) result.maxIterations = config[\"max-iterations\"];\n // Prefer gadgets (plural) from resolved config, fall back to legacy gadget (singular)\n const gadgets = config.gadgets ?? config.gadget;\n if (gadgets !== undefined) result.gadget = gadgets;\n if (config.builtins !== undefined) result.builtins = config.builtins;\n if (config[\"builtin-interaction\"] !== undefined)\n result.builtinInteraction = config[\"builtin-interaction\"];\n if (config[\"gadget-start-prefix\"] !== undefined)\n result.gadgetStartPrefix = config[\"gadget-start-prefix\"];\n if (config[\"gadget-end-prefix\"] !== undefined)\n result.gadgetEndPrefix = config[\"gadget-end-prefix\"];\n if (config[\"gadget-arg-prefix\"] !== undefined)\n result.gadgetArgPrefix = config[\"gadget-arg-prefix\"];\n if (config[\"gadget-approval\"] !== undefined) result.gadgetApproval = config[\"gadget-approval\"];\n if (config.quiet !== undefined) result.quiet = config.quiet;\n if (config[\"log-llm-requests\"] !== undefined) result.logLlmRequests = config[\"log-llm-requests\"];\n if (config.subagents !== undefined) result.subagents = config.subagents;\n return result;\n}\n","/**\n * TUI screen lifecycle management.\n *\n * Handles creation, rendering, and cleanup of the blessed Screen instance.\n * Ensures proper terminal restoration on exit.\n */\n\nimport { Screen, setRuntime, NodeRuntime } from \"@unblessed/node\";\nimport type { TUIScreenContext } from \"./types.js\";\n\n// Initialize the Node.js runtime (required before any blessed widgets can be created)\nlet runtimeInitialized = false;\n\nfunction ensureRuntimeInitialized(): void {\n if (!runtimeInitialized) {\n setRuntime(new NodeRuntime());\n runtimeInitialized = true;\n }\n}\n\n/** Default render debounce interval in milliseconds */\nconst RENDER_DEBOUNCE_MS = 16; // ~60fps\n\n/**\n * Creates and configures a blessed Screen with proper lifecycle management.\n *\n * @param options - Screen configuration options\n * @returns Screen context with lifecycle methods\n */\nexport function createScreen(options?: {\n stdin?: NodeJS.ReadStream;\n stdout?: NodeJS.WriteStream;\n title?: string;\n}): TUIScreenContext {\n // Ensure runtime is initialized before creating any blessed widgets\n ensureRuntimeInitialized();\n\n const screen = new Screen({\n smartCSR: true, // Smart cursor rendering for better performance\n fullUnicode: true, // Support emoji and extended characters\n title: options?.title ?? \"llmist\",\n input: options?.stdin,\n output: options?.stdout,\n // Capture all keyboard input\n grabKeys: true,\n // Use alternate screen buffer (restores on exit)\n useBCE: true,\n });\n\n let isDestroyed = false;\n let renderPending = false;\n let renderTimeout: ReturnType<typeof setTimeout> | null = null;\n\n // Debounced render function to avoid excessive redraws\n // Uses trailing-edge debounce: captures latest state before rendering\n const requestRender = () => {\n if (isDestroyed) return;\n\n // If a render is already pending, it will pick up the latest state\n // when it fires, so we don't need to schedule another one\n if (renderPending) return;\n\n renderPending = true;\n renderTimeout = setTimeout(() => {\n renderPending = false;\n if (!isDestroyed) {\n screen.render();\n }\n }, RENDER_DEBOUNCE_MS);\n };\n\n // Immediate render for time-sensitive updates (like streaming tokens)\n const renderNow = () => {\n if (isDestroyed) return;\n\n // Cancel any pending debounced render\n if (renderTimeout) {\n clearTimeout(renderTimeout);\n renderTimeout = null;\n renderPending = false;\n }\n\n screen.render();\n };\n\n // Cleanup function\n const destroy = () => {\n if (isDestroyed) return;\n isDestroyed = true;\n\n // Clear any pending render\n if (renderTimeout) {\n clearTimeout(renderTimeout);\n renderTimeout = null;\n }\n\n // Destroy screen (restores terminal)\n screen.destroy();\n\n // Ensure cursor is visible\n process.stdout.write(\"\\x1b[?25h\");\n };\n\n // Handle process signals for graceful cleanup\n const sigintHandler = () => {\n destroy();\n process.exit(130); // SIGINT convention\n };\n\n const sigtermHandler = () => {\n destroy();\n process.exit(143); // SIGTERM convention\n };\n\n process.once(\"SIGINT\", sigintHandler);\n process.once(\"SIGTERM\", sigtermHandler);\n\n // Also handle uncaught exceptions to restore terminal\n process.once(\"uncaughtException\", (err) => {\n destroy();\n console.error(\"Uncaught exception:\", err);\n process.exit(1);\n });\n\n return {\n screen,\n requestRender,\n renderNow,\n destroy,\n };\n}\n","/**\n * TUI layout widget creation.\n *\n * Creates and configures the three main TUI widgets:\n * - Body: ScrollableBox for interactive block widgets\n * - InputBar: Always-visible input field at the bottom\n * - StatusBar: Metrics display (tokens, time, cost)\n */\n\nimport { Box, ScrollableBox, Textbox, type Screen } from \"@unblessed/node\";\nimport type { TUIBlockLayout, FocusMode } from \"./types.js\";\n\n/**\n * Creates the TUI layout with ScrollableBox for interactive blocks.\n *\n * Layout structure (from bottom):\n * - Status bar: 1 line at very bottom\n * - Input bar: 1 line above status\n * - Body: Remaining space (ScrollableBox with Box children)\n *\n * @param screen - The blessed Screen instance\n * @returns Layout object containing all widgets\n */\nexport function createBlockLayout(screen: Screen): TUIBlockLayout {\n // Main scrollable container for block widgets\n // Uses ScrollableBox to support Box children (not just text)\n const body = new ScrollableBox({\n parent: screen,\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%-2\",\n // Scrolling configuration\n scrollable: true,\n alwaysScroll: true,\n mouse: true,\n keys: false, // We handle keys ourselves for block selection\n scrollbar: {\n ch: \" \",\n style: {\n bg: \"blue\",\n },\n },\n // Don't use blessed tags - we pass ANSI directly from chalk\n tags: false,\n // Style\n style: {\n fg: \"white\",\n bg: \"black\",\n },\n });\n\n // Input bar - always visible at bottom - 1\n // Shows \"> \" prompt indicator even when idle\n const inputBar = new Textbox({\n parent: screen,\n bottom: 1,\n left: 0,\n width: \"100%\",\n height: 1,\n inputOnFocus: true,\n keys: true,\n mouse: true,\n style: {\n fg: \"white\",\n bg: \"black\",\n },\n });\n\n // Pre-fill with prompt indicator\n inputBar.setValue(\"> \");\n\n // Status bar at very bottom\n // Uses ANSI codes for color formatting (tags: false)\n const statusBar = new Box({\n parent: screen,\n bottom: 0,\n left: 0,\n width: \"100%\",\n height: 1,\n tags: false,\n style: {\n fg: \"white\",\n bg: \"black\",\n },\n });\n\n return { body, inputBar, statusBar };\n}\n\n/**\n * Sets up keyboard navigation for block selection in the TUI.\n *\n * Provides navigation between selectable blocks (LLM calls, gadgets)\n * and expand/collapse functionality for viewing details.\n *\n * Navigation only works in \"browse\" focus mode. In \"input\" mode,\n * keys are captured by the input field.\n *\n * @param screen - The blessed Screen instance\n * @param callbacks - Object with navigation callback functions\n * @param getFocusMode - Function to get current focus mode\n */\nexport function setupBlockNavigationKeys(\n screen: Screen,\n callbacks: {\n onSelectNext: () => void;\n onSelectPrevious: () => void;\n onToggleExpand: () => void;\n onCollapse: () => void;\n onSelectFirst: () => void;\n onSelectLast: () => void;\n onShowRawRequest?: () => void;\n onShowRawResponse?: () => void;\n },\n getFocusMode: () => FocusMode,\n): void {\n // Navigation: up/down or vim keys (browse mode only)\n screen.key([\"up\", \"k\"], () => {\n if (getFocusMode() !== \"browse\") return;\n callbacks.onSelectPrevious();\n screen.render();\n });\n\n screen.key([\"down\", \"j\"], () => {\n if (getFocusMode() !== \"browse\") return;\n callbacks.onSelectNext();\n screen.render();\n });\n\n // Expand/collapse with Enter or Space (browse mode only)\n screen.key([\"enter\", \"space\"], () => {\n if (getFocusMode() !== \"browse\") return;\n callbacks.onToggleExpand();\n screen.render();\n });\n\n // Collapse with Escape or h (vim-style left) (browse mode only)\n screen.key([\"escape\", \"h\"], () => {\n if (getFocusMode() !== \"browse\") return;\n callbacks.onCollapse();\n screen.render();\n });\n\n // Jump to first/last (browse mode only)\n screen.key([\"home\", \"g\"], () => {\n if (getFocusMode() !== \"browse\") return;\n callbacks.onSelectFirst();\n screen.render();\n });\n\n screen.key([\"end\", \"G\"], () => {\n if (getFocusMode() !== \"browse\") return;\n callbacks.onSelectLast();\n screen.render();\n });\n\n // Raw viewer: r = request, R = response (browse mode only)\n screen.key([\"r\"], () => {\n if (getFocusMode() !== \"browse\") return;\n callbacks.onShowRawRequest?.();\n });\n\n screen.key([\"S-r\"], () => {\n if (getFocusMode() !== \"browse\") return;\n callbacks.onShowRawResponse?.();\n });\n}\n","/**\n * TUI status bar for displaying real-time metrics.\n *\n * Shows accumulated token counts, elapsed time, and cost.\n * Also displays currently active LLM calls and gadgets with a spinner.\n * Updates on LLM call lifecycle events.\n */\n\nimport type { Box } from \"@unblessed/node\";\nimport type { TUIMetrics, FocusMode } from \"./types.js\";\nimport { formatTokens, formatCost } from \"../ui/formatters.js\";\nimport type { ExecutionTree, ExecutionEvent, NodeId } from \"../../core/execution-tree.js\";\n\n/** Rough estimate: ~4 characters per token for English text */\nconst CHARS_PER_TOKEN = 4;\n\n/** Braille spinner frames for smooth animation */\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n\n/** Spinner animation interval in ms (~12fps) */\nconst SPINNER_INTERVAL_MS = 80;\n\n/**\n * Manages the status bar display and metrics tracking.\n */\nexport class StatusBar {\n private metrics: TUIMetrics;\n private statusBox: Box;\n private renderCallback: () => void;\n private renderNowCallback: () => void;\n\n /** Current call's streaming input tokens (estimate) */\n private streamingInputTokens = 0;\n /** Current call's streaming output tokens (estimate) */\n private streamingOutputTokens = 0;\n /** Whether we're currently streaming */\n private isStreaming = false;\n\n /** Active LLM calls: Map from label (\"#1\") to model name */\n private activeLLMCalls = new Map<string, string>();\n\n /** Active gadgets (by name) */\n private activeGadgets = new Set<string>();\n\n /** Spinner frame index */\n private spinnerFrame = 0;\n\n /** Spinner animation interval */\n private spinnerInterval: ReturnType<typeof setInterval> | null = null;\n\n /** Current focus mode */\n private focusMode: FocusMode = \"browse\";\n\n /** Track tree node IDs to display labels for LLM calls */\n private nodeIdToLabel = new Map<NodeId, string>();\n\n /** Track tree node IDs for gadgets */\n private nodeIdToGadgetName = new Map<NodeId, string>();\n\n /** Tree subscription unsubscribe function */\n private treeUnsubscribe: (() => void) | null = null;\n\n constructor(\n statusBox: Box,\n model: string,\n renderCallback: () => void,\n renderNowCallback?: () => void,\n ) {\n this.statusBox = statusBox;\n this.renderCallback = renderCallback;\n this.renderNowCallback = renderNowCallback ?? renderCallback;\n this.metrics = {\n inputTokens: 0,\n outputTokens: 0,\n cachedTokens: 0,\n cost: 0,\n startTime: Date.now(),\n iteration: 0,\n model,\n };\n\n // Initial render\n this.render();\n }\n\n /**\n * Called when a new LLM call starts.\n * @param model - Model name\n * @param estimatedInputTokens - Estimated input tokens for this call\n */\n startCall(model: string, estimatedInputTokens: number): void {\n this.metrics.model = model;\n this.metrics.iteration++;\n // Track streaming estimates separately\n this.streamingInputTokens = estimatedInputTokens;\n this.streamingOutputTokens = 0;\n this.isStreaming = true;\n this.render();\n }\n\n /**\n * Called during streaming to update output token estimate.\n * Uses immediate rendering for real-time feedback.\n * @param estimatedOutputTokens - Estimated output tokens so far\n */\n updateStreaming(estimatedOutputTokens: number): void {\n this.streamingOutputTokens = estimatedOutputTokens;\n this.render(true); // immediate render for streaming updates\n }\n\n /**\n * Called when an LLM call completes.\n * Replaces streaming estimates with actual values.\n */\n endCall(\n inputTokens: number,\n outputTokens: number,\n cachedTokens: number,\n cost: number,\n ): void {\n // Add actual values to accumulated totals\n this.metrics.inputTokens += inputTokens;\n this.metrics.outputTokens += outputTokens;\n this.metrics.cachedTokens += cachedTokens;\n this.metrics.cost += cost;\n // Clear streaming state\n this.streamingInputTokens = 0;\n this.streamingOutputTokens = 0;\n this.isStreaming = false;\n this.render();\n }\n\n /**\n * Add cost from gadget execution (e.g., subagent costs).\n */\n addGadgetCost(cost: number): void {\n if (cost > 0) {\n this.metrics.cost += cost;\n this.render();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Activity Tracking (for real-time display of what's running)\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Track an LLM call as active.\n * @param label - Display label like \"#1\" or \"#1.1\"\n * @param model - Full model name like \"gemini:gemini-2.5-flash\"\n */\n startLLMCall(label: string, model: string): void {\n this.activeLLMCalls.set(label, model);\n this.startSpinner();\n this.render();\n }\n\n /**\n * Mark an LLM call as complete.\n * @param label - Display label like \"#1\" or \"#1.1\"\n */\n endLLMCall(label: string): void {\n this.activeLLMCalls.delete(label);\n this.maybeStopSpinner();\n this.render();\n }\n\n /**\n * Track a gadget as active.\n * @param name - Gadget name like \"ReadFile\" or \"BrowseWeb\"\n */\n startGadget(name: string): void {\n this.activeGadgets.add(name);\n this.startSpinner();\n this.render();\n }\n\n /**\n * Mark a gadget as complete.\n * @param name - Gadget name\n */\n endGadget(name: string): void {\n this.activeGadgets.delete(name);\n this.maybeStopSpinner();\n this.render();\n }\n\n /**\n * Start the spinner animation if not already running.\n */\n private startSpinner(): void {\n if (this.spinnerInterval) return;\n this.spinnerInterval = setInterval(() => {\n this.spinnerFrame = (this.spinnerFrame + 1) % SPINNER_FRAMES.length;\n this.render(true); // immediate render for smooth animation\n }, SPINNER_INTERVAL_MS);\n }\n\n /**\n * Stop the spinner if no activity is in progress.\n */\n private maybeStopSpinner(): void {\n if (this.activeLLMCalls.size === 0 && this.activeGadgets.size === 0) {\n this.stopSpinner();\n }\n }\n\n /**\n * Force stop the spinner animation.\n */\n private stopSpinner(): void {\n if (this.spinnerInterval) {\n clearInterval(this.spinnerInterval);\n this.spinnerInterval = null;\n }\n }\n\n /**\n * Clear all activity tracking and stop spinner.\n * Call this when the agent loop completes or between REPL iterations.\n */\n clearActivity(): void {\n this.activeLLMCalls.clear();\n this.activeGadgets.clear();\n this.nodeIdToLabel.clear();\n this.nodeIdToGadgetName.clear();\n this.stopSpinner();\n this.render();\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Tree Subscription (for tree-only block creation)\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Subscribe to ExecutionTree events for automatic activity tracking.\n * This enables tree-only block creation where the tree is the single\n * source of truth for LLM calls and gadgets.\n *\n * @param tree - The ExecutionTree to subscribe to\n * @returns Unsubscribe function\n */\n subscribeToTree(tree: ExecutionTree): () => void {\n // Unsubscribe from any previous tree\n if (this.treeUnsubscribe) {\n this.treeUnsubscribe();\n }\n\n // Clear previous mappings\n this.nodeIdToLabel.clear();\n this.nodeIdToGadgetName.clear();\n\n this.treeUnsubscribe = tree.onAll((event: ExecutionEvent) => {\n this.handleTreeEvent(event);\n });\n\n return () => {\n if (this.treeUnsubscribe) {\n this.treeUnsubscribe();\n this.treeUnsubscribe = null;\n }\n };\n }\n\n /**\n * Handle an ExecutionTree event for activity tracking.\n */\n private handleTreeEvent(event: ExecutionEvent): void {\n switch (event.type) {\n case \"llm_call_start\": {\n // Create label like \"#1\" for root calls, \"#1.1\" for nested\n const label = event.depth === 0\n ? `#${event.iteration + 1}`\n : `#${event.iteration + 1}.${event.depth}`;\n this.nodeIdToLabel.set(event.nodeId, label);\n this.startLLMCall(label, event.model);\n break;\n }\n\n case \"llm_call_complete\": {\n const label = this.nodeIdToLabel.get(event.nodeId);\n if (label) {\n this.endLLMCall(label);\n // Accumulate token/cost metrics from tree event (includes nested calls)\n if (event.usage || event.cost) {\n this.endCall(\n event.usage?.inputTokens ?? 0,\n event.usage?.outputTokens ?? 0,\n event.usage?.cachedInputTokens ?? 0,\n event.cost ?? 0,\n );\n }\n this.nodeIdToLabel.delete(event.nodeId);\n }\n break;\n }\n\n case \"llm_call_error\": {\n const label = this.nodeIdToLabel.get(event.nodeId);\n if (label) {\n this.endLLMCall(label);\n this.nodeIdToLabel.delete(event.nodeId);\n }\n break;\n }\n\n case \"gadget_call\": {\n this.nodeIdToGadgetName.set(event.nodeId, event.name);\n this.startGadget(event.name);\n break;\n }\n\n case \"gadget_complete\": {\n const name = this.nodeIdToGadgetName.get(event.nodeId);\n if (name) {\n this.endGadget(name);\n if (event.cost) {\n this.addGadgetCost(event.cost);\n }\n this.nodeIdToGadgetName.delete(event.nodeId);\n }\n break;\n }\n\n case \"gadget_error\":\n case \"gadget_skipped\": {\n const name = this.nodeIdToGadgetName.get(event.nodeId);\n if (name) {\n this.endGadget(name);\n this.nodeIdToGadgetName.delete(event.nodeId);\n }\n break;\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Focus Mode\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Set the current focus mode (called by TUIApp).\n * Updates the status bar to show the mode indicator.\n * Uses immediate render to ensure the mode is visible before input focus changes.\n */\n setFocusMode(mode: FocusMode): void {\n this.focusMode = mode;\n this.render(true); // immediate render for mode changes\n }\n\n /**\n * Get the current focus mode.\n */\n getFocusMode(): FocusMode {\n return this.focusMode;\n }\n\n /**\n * Shorten model name for display.\n * \"gemini:gemini-2.5-flash\" → \"2.5-flash\"\n */\n private shortenModelName(model: string): string {\n // Remove provider prefix\n const withoutProvider = model.includes(\":\") ? model.split(\":\")[1] : model;\n // Shorten common patterns\n return withoutProvider\n .replace(\"claude-\", \"\")\n .replace(\"gemini-\", \"\")\n .replace(\"gpt-\", \"\")\n .replace(\"-latest\", \"\");\n }\n\n /**\n * Get current metrics for external use.\n */\n getMetrics(): Readonly<TUIMetrics> {\n return { ...this.metrics };\n }\n\n /**\n * Get elapsed time in seconds.\n */\n getElapsedSeconds(): number {\n return (Date.now() - this.metrics.startTime) / 1000;\n }\n\n /**\n * Render the status bar content.\n * @param immediate - If true, render immediately without debouncing\n */\n private render(immediate = false): void {\n const elapsed = this.getElapsedSeconds().toFixed(1);\n\n // ANSI color codes\n const YELLOW = \"\\x1b[33m\";\n const GREEN = \"\\x1b[32m\";\n const BLUE = \"\\x1b[34m\";\n const CYAN = \"\\x1b[36m\";\n const MAGENTA = \"\\x1b[35m\";\n const GRAY = \"\\x1b[90m\";\n const RESET = \"\\x1b[0m\";\n const BG_BLUE = \"\\x1b[44m\";\n const BG_GREEN = \"\\x1b[42m\";\n const WHITE = \"\\x1b[37m\";\n const BLACK = \"\\x1b[30m\";\n\n // Calculate display values: accumulated + current streaming\n const displayInputTokens = this.metrics.inputTokens + this.streamingInputTokens;\n const displayOutputTokens = this.metrics.outputTokens + this.streamingOutputTokens;\n\n // Build status line using ANSI codes\n // Order: mode indicator, stable metrics (tokens, time, cost), then dynamic activity (LLM calls, gadgets)\n const parts: string[] = [];\n\n // Focus mode indicator at the start\n if (this.focusMode === \"browse\") {\n parts.push(`${BG_BLUE}${WHITE} BROWSE ${RESET}`);\n } else {\n parts.push(`${BG_GREEN}${BLACK} INPUT ${RESET}`);\n }\n\n // Input tokens (yellow) - show ~ prefix during streaming to indicate estimate\n const inputPrefix = this.isStreaming && this.streamingInputTokens > 0 ? \"~\" : \"\";\n parts.push(`${YELLOW}↑ ${inputPrefix}${formatTokens(displayInputTokens)}${RESET}`);\n\n // Cached tokens (blue) - only show if present\n if (this.metrics.cachedTokens > 0) {\n parts.push(`${BLUE}⤿ ${formatTokens(this.metrics.cachedTokens)}${RESET}`);\n }\n\n // Output tokens (green) - show ~ prefix during streaming to indicate estimate\n const outputPrefix = this.isStreaming ? \"~\" : \"\";\n parts.push(`${GREEN}↓ ${outputPrefix}${formatTokens(displayOutputTokens)}${RESET}`);\n\n // Elapsed time (gray)\n parts.push(`${GRAY}${elapsed}s${RESET}`);\n\n // Cost (cyan)\n parts.push(`${CYAN}$${formatCost(this.metrics.cost)}${RESET}`);\n\n // Activity section at the end (if anything is running)\n if (this.activeLLMCalls.size > 0 || this.activeGadgets.size > 0) {\n const spinner = SPINNER_FRAMES[this.spinnerFrame];\n\n // Show active LLM calls with model names, grouped by model\n if (this.activeLLMCalls.size > 0) {\n const byModel = new Map<string, string[]>();\n for (const [label, model] of this.activeLLMCalls) {\n const shortModel = this.shortenModelName(model);\n if (!byModel.has(shortModel)) byModel.set(shortModel, []);\n byModel.get(shortModel)?.push(label);\n }\n\n const llmParts: string[] = [];\n for (const [model, labels] of byModel) {\n llmParts.push(`${model} ${labels.join(\", \")}`);\n }\n parts.push(`${spinner} ${MAGENTA}${llmParts.join(\" | \")}${RESET}`);\n }\n\n // Show active gadgets (limit to 3, show +N for more)\n if (this.activeGadgets.size > 0) {\n const gadgetList = [...this.activeGadgets].slice(0, 3).join(\", \");\n const more = this.activeGadgets.size > 3 ? ` +${this.activeGadgets.size - 3}` : \"\";\n parts.push(`${CYAN}⏵ ${gadgetList}${more}${RESET}`);\n }\n }\n\n this.statusBox.setContent(parts.join(` ${GRAY}|${RESET} `));\n\n // Use immediate render for streaming updates, debounced for others\n if (immediate) {\n this.renderNowCallback();\n } else {\n this.renderCallback();\n }\n }\n\n /**\n * Estimate tokens from text length.\n * @param text - Text to estimate tokens for\n * @returns Estimated token count\n */\n static estimateTokens(text: string): number {\n return Math.ceil(text.length / CHARS_PER_TOKEN);\n }\n}\n","/**\n * TUI input handler for AskUser prompts.\n *\n * Manages the input field lifecycle for user responses.\n * The input field is always visible but only active during prompts.\n */\n\nimport type { Screen, Textbox, Box } from \"@unblessed/node\";\nimport type { PendingInput, CtrlCCallback } from \"./types.js\";\n\n/** Prompt indicator shown when input is idle */\nconst IDLE_PROMPT = \"> \";\n\n/** Prompt indicator shown when waiting for input */\nconst ACTIVE_PROMPT = \">>> \";\n\n/** Prompt indicator for pending REPL input (not capturing keys yet) */\nconst PENDING_PROMPT = \"> \";\n\n/**\n * Manages input field for AskUser responses.\n */\nexport class InputHandler {\n private inputBar: Textbox;\n private body: Box;\n private screen: Screen;\n private renderCallback: () => void;\n private renderNowCallback: () => void;\n\n /** Currently pending input request */\n private pendingInput: PendingInput | null = null;\n\n /** Whether we're waiting for REPL prompt (vs AskUser which should auto-focus) */\n private isPendingREPLPrompt = false;\n\n /** Callback when Ctrl+C is pressed */\n private ctrlCCallback: CtrlCCallback | null = null;\n\n /** Callback when Ctrl+B is pressed (toggle focus mode) */\n private ctrlBCallback: (() => void) | null = null;\n\n constructor(\n inputBar: Textbox,\n body: Box,\n screen: Screen,\n renderCallback: () => void,\n renderNowCallback?: () => void,\n ) {\n this.inputBar = inputBar;\n this.body = body;\n this.screen = screen;\n this.renderCallback = renderCallback;\n this.renderNowCallback = renderNowCallback ?? renderCallback;\n\n // Set up input submission handler\n this.inputBar.on(\"submit\", (value: string) => {\n this.handleSubmit(value);\n });\n\n // Handle cancel (ESC while focused)\n this.inputBar.on(\"cancel\", () => {\n this.handleCancel();\n });\n\n // Handle Ctrl+C on the input bar - propagate to callback\n // This ensures Ctrl+C works even when textbox has focus\n this.inputBar.key([\"C-c\"], () => {\n if (this.ctrlCCallback) {\n this.ctrlCCallback();\n }\n });\n\n // Handle Ctrl+B on the input bar - toggle focus mode\n // This ensures Ctrl+B works to exit input mode back to browse mode\n this.inputBar.key([\"C-b\"], () => {\n if (this.ctrlBCallback) {\n this.ctrlBCallback();\n }\n });\n\n // Screen-level Enter key to activate pending REPL prompt\n // This allows navigation to work when not actively typing\n this.screen.key([\"enter\"], () => {\n if (this.isPendingREPLPrompt) {\n this.activatePendingPrompt();\n }\n });\n\n // Show idle prompt\n this.setIdle();\n }\n\n /**\n * Set callback for Ctrl+C events.\n */\n onCtrlC(callback: CtrlCCallback): void {\n this.ctrlCCallback = callback;\n }\n\n /**\n * Set callback for Ctrl+B events (toggle focus mode).\n */\n onCtrlB(callback: () => void): void {\n this.ctrlBCallback = callback;\n }\n\n /**\n * Request user input with a question.\n *\n * @param question - The question to display\n * @param gadgetName - Name of the gadget requesting input\n * @returns Promise that resolves with user's response\n */\n async waitForInput(question: string, gadgetName: string): Promise<string> {\n return new Promise((resolve, reject) => {\n this.pendingInput = {\n question,\n gadgetName,\n resolve,\n reject,\n };\n\n // Show the question in the body area\n this.appendQuestionToBody(question);\n\n // Activate input mode\n this.setActive();\n });\n }\n\n /**\n * Wait for user to enter a new prompt (REPL mode).\n *\n * Unlike waitForInput, this doesn't auto-focus so navigation keys still work.\n * Press Enter to start typing a new prompt.\n *\n * @returns Promise that resolves with user's prompt\n */\n async waitForPrompt(): Promise<string> {\n return new Promise((resolve, reject) => {\n this.pendingInput = {\n question: \"\",\n gadgetName: \"prompt\",\n resolve,\n reject,\n };\n\n // Set to pending state - show prompt but don't capture all keys\n // This allows block navigation to work while waiting for user to start typing\n this.setPendingPrompt();\n });\n }\n\n /**\n * Activate a pending REPL prompt (called when user presses Enter).\n */\n activatePendingPrompt(): void {\n if (this.isPendingREPLPrompt && this.pendingInput) {\n this.isPendingREPLPrompt = false;\n this.setActive();\n }\n }\n\n /**\n * Check if there's a pending input request.\n */\n hasPendingInput(): boolean {\n return this.pendingInput !== null;\n }\n\n /**\n * Cancel any pending input request.\n */\n cancelPending(): void {\n if (this.pendingInput) {\n this.pendingInput.reject(new Error(\"Input cancelled\"));\n this.pendingInput = null;\n this.setIdle();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Focus Mode API (controlled by TUIApp)\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Activate input mode - show input bar and capture keyboard.\n * Called by TUIApp when switching to input mode.\n */\n activate(): void {\n this.isPendingREPLPrompt = false;\n this.inputBar.show();\n this.inputBar.setValue(ACTIVE_PROMPT);\n // Render immediately to ensure input bar is visible before focus\n this.renderNowCallback();\n // Then focus and start reading input\n this.inputBar.focus();\n this.inputBar.readInput();\n }\n\n /**\n * Deactivate input mode - hide input bar completely.\n * Called by TUIApp when switching to browse mode.\n */\n deactivate(): void {\n this.inputBar.hide();\n this.isPendingREPLPrompt = false;\n this.renderNowCallback();\n }\n\n /**\n * Check if input mode is active (input bar visible and focused).\n */\n isInputActive(): boolean {\n return this.inputBar.visible !== false;\n }\n\n /**\n * Handle input submission.\n */\n private handleSubmit(rawValue: string): void {\n // Extract actual input (remove prompt prefix)\n const value = rawValue.startsWith(ACTIVE_PROMPT)\n ? rawValue.slice(ACTIVE_PROMPT.length).trim()\n : rawValue.startsWith(IDLE_PROMPT)\n ? rawValue.slice(IDLE_PROMPT.length).trim()\n : rawValue.trim();\n\n if (!value) {\n // Empty input - refocus for retry\n this.inputBar.focus();\n this.inputBar.readInput();\n return;\n }\n\n if (this.pendingInput) {\n // Resolve the pending promise\n const { resolve } = this.pendingInput;\n this.pendingInput = null;\n\n // Reset to idle state\n this.setIdle();\n\n // Resolve with the user's input\n resolve(value);\n } else {\n // No pending input - just reset\n this.setIdle();\n }\n }\n\n /**\n * Handle input cancellation (ESC key).\n */\n private handleCancel(): void {\n if (this.pendingInput) {\n // Don't actually cancel - just reset focus\n // The pending input will continue to wait\n this.inputBar.focus();\n this.inputBar.readInput();\n } else {\n this.setIdle();\n }\n }\n\n /**\n * Set input to idle state.\n */\n private setIdle(): void {\n this.isPendingREPLPrompt = false;\n this.inputBar.setValue(IDLE_PROMPT);\n // Don't focus - let body handle scroll keys\n this.renderCallback();\n }\n\n /**\n * Set input to pending REPL prompt state.\n * Shows the prompt indicator but doesn't capture all keys.\n */\n private setPendingPrompt(): void {\n this.isPendingREPLPrompt = true;\n this.inputBar.setValue(PENDING_PROMPT);\n // Don't focus - let navigation keys work\n // User presses Enter to activate and start typing\n this.renderCallback();\n }\n\n /**\n * Set input to active state for user input.\n */\n private setActive(): void {\n this.isPendingREPLPrompt = false;\n this.inputBar.setValue(ACTIVE_PROMPT);\n this.inputBar.focus();\n this.inputBar.readInput();\n this.renderCallback();\n }\n\n /**\n * Append the question to the body content.\n */\n private appendQuestionToBody(question: string): void {\n const currentContent = this.body.getContent();\n const separator = \"\\n\" + \"─\".repeat(40) + \"\\n\";\n const formatted = `${separator}? ${question}${separator}`;\n\n this.body.setContent(currentContent + formatted);\n this.body.setScrollPerc?.(100);\n this.renderCallback();\n }\n}\n","/**\n * BlockRenderer - Interactive block-based TUI renderer.\n *\n * Manages a tree of selectable/expandable blocks for LLM calls and gadgets.\n * Handles navigation, selection, and expand/collapse interactions.\n *\n * Can optionally subscribe to an ExecutionTree for automatic updates,\n * eliminating the need for manual event handling.\n *\n * @module\n */\n\nimport { Box, type ScrollableBox } from \"@unblessed/node\";\nimport type {\n ExecutionTree,\n ExecutionEvent,\n} from \"../../core/execution-tree.js\";\nimport type {\n BlockNode,\n LLMCallNode,\n GadgetNode,\n TextNode,\n SelectableBlock,\n} from \"./types.js\";\nimport {\n formatLLMCallCollapsed,\n formatLLMCallExpanded,\n formatGadgetCollapsed,\n formatGadgetExpanded,\n getIndent,\n getContinuationIndent,\n} from \"../ui/block-formatters.js\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// BlockRenderer Class\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Manages interactive blocks in the TUI.\n *\n * Features:\n * - Tree structure of LLM calls and gadgets\n * - Keyboard navigation (up/down)\n * - Expand/collapse for details\n * - Dynamic updates (gadget results, subagent events)\n */\nexport class BlockRenderer {\n private container: ScrollableBox;\n private renderCallback: () => void;\n\n /** All nodes in the tree (flat for easy lookup) */\n private nodes = new Map<string, BlockNode>();\n\n /** Root node IDs (top-level LLM calls and text) */\n private rootIds: string[] = [];\n\n /** Rendered blocks with UI state */\n private blocks = new Map<string, SelectableBlock>();\n\n /** IDs of selectable blocks in display order */\n private selectableIds: string[] = [];\n\n /** Currently selected block index (-1 = none) */\n private selectedIndex = -1;\n\n /** Counter for generating unique node IDs */\n private nodeIdCounter = 0;\n\n /** Current LLM call node (for adding gadget children) */\n private currentLLMCallId: string | null = null;\n\n /** Persisted expanded states (survives rebuildBlocks) */\n private expandedStates = new Map<string, boolean>();\n\n /** Whether to auto-scroll to bottom on new content (\"follow mode\") */\n private followMode: boolean = true;\n\n /** Threshold in pixels for detecting \"at bottom\" position */\n private static readonly AT_BOTTOM_THRESHOLD = 5;\n\n /** Track main agent LLM calls by iteration to prevent duplicates */\n private llmCallByIteration = new Map<number, string>();\n\n /** Track gadgets by invocationId to prevent duplicates */\n private gadgetByInvocationId = new Map<string, string>();\n\n /** Track nested LLM calls by parentId_iteration to prevent duplicates */\n private nestedLLMCallByKey = new Map<string, string>();\n\n constructor(container: ScrollableBox, renderCallback: () => void) {\n this.container = container;\n this.renderCallback = renderCallback;\n }\n\n // ───────────────────────────────────────────────────────────────────────────\n // Public API - Node Management\n // ───────────────────────────────────────────────────────────────────────────\n\n /**\n * Add an LLM call node (top-level or nested in gadget).\n * For main agent calls (no parent), deduplicates by iteration number.\n *\n * @param iteration - 1-indexed iteration number\n * @param model - Model name (e.g., \"anthropic:claude-sonnet-4-5\")\n * @param parentGadgetId - Parent gadget block ID for nested LLM calls\n * @param isNested - Override flag to treat as nested even without parentGadgetId\n * (used when tree event depth > 0 but parent lookup failed)\n */\n addLLMCall(\n iteration: number,\n model: string,\n parentGadgetId?: string,\n isNested?: boolean,\n ): string {\n // Deduplicate main agent LLM calls by iteration (only if NOT a nested call)\n // isNested flag prevents deduplication even when parentGadgetId lookup failed\n if (!parentGadgetId && !isNested) {\n const existingId = this.llmCallByIteration.get(iteration);\n if (existingId) {\n // Return existing block instead of creating duplicate\n this.currentLLMCallId = existingId;\n return existingId;\n }\n } else if (parentGadgetId) {\n // Deduplicate nested subagent LLM calls by parent + iteration\n const nestedKey = `${parentGadgetId}_${iteration}`;\n const existingId = this.nestedLLMCallByKey.get(nestedKey);\n if (existingId) {\n // Return existing block instead of creating duplicate\n this.currentLLMCallId = existingId;\n return existingId;\n }\n }\n\n const id = this.generateId(\"llm\");\n const parentNode = parentGadgetId ? this.getNode(parentGadgetId) : undefined;\n const depth = parentNode ? parentNode.depth + 1 : 0;\n\n const node: LLMCallNode = {\n id,\n type: \"llm_call\",\n depth,\n parentId: parentGadgetId ?? null,\n iteration,\n model,\n isComplete: false,\n children: [],\n };\n\n this.nodes.set(id, node);\n\n if (parentGadgetId) {\n // Nested LLM call - add to parent gadget's children\n const parent = this.getNode(parentGadgetId) as GadgetNode;\n parent.children.push(id);\n // Track for deduplication\n const nestedKey = `${parentGadgetId}_${iteration}`;\n this.nestedLLMCallByKey.set(nestedKey, id);\n } else {\n // Top-level LLM call - track by iteration for deduplication\n this.rootIds.push(id);\n this.llmCallByIteration.set(iteration, id);\n }\n\n this.currentLLMCallId = id;\n this.rebuildBlocks();\n return id;\n }\n\n /**\n * Complete an LLM call with details and optional raw response.\n */\n completeLLMCall(\n id: string,\n details: LLMCallNode[\"details\"],\n rawResponse?: string,\n ): void {\n const node = this.getNode(id) as LLMCallNode | undefined;\n if (!node || node.type !== \"llm_call\") return;\n\n node.isComplete = true;\n node.details = details;\n if (rawResponse !== undefined) {\n node.rawResponse = rawResponse;\n }\n this.updateBlock(id);\n }\n\n /**\n * Store raw request messages for an LLM call.\n * Called when the LLM call is ready (after controller modifications).\n */\n setLLMCallRequest(\n id: string,\n messages: import(\"../../core/messages.js\").LLMMessage[],\n ): void {\n const node = this.getNode(id) as LLMCallNode | undefined;\n if (!node || node.type !== \"llm_call\") return;\n node.rawRequest = messages;\n }\n\n /**\n * Add a gadget node as a child of the current LLM call.\n *\n * Gadgets are nested under the LLM call that spawned them.\n * They appear indented and are visible when the parent is rendered.\n */\n addGadget(\n invocationId: string,\n name: string,\n parameters?: Record<string, unknown>,\n ): string {\n // Deduplicate gadgets by invocationId\n const existingId = this.gadgetByInvocationId.get(invocationId);\n if (existingId) {\n // Return existing block instead of creating duplicate\n return existingId;\n }\n\n const id = this.generateId(\"gadget\");\n const parentLLMCallId = this.currentLLMCallId;\n\n // Calculate depth based on parent\n let depth = 0;\n if (parentLLMCallId) {\n const parent = this.getNode(parentLLMCallId);\n if (parent) {\n depth = parent.depth + 1;\n }\n }\n\n const node: GadgetNode = {\n id,\n type: \"gadget\",\n depth,\n parentId: parentLLMCallId,\n invocationId,\n name,\n isComplete: false,\n parameters,\n children: [], // Used for subagent nested LLM calls\n };\n\n this.nodes.set(id, node);\n\n if (parentLLMCallId) {\n // Nest under parent LLM call\n const parent = this.getNode(parentLLMCallId) as LLMCallNode;\n parent.children.push(id);\n } else {\n // No parent LLM call - add to root\n this.rootIds.push(id);\n }\n\n // Track for deduplication\n this.gadgetByInvocationId.set(invocationId, id);\n\n this.rebuildBlocks();\n return id;\n }\n\n /**\n * Complete a gadget with result.\n */\n completeGadget(\n invocationId: string,\n result?: string,\n error?: string,\n executionTimeMs?: number,\n cost?: number,\n ): void {\n // Find gadget by invocationId\n const node = this.findGadgetByInvocationId(invocationId);\n if (!node) return;\n\n node.isComplete = true;\n node.result = result;\n node.error = error;\n node.executionTimeMs = executionTimeMs;\n node.cost = cost;\n\n // Estimate result tokens (rough: ~4 chars per token)\n if (result) {\n node.resultTokens = Math.ceil(result.length / 4);\n }\n\n // Aggregate subagent stats from child LLM call nodes\n if (node.children.length > 0) {\n node.subagentStats = this.aggregateSubagentStats(node.children);\n }\n\n this.updateBlock(node.id);\n }\n\n /**\n * Aggregate token/cost stats from child LLM call nodes.\n */\n private aggregateSubagentStats(\n childIds: string[],\n ): GadgetNode[\"subagentStats\"] {\n let inputTokens = 0;\n let outputTokens = 0;\n let cachedTokens = 0;\n let cost = 0;\n let llmCallCount = 0;\n\n for (const childId of childIds) {\n const child = this.nodes.get(childId);\n if (child?.type === \"llm_call\" && child.details) {\n inputTokens += child.details.inputTokens ?? 0;\n outputTokens += child.details.outputTokens ?? 0;\n cachedTokens += child.details.cachedInputTokens ?? 0;\n cost += child.details.cost ?? 0;\n llmCallCount++;\n }\n }\n\n return { inputTokens, outputTokens, cachedTokens, cost, llmCallCount };\n }\n\n /**\n * Add a text node (flows between LLM calls).\n */\n addText(content: string): string {\n const id = this.generateId(\"text\");\n\n const node: TextNode = {\n id,\n type: \"text\",\n depth: 0,\n parentId: null,\n content,\n children: [] as never[],\n };\n\n this.nodes.set(id, node);\n this.rootIds.push(id);\n this.rebuildBlocks();\n return id;\n }\n\n /**\n * Find a gadget node by its invocation ID.\n * Uses O(1) Map lookup instead of linear search.\n */\n findGadgetByInvocationId(invocationId: string): GadgetNode | undefined {\n const blockId = this.gadgetByInvocationId.get(invocationId);\n if (!blockId) return undefined;\n const node = this.nodes.get(blockId);\n return node?.type === \"gadget\" ? (node as GadgetNode) : undefined;\n }\n\n /**\n * Set the current LLM call context for gadget parenting.\n * Used when processing subagent events to ensure gadgets are nested\n * under the correct subagent LLM call.\n */\n setCurrentLLMCall(llmCallId: string | null): void {\n this.currentLLMCallId = llmCallId;\n }\n\n /**\n * Get the current LLM call ID.\n *\n * In tree mode, this is only used for attaching raw request/response data\n * to the block for the raw viewer feature. Parent-child relationships are\n * determined by event.parentId in handleTreeEvent(), not by this method.\n */\n getCurrentLLMCallId(): string | null {\n return this.currentLLMCallId;\n }\n\n /**\n * Check if tree subscription is active.\n * When active, external code should skip block creation (tree handles it).\n */\n isTreeSubscribed(): boolean {\n return this.treeUnsubscribe !== null;\n }\n\n /**\n * Store raw response for an LLM call (enrichment only).\n * Use this when tree handles completion but hooks have raw data.\n */\n setLLMCallResponse(id: string, rawResponse: string): void {\n const node = this.getNode(id) as LLMCallNode | undefined;\n if (!node || node.type !== \"llm_call\") return;\n node.rawResponse = rawResponse;\n }\n\n /**\n * Clear all blocks.\n */\n clear(): void {\n this.nodes.clear();\n this.blocks.clear();\n this.expandedStates.clear();\n this.llmCallByIteration.clear();\n this.gadgetByInvocationId.clear();\n this.nestedLLMCallByKey.clear();\n this.rootIds = [];\n this.selectableIds = [];\n this.selectedIndex = -1;\n this.currentLLMCallId = null;\n\n // Clear container children\n for (const child of [...this.container.children]) {\n child.detach();\n }\n this.renderCallback();\n }\n\n // ───────────────────────────────────────────────────────────────────────────\n // Public API - Selection & Navigation\n // ───────────────────────────────────────────────────────────────────────────\n\n /**\n * Move selection to the next selectable block.\n */\n selectNext(): void {\n if (this.selectableIds.length === 0) return;\n\n if (this.selectedIndex < this.selectableIds.length - 1) {\n this.selectedIndex++;\n this.updateSelection();\n }\n }\n\n /**\n * Move selection to the previous selectable block.\n */\n selectPrevious(): void {\n if (this.selectableIds.length === 0) return;\n\n if (this.selectedIndex > 0) {\n this.selectedIndex--;\n this.updateSelection();\n } else if (this.selectedIndex === -1 && this.selectableIds.length > 0) {\n // Select last if nothing selected\n this.selectedIndex = this.selectableIds.length - 1;\n this.updateSelection();\n }\n }\n\n /**\n * Select first selectable block.\n */\n selectFirst(): void {\n if (this.selectableIds.length > 0) {\n this.selectedIndex = 0;\n this.updateSelection();\n }\n }\n\n /**\n * Select last selectable block.\n */\n selectLast(): void {\n if (this.selectableIds.length > 0) {\n this.selectedIndex = this.selectableIds.length - 1;\n this.updateSelection();\n }\n }\n\n /**\n * Get currently selected block.\n */\n getSelectedBlock(): SelectableBlock | undefined {\n if (this.selectedIndex < 0 || this.selectedIndex >= this.selectableIds.length) {\n return undefined;\n }\n return this.blocks.get(this.selectableIds[this.selectedIndex]);\n }\n\n /**\n * Toggle expand/collapse of selected block.\n */\n toggleExpand(): void {\n const block = this.getSelectedBlock();\n if (!block) return;\n\n block.expanded = !block.expanded;\n // Persist expanded state across rebuilds\n this.expandedStates.set(block.node.id, block.expanded);\n this.updateBlock(block.node.id);\n }\n\n /**\n * Collapse selected block (or deselect if already collapsed).\n */\n collapseOrDeselect(): void {\n const block = this.getSelectedBlock();\n if (!block) return;\n\n if (block.expanded) {\n block.expanded = false;\n // Persist collapsed state across rebuilds\n this.expandedStates.set(block.node.id, false);\n this.updateBlock(block.node.id);\n } else {\n this.selectedIndex = -1;\n this.updateSelection();\n }\n }\n\n // ───────────────────────────────────────────────────────────────────────────\n // Private - Node & Block Management\n // ───────────────────────────────────────────────────────────────────────────\n\n private generateId(prefix: string): string {\n return `${prefix}_${++this.nodeIdCounter}`;\n }\n\n private getNode(id: string): BlockNode | undefined {\n return this.nodes.get(id);\n }\n\n /**\n * Rebuild all blocks from the node tree.\n * Called when nodes are added/removed.\n */\n private rebuildBlocks(): void {\n // Clear existing blocks\n for (const child of [...this.container.children]) {\n child.detach();\n }\n this.blocks.clear();\n this.selectableIds = [];\n\n // Track vertical position (starts at 0, will be offset for bottom-alignment)\n let top = 0;\n\n // Traverse tree in order\n for (const rootId of this.rootIds) {\n top = this.renderNodeTree(rootId, top);\n }\n\n // Restore selection if possible\n if (this.selectedIndex >= this.selectableIds.length) {\n this.selectedIndex = this.selectableIds.length - 1;\n }\n\n // Apply bottom alignment and auto-scroll (chat-like behavior)\n this.applyBottomAlignmentAndScroll();\n\n this.renderCallback();\n }\n\n /**\n * Render a node and its children recursively.\n * Returns the next available top position.\n */\n private renderNodeTree(nodeId: string, top: number): number {\n const node = this.getNode(nodeId);\n if (!node) return top;\n\n // Create block for this node\n const block = this.createBlock(node, top);\n this.blocks.set(nodeId, block);\n\n // Track selectable blocks\n if (block.selectable) {\n this.selectableIds.push(nodeId);\n }\n\n // Calculate height of this block\n const height = this.getBlockHeight(block);\n top += height;\n\n // Always render children (gadgets are always visible under their LLM call)\n // The expanded state controls inline details, not child visibility\n if (\"children\" in node && node.children.length > 0) {\n for (const childId of node.children) {\n top = this.renderNodeTree(childId, top);\n }\n }\n\n return top;\n }\n\n /**\n * Create a block for a node.\n */\n private createBlock(node: BlockNode, top: number): SelectableBlock {\n const isSelected = this.selectableIds.length === this.selectedIndex;\n const selectable = node.type !== \"text\";\n\n // Get persisted expanded state (survives rebuildBlocks), default to collapsed\n const expanded = this.expandedStates.get(node.id) ?? false;\n\n // Format content\n const content = this.formatBlockContent(node, isSelected, expanded);\n\n // Create Box widget\n const box = new Box({\n parent: this.container,\n top,\n left: 0,\n width: \"100%\",\n height: content.split(\"\\n\").length,\n content,\n tags: false, // We use ANSI codes directly\n });\n\n return {\n node,\n box,\n expanded,\n selectable,\n };\n }\n\n /**\n * Format block content based on type and state.\n */\n private formatBlockContent(\n node: BlockNode,\n selected: boolean,\n expanded: boolean,\n ): string {\n const indent = getIndent(node.depth);\n\n switch (node.type) {\n case \"llm_call\": {\n const collapsed = formatLLMCallCollapsed(node, selected);\n if (!expanded) {\n return indent + collapsed;\n }\n const expandedLines = formatLLMCallExpanded(node);\n const contIndent = getContinuationIndent(node.depth);\n return [\n indent + collapsed,\n ...expandedLines.map((line) => contIndent + line),\n ].join(\"\\n\");\n }\n\n case \"gadget\": {\n const collapsed = formatGadgetCollapsed(node, selected);\n if (!expanded) {\n return indent + collapsed;\n }\n const expandedLines = formatGadgetExpanded(node);\n const contIndent = getContinuationIndent(node.depth);\n return [\n indent + collapsed,\n ...expandedLines.map((line) => contIndent + line),\n ].join(\"\\n\");\n }\n\n case \"text\":\n return node.content;\n }\n }\n\n /**\n * Get the height (in lines) of a block.\n */\n private getBlockHeight(block: SelectableBlock): number {\n const content = block.box.getContent();\n return content.split(\"\\n\").length;\n }\n\n /**\n * Update a single block (after state change).\n */\n private updateBlock(nodeId: string): void {\n const block = this.blocks.get(nodeId);\n const node = this.getNode(nodeId);\n if (!block || !node) return;\n\n const isSelected = this.selectableIds[this.selectedIndex] === nodeId;\n const content = this.formatBlockContent(node, isSelected, block.expanded);\n\n const oldHeight = this.getBlockHeight(block);\n block.box.setContent(content);\n const newHeight = content.split(\"\\n\").length;\n block.box.height = newHeight;\n\n // If height changed, need to reposition subsequent blocks\n if (oldHeight !== newHeight) {\n this.repositionBlocks();\n }\n\n this.renderCallback();\n }\n\n /**\n * Update selection highlighting.\n */\n private updateSelection(): void {\n // Update all selectable blocks\n for (const id of this.selectableIds) {\n const block = this.blocks.get(id);\n if (block) {\n const isSelected = this.selectableIds[this.selectedIndex] === id;\n const content = this.formatBlockContent(block.node, isSelected, block.expanded);\n block.box.setContent(content);\n }\n }\n\n // Scroll to keep selection visible\n this.scrollToSelection();\n this.renderCallback();\n }\n\n /**\n * Reposition all blocks after height change.\n */\n private repositionBlocks(): void {\n let top = 0;\n for (const rootId of this.rootIds) {\n top = this.repositionNodeTree(rootId, top);\n }\n\n // Re-apply bottom alignment after repositioning\n this.applyBottomAlignmentAndScroll();\n }\n\n private repositionNodeTree(nodeId: string, top: number): number {\n const block = this.blocks.get(nodeId);\n const node = this.getNode(nodeId);\n if (!block || !node) return top;\n\n block.box.top = top;\n const height = this.getBlockHeight(block);\n top += height;\n\n // Always traverse children (they're always visible)\n if (\"children\" in node) {\n for (const childId of node.children) {\n top = this.repositionNodeTree(childId, top);\n }\n }\n\n return top;\n }\n\n /**\n * Scroll container to keep selected block visible.\n */\n private scrollToSelection(): void {\n const block = this.getSelectedBlock();\n if (!block) return;\n\n // Skip if scroll methods not available\n if (!this.container.getScroll || !this.container.scrollTo) return;\n\n const blockTop = block.box.top as number;\n const blockHeight = this.getBlockHeight(block);\n const containerHeight = this.container.height as number;\n const scrollPos = this.container.getScroll();\n\n // If block is above visible area, scroll up\n if (blockTop < scrollPos) {\n this.container.scrollTo(blockTop);\n // Disable follow mode when scrolling up\n this.followMode = false;\n }\n // If block is below visible area, scroll down\n else if (blockTop + blockHeight > scrollPos + containerHeight) {\n this.container.scrollTo(blockTop + blockHeight - containerHeight);\n // Check if now at bottom, re-enable follow mode\n if (this.isAtBottom()) {\n this.followMode = true;\n }\n }\n }\n\n // ───────────────────────────────────────────────────────────────────────────\n // Bottom Alignment & Auto-Scroll (Chat-like behavior)\n // ───────────────────────────────────────────────────────────────────────────\n\n /**\n * Calculate total height of all rendered blocks.\n * Used for bottom-alignment offset calculation.\n */\n private getTotalContentHeight(): number {\n let totalHeight = 0;\n for (const rootId of this.rootIds) {\n totalHeight = this.sumNodeTreeHeight(rootId, totalHeight);\n }\n return totalHeight;\n }\n\n private sumNodeTreeHeight(nodeId: string, currentHeight: number): number {\n const block = this.blocks.get(nodeId);\n const node = this.getNode(nodeId);\n if (!block || !node) return currentHeight;\n\n currentHeight += this.getBlockHeight(block);\n\n if (\"children\" in node) {\n for (const childId of node.children) {\n currentHeight = this.sumNodeTreeHeight(childId, currentHeight);\n }\n }\n return currentHeight;\n }\n\n /**\n * Calculate vertical offset to push content to bottom when content < viewport.\n * Returns 0 when content fills or exceeds viewport.\n */\n private getBottomAlignmentOffset(): number {\n const containerHeight = this.container.height as number;\n const contentHeight = this.getTotalContentHeight();\n\n if (contentHeight >= containerHeight) {\n return 0; // Content fills viewport, no offset needed\n }\n\n return containerHeight - contentHeight;\n }\n\n /**\n * Check if scroll position is at or near the bottom.\n */\n private isAtBottom(): boolean {\n if (!this.container.getScroll) return true;\n\n const scrollPos = this.container.getScroll();\n const containerHeight = this.container.height as number;\n const contentHeight = this.getTotalContentHeight();\n\n // At bottom if scrollPos + containerHeight >= contentHeight (with threshold)\n const maxScroll = Math.max(0, contentHeight - containerHeight);\n return scrollPos >= maxScroll - BlockRenderer.AT_BOTTOM_THRESHOLD;\n }\n\n /**\n * Scroll to the bottom of content.\n */\n private scrollToBottom(): void {\n if (!this.container.setScrollPerc) return;\n this.container.setScrollPerc(100);\n }\n\n /**\n * Apply bottom-alignment offset to all blocks and handle auto-scroll.\n * Called after rebuildBlocks() and repositionBlocks().\n */\n private applyBottomAlignmentAndScroll(): void {\n const offset = this.getBottomAlignmentOffset();\n\n // Apply offset to all blocks if content is shorter than viewport\n if (offset > 0) {\n for (const rootId of this.rootIds) {\n this.applyOffsetToNodeTree(rootId, offset);\n }\n }\n\n // Auto-scroll to bottom if in follow mode\n if (this.followMode) {\n this.scrollToBottom();\n }\n }\n\n /**\n * Apply vertical offset to a node tree (for bottom alignment).\n */\n private applyOffsetToNodeTree(nodeId: string, offset: number): void {\n const block = this.blocks.get(nodeId);\n const node = this.getNode(nodeId);\n if (!block || !node) return;\n\n block.box.top = (block.box.top as number) + offset;\n\n if (\"children\" in node) {\n for (const childId of node.children) {\n this.applyOffsetToNodeTree(childId, offset);\n }\n }\n }\n\n /**\n * Handle user scroll event.\n * Disables follow mode if user scrolls away from bottom.\n */\n handleUserScroll(): void {\n if (!this.isAtBottom()) {\n this.followMode = false;\n } else {\n // User scrolled back to bottom, re-enable follow mode\n this.followMode = true;\n }\n }\n\n /**\n * Re-enable follow mode and scroll to bottom.\n * Called when user presses End/G to go to last block.\n */\n enableFollowMode(): void {\n this.followMode = true;\n this.scrollToBottom();\n this.renderCallback();\n }\n\n /**\n * Handle terminal resize.\n * Recalculates bottom alignment with new container dimensions.\n */\n handleResize(): void {\n this.repositionBlocks();\n this.renderCallback();\n }\n\n // ───────────────────────────────────────────────────────────────────────────\n // ExecutionTree Integration\n // ───────────────────────────────────────────────────────────────────────────\n\n /** Unsubscribe function for tree events */\n private treeUnsubscribe: (() => void) | null = null;\n\n /** Map tree node IDs to block node IDs */\n private treeNodeToBlockId = new Map<string, string>();\n\n /**\n * Subscribe to an ExecutionTree for automatic block updates.\n *\n * When subscribed, the BlockRenderer will automatically create and update\n * blocks based on tree events. This eliminates the need to manually call\n * addLLMCall(), addGadget(), etc.\n *\n * @param tree - The ExecutionTree to subscribe to\n * @returns Unsubscribe function to stop listening\n *\n * @example\n * ```typescript\n * const agent = builder.ask(\"Hello\");\n * const unsubscribe = blockRenderer.subscribeToTree(agent.getTree());\n *\n * for await (const event of agent.run()) {\n * // Blocks are automatically updated via tree subscription\n * }\n *\n * unsubscribe();\n * ```\n */\n subscribeToTree(tree: ExecutionTree): () => void {\n // Unsubscribe from previous tree if any\n if (this.treeUnsubscribe) {\n this.treeUnsubscribe();\n }\n\n this.treeNodeToBlockId.clear();\n\n // Subscribe to all events\n this.treeUnsubscribe = tree.onAll((event: ExecutionEvent) => {\n this.handleTreeEvent(event, tree);\n });\n\n return () => {\n if (this.treeUnsubscribe) {\n this.treeUnsubscribe();\n this.treeUnsubscribe = null;\n }\n };\n }\n\n /**\n * Handle an ExecutionTree event.\n */\n private handleTreeEvent(event: ExecutionEvent, tree: ExecutionTree): void {\n switch (event.type) {\n case \"llm_call_start\": {\n // Find parent block ID if this is a nested LLM call\n let parentBlockId: string | undefined;\n if (event.parentId) {\n parentBlockId = this.treeNodeToBlockId.get(event.parentId);\n }\n\n // Create the LLM call block\n // Note: event.iteration is 0-indexed, but display uses 1-indexed\n // The hook path already adds +1, so we do the same here for deduplication\n // Pass isNested=true when depth > 0 to prevent false deduplication\n // against top-level calls when parentBlockId lookup fails\n const blockId = this.addLLMCall(\n event.iteration + 1,\n event.model,\n parentBlockId,\n event.depth > 0,\n );\n this.treeNodeToBlockId.set(event.nodeId, blockId);\n\n // Attach raw request data from tree (needed for nested LLM calls)\n const startNode = tree.getNode(event.nodeId);\n if (startNode?.type === \"llm_call\" && startNode.request) {\n this.setLLMCallRequest(blockId, startNode.request);\n }\n break;\n }\n\n case \"llm_call_complete\": {\n const blockId = this.treeNodeToBlockId.get(event.nodeId);\n if (blockId) {\n this.completeLLMCall(blockId, {\n inputTokens: event.usage?.inputTokens,\n cachedInputTokens: event.usage?.cachedInputTokens,\n outputTokens: event.usage?.outputTokens,\n cost: event.cost,\n finishReason: event.finishReason ?? undefined,\n });\n\n // Attach raw response data from tree (needed for nested LLM calls)\n const completeNode = tree.getNode(event.nodeId);\n if (completeNode?.type === \"llm_call\" && completeNode.response) {\n this.setLLMCallResponse(blockId, completeNode.response);\n }\n }\n break;\n }\n\n case \"gadget_call\": {\n // Find parent LLM call block\n let parentBlockId: string | undefined;\n if (event.parentId) {\n parentBlockId = this.treeNodeToBlockId.get(event.parentId);\n }\n\n // Temporarily set current LLM call for proper parenting\n const previousLLMCallId = this.currentLLMCallId;\n if (parentBlockId) {\n this.setCurrentLLMCall(parentBlockId);\n }\n\n const blockId = this.addGadget(\n event.invocationId,\n event.name,\n event.parameters,\n );\n this.treeNodeToBlockId.set(event.nodeId, blockId);\n\n // Restore previous context\n this.currentLLMCallId = previousLLMCallId;\n break;\n }\n\n case \"gadget_complete\": {\n this.completeGadget(\n event.invocationId,\n event.result,\n undefined,\n event.executionTimeMs,\n event.cost,\n );\n break;\n }\n\n case \"gadget_error\": {\n this.completeGadget(\n event.invocationId,\n undefined,\n event.error,\n event.executionTimeMs,\n );\n break;\n }\n\n case \"gadget_skipped\": {\n // Find the gadget and mark it as skipped\n const node = this.findGadgetByInvocationId(event.invocationId);\n if (node) {\n node.isComplete = true;\n node.error = `Skipped: ${event.failedDependencyError}`;\n this.updateBlock(node.id);\n }\n break;\n }\n\n // text events are handled separately (not part of tree structure)\n // llm_call_stream and llm_call_error are informational\n }\n }\n\n /**\n * Get block ID for a tree node ID.\n * Useful for external code that needs to correlate tree nodes with blocks.\n */\n getBlockIdForTreeNode(treeNodeId: string): string | undefined {\n return this.treeNodeToBlockId.get(treeNodeId);\n }\n}\n","/**\n * Block content formatters for interactive TUI blocks.\n *\n * Provides formatting for both collapsed (one-line) and expanded (multi-line)\n * views of LLM calls and gadget executions.\n *\n * @module\n */\n\nimport chalk from \"chalk\";\nimport type { LLMCallNode, GadgetNode } from \"../tui/types.js\";\nimport { formatTokens, formatCost } from \"./formatters.js\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Box Drawing Characters\n// ─────────────────────────────────────────────────────────────────────────────\n\nconst BOX = {\n topLeft: \"┌\",\n topRight: \"┐\",\n bottomLeft: \"└\",\n bottomRight: \"┘\",\n horizontal: \"─\",\n vertical: \"│\",\n verticalRight: \"├\",\n verticalLeft: \"┤\",\n} as const;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Collapse/Expand Indicators\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Indicator for a collapsed block that can be expanded */\nexport const COLLAPSED_INDICATOR = \"▶\";\n/** Indicator for an expanded block */\nexport const EXPANDED_INDICATOR = \"▼\";\n/** Indicator for an in-progress item */\nexport const PROGRESS_INDICATOR = \"⏵\";\n/** Indicator for a completed item */\nexport const COMPLETE_INDICATOR = \"✓\";\n/** Indicator for an error */\nexport const ERROR_INDICATOR = \"✗\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// LLM Call Formatting\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Formats a collapsed LLM call line.\n *\n * Format: `▶ #1 claude-sonnet-4 | ↑ 10.4k | ⟳ 3.0k | ↓ 49 | 24.8s | $0.0032 | STOP`\n */\nexport function formatLLMCallCollapsed(node: LLMCallNode, selected: boolean): string {\n const indicator = node.isComplete ? COMPLETE_INDICATOR : PROGRESS_INDICATOR;\n const indicatorColor = node.isComplete ? chalk.green : chalk.blue;\n\n const parts: string[] = [];\n\n // #N model\n const callNumber = chalk.cyan(`#${node.iteration}`);\n const model = chalk.magenta(node.model);\n parts.push(`${callNumber} ${model}`);\n\n if (node.details) {\n const d = node.details;\n\n // ↑ input tokens\n if (d.inputTokens && d.inputTokens > 0) {\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${formatTokens(d.inputTokens)}`));\n }\n\n // ⟳ cached tokens\n if (d.cachedInputTokens && d.cachedInputTokens > 0) {\n parts.push(chalk.dim(\"⟳\") + chalk.blue(` ${formatTokens(d.cachedInputTokens)}`));\n }\n\n // ↓ output tokens\n if (d.outputTokens && d.outputTokens > 0) {\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${formatTokens(d.outputTokens)}`));\n }\n\n // Time\n if (d.elapsedSeconds !== undefined) {\n parts.push(chalk.dim(`${d.elapsedSeconds.toFixed(1)}s`));\n }\n\n // Cost\n if (d.cost !== undefined && d.cost > 0) {\n parts.push(chalk.cyan(`$${formatCost(d.cost)}`));\n }\n\n // Finish reason\n if (node.isComplete && d.finishReason) {\n const reason = d.finishReason.toUpperCase();\n if (reason === \"STOP\" || reason === \"END_TURN\") {\n parts.push(chalk.green(reason));\n } else {\n parts.push(chalk.yellow(reason));\n }\n }\n }\n\n const line = parts.join(chalk.dim(\" | \"));\n const prefix = indicatorColor(indicator);\n\n // Highlight selected line\n if (selected) {\n return chalk.bgBlue.white(`${prefix} ${line}`);\n }\n\n return `${prefix} ${line}`;\n}\n\n/**\n * Formats expanded LLM call details as multiple lines.\n *\n * Returns an array of lines to display below the collapsed header.\n */\nexport function formatLLMCallExpanded(node: LLMCallNode): string[] {\n const lines: string[] = [];\n const indent = \" \";\n const d = node.details;\n\n if (!d) {\n lines.push(`${indent}${chalk.dim(\"No details available\")}`);\n return lines;\n }\n\n // Calculate box width\n const width = Math.min(60, (process.stdout.columns || 80) - 4);\n const headerLine = `${BOX.topLeft}${BOX.horizontal} Details ${BOX.horizontal.repeat(width - 11)}`;\n\n lines.push(`${indent}${chalk.dim(headerLine)}`);\n\n // Model\n lines.push(`${indent}${chalk.dim(BOX.vertical)} Model: ${chalk.magenta(node.model)}`);\n\n // Input tokens with cache breakdown\n if (d.inputTokens !== undefined) {\n let inputLine = `${indent}${chalk.dim(BOX.vertical)} Input: ${chalk.yellow(formatTokens(d.inputTokens))} tokens`;\n if (d.cachedInputTokens && d.cachedInputTokens > 0) {\n const cachePercent = ((d.cachedInputTokens / d.inputTokens) * 100).toFixed(1);\n inputLine += chalk.blue(` (${formatTokens(d.cachedInputTokens)} cached, ${cachePercent}%)`);\n }\n lines.push(inputLine);\n }\n\n // Output tokens\n if (d.outputTokens !== undefined) {\n lines.push(`${indent}${chalk.dim(BOX.vertical)} Output: ${chalk.green(formatTokens(d.outputTokens))} tokens`);\n }\n\n // Context usage\n if (d.contextPercent !== undefined) {\n let contextColor = chalk.green;\n if (d.contextPercent >= 80) contextColor = chalk.red;\n else if (d.contextPercent >= 50) contextColor = chalk.yellow;\n lines.push(`${indent}${chalk.dim(BOX.vertical)} Context: ${contextColor(`${Math.round(d.contextPercent)}%`)}`);\n }\n\n // Time with tokens/second calculation\n if (d.elapsedSeconds !== undefined) {\n let timeLine = `${indent}${chalk.dim(BOX.vertical)} Time: ${chalk.dim(`${d.elapsedSeconds.toFixed(1)}s`)}`;\n if (d.outputTokens && d.elapsedSeconds > 0) {\n const tokensPerSec = Math.round(d.outputTokens / d.elapsedSeconds);\n timeLine += chalk.dim(` (${tokensPerSec} tok/s)`);\n }\n lines.push(timeLine);\n }\n\n // Cost with breakdown\n if (d.cost !== undefined && d.cost > 0) {\n lines.push(`${indent}${chalk.dim(BOX.vertical)} Cost: ${chalk.cyan(`$${formatCost(d.cost)}`)}`);\n }\n\n // Finish reason\n if (d.finishReason) {\n const reason = d.finishReason.toUpperCase();\n const reasonColor = reason === \"STOP\" || reason === \"END_TURN\" ? chalk.green : chalk.yellow;\n lines.push(`${indent}${chalk.dim(BOX.vertical)} Finish: ${reasonColor(reason)}`);\n }\n\n // Close box\n lines.push(`${indent}${chalk.dim(BOX.bottomLeft + BOX.horizontal.repeat(width - 1))}`);\n\n return lines;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Gadget Formatting\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Formats a collapsed gadget line.\n *\n * Format: `✓ Navigate(url=https://...) 1.2s | ↑ 5k ⤿ 2k ↓ 1k | $0.01`\n */\nexport function formatGadgetCollapsed(node: GadgetNode, selected: boolean): string {\n let indicator: string;\n let indicatorColor: typeof chalk;\n\n if (node.error) {\n indicator = ERROR_INDICATOR;\n indicatorColor = chalk.red;\n } else if (node.isComplete) {\n indicator = COMPLETE_INDICATOR;\n indicatorColor = chalk.green;\n } else {\n indicator = PROGRESS_INDICATOR;\n indicatorColor = chalk.blue;\n }\n\n const gadgetLabel = chalk.magenta.bold(node.name);\n\n // Format parameters inline (use available terminal width)\n let paramsStr = \"\";\n if (node.parameters && Object.keys(node.parameters).length > 0) {\n const termWidth = process.stdout.columns || 120;\n const maxParamLen = Math.max(60, termWidth - 40); // Leave room for indicator, name, time\n const entries = Object.entries(node.parameters).slice(0, 4);\n const formatted = entries.map(([key, value]) => {\n const strValue = typeof value === \"string\" ? value : JSON.stringify(value);\n const truncated = strValue.length > maxParamLen ? strValue.slice(0, maxParamLen - 3) + \"...\" : strValue;\n return `${chalk.dim(key)}=${chalk.cyan(truncated)}`;\n });\n paramsStr = `${chalk.dim(\"(\")}${formatted.join(chalk.dim(\", \"))}${chalk.dim(\")\")}`;\n }\n\n // Error preview\n let errorStr = \"\";\n if (node.error) {\n const truncated = node.error.length > 40 ? node.error.slice(0, 37) + \"...\" : node.error;\n errorStr = ` ${chalk.red(\"error:\")} ${truncated}`;\n }\n\n // Build metrics array\n const metrics: string[] = [];\n\n // Duration\n if (node.executionTimeMs !== undefined) {\n const time = node.executionTimeMs >= 1000\n ? `${(node.executionTimeMs / 1000).toFixed(1)}s`\n : `${Math.round(node.executionTimeMs)}ms`;\n metrics.push(time);\n }\n\n // Subagent token stats (if any LLM calls were made)\n if (node.subagentStats && node.subagentStats.llmCallCount > 0) {\n const { inputTokens, cachedTokens, outputTokens } = node.subagentStats;\n const tokenParts: string[] = [];\n tokenParts.push(chalk.dim(\"↑\") + chalk.yellow(` ${formatTokens(inputTokens)}`));\n if (cachedTokens > 0) {\n tokenParts.push(chalk.dim(\"⤿\") + chalk.blue(` ${formatTokens(cachedTokens)}`));\n }\n tokenParts.push(chalk.dim(\"↓\") + chalk.green(` ${formatTokens(outputTokens)}`));\n metrics.push(tokenParts.join(\" \"));\n } else if (node.resultTokens && node.resultTokens > 0) {\n // Simple gadget - just show output tokens\n metrics.push(chalk.dim(\"↓\") + chalk.green(` ${formatTokens(node.resultTokens)}`));\n }\n\n // Cost\n if (node.cost && node.cost > 0) {\n metrics.push(chalk.cyan(`$${formatCost(node.cost)}`));\n }\n\n // Join metrics with separator\n const metricsStr = metrics.length > 0 ? ` ${chalk.dim(metrics.join(\" | \"))}` : \"\";\n\n const line = `${indicatorColor(indicator)} ${gadgetLabel}${paramsStr}${errorStr}${metricsStr}`;\n\n // Highlight selected line\n if (selected) {\n return chalk.bgBlue.white(line);\n }\n\n return line;\n}\n\n/**\n * Formats expanded gadget details as multiple lines.\n *\n * Returns an array of lines to display below the collapsed header.\n */\nexport function formatGadgetExpanded(node: GadgetNode): string[] {\n const lines: string[] = [];\n const indent = \" \";\n const termWidth = process.stdout.columns || 120;\n const width = Math.max(60, termWidth - 8); // Use most of terminal width\n\n // Parameters section\n if (node.parameters && Object.keys(node.parameters).length > 0) {\n const headerLine = `${BOX.topLeft}${BOX.horizontal} Parameters ${BOX.horizontal.repeat(width - 14)}`;\n lines.push(`${indent}${chalk.dim(headerLine)}`);\n\n for (const [key, value] of Object.entries(node.parameters)) {\n const strValue = typeof value === \"string\" ? value : JSON.stringify(value, null, 2);\n // Handle multi-line values\n const valueLines = strValue.split(\"\\n\");\n const maxValueLen = width - 10; // Leave room for indent and key\n if (valueLines.length === 1) {\n const truncated = strValue.length > maxValueLen ? strValue.slice(0, maxValueLen - 3) + \"...\" : strValue;\n lines.push(`${indent}${chalk.dim(BOX.vertical)} ${chalk.dim(key)}: ${chalk.cyan(truncated)}`);\n } else {\n lines.push(`${indent}${chalk.dim(BOX.vertical)} ${chalk.dim(key)}:`);\n for (const line of valueLines.slice(0, 5)) {\n lines.push(`${indent}${chalk.dim(BOX.vertical)} ${chalk.cyan(line)}`);\n }\n if (valueLines.length > 5) {\n lines.push(`${indent}${chalk.dim(BOX.vertical)} ${chalk.dim(`... (${valueLines.length - 5} more lines)`)}`);\n }\n }\n }\n lines.push(`${indent}${chalk.dim(BOX.bottomLeft + BOX.horizontal.repeat(width - 1))}`);\n }\n\n // Result section\n if (node.result || node.error) {\n const headerText = node.error ? \" Error \" : \" Result \";\n const headerLine = `${BOX.topLeft}${BOX.horizontal}${headerText}${BOX.horizontal.repeat(width - headerText.length - 2)}`;\n lines.push(`${indent}${chalk.dim(headerLine)}`);\n\n const content = node.error || node.result || \"\";\n const contentLines = content.split(\"\\n\");\n const maxLines = 10;\n const displayLines = contentLines.slice(0, maxLines);\n\n for (const line of displayLines) {\n const truncated = line.length > width - 4 ? line.slice(0, width - 7) + \"...\" : line;\n const color = node.error ? chalk.red : chalk.white;\n lines.push(`${indent}${chalk.dim(BOX.vertical)} ${color(truncated)}`);\n }\n\n if (contentLines.length > maxLines) {\n lines.push(`${indent}${chalk.dim(BOX.vertical)} ${chalk.dim(`... (${contentLines.length - maxLines} more lines)`)}`);\n }\n\n // Execution time\n if (node.executionTimeMs !== undefined) {\n const time = node.executionTimeMs >= 1000\n ? `${(node.executionTimeMs / 1000).toFixed(1)}s`\n : `${Math.round(node.executionTimeMs)}ms`;\n lines.push(`${indent}${chalk.dim(BOX.vertical)} Time: ${chalk.dim(time)}`);\n }\n\n lines.push(`${indent}${chalk.dim(BOX.bottomLeft + BOX.horizontal.repeat(width - 1))}`);\n }\n\n // Subagent activity section\n if (node.children.length > 0) {\n const headerLine = `${BOX.topLeft}${BOX.horizontal} Subagent Activity ${BOX.horizontal.repeat(width - 21)}`;\n lines.push(`${indent}${chalk.dim(headerLine)}`);\n lines.push(`${indent}${chalk.dim(BOX.vertical)} ${chalk.dim(`${node.children.length} nested calls (expand children to see details)`)}`);\n lines.push(`${indent}${chalk.dim(BOX.bottomLeft + BOX.horizontal.repeat(width - 1))}`);\n }\n\n // Metrics section - show if any metrics are available\n if (node.executionTimeMs !== undefined || node.cost || node.resultTokens || node.subagentStats) {\n const metricsHeaderLine = `${BOX.topLeft}${BOX.horizontal} Metrics ${BOX.horizontal.repeat(width - 11)}`;\n lines.push(`${indent}${chalk.dim(metricsHeaderLine)}`);\n\n // Duration\n if (node.executionTimeMs !== undefined) {\n const time = node.executionTimeMs >= 1000\n ? `${(node.executionTimeMs / 1000).toFixed(1)}s`\n : `${Math.round(node.executionTimeMs)}ms`;\n lines.push(`${indent}${chalk.dim(BOX.vertical)} Duration: ${chalk.dim(time)}`);\n }\n\n // Output tokens (estimated from result)\n if (node.resultTokens && node.resultTokens > 0) {\n lines.push(`${indent}${chalk.dim(BOX.vertical)} Output: ${chalk.green(`~${formatTokens(node.resultTokens)}`)} tokens`);\n }\n\n // Cost\n if (node.cost && node.cost > 0) {\n lines.push(`${indent}${chalk.dim(BOX.vertical)} Cost: ${chalk.cyan(`$${formatCost(node.cost)}`)}`);\n }\n\n // Subagent stats (aggregated from child LLM calls)\n if (node.subagentStats && node.subagentStats.llmCallCount > 0) {\n const s = node.subagentStats;\n const tokenParts: string[] = [];\n tokenParts.push(chalk.dim(\"↑\") + chalk.yellow(` ${formatTokens(s.inputTokens)}`));\n if (s.cachedTokens > 0) {\n tokenParts.push(chalk.dim(\"⤿\") + chalk.blue(` ${formatTokens(s.cachedTokens)}`));\n }\n tokenParts.push(chalk.dim(\"↓\") + chalk.green(` ${formatTokens(s.outputTokens)}`));\n const tokenStr = tokenParts.join(\" \");\n lines.push(`${indent}${chalk.dim(BOX.vertical)} LLM calls: ${s.llmCallCount} (${tokenStr})`);\n }\n\n lines.push(`${indent}${chalk.dim(BOX.bottomLeft + BOX.horizontal.repeat(width - 1))}`);\n }\n\n if (lines.length === 0) {\n lines.push(`${indent}${chalk.dim(\"No details available\")}`);\n }\n\n return lines;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Indentation Helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Creates indentation string based on tree depth.\n * Uses tree-style prefixes for visual hierarchy.\n */\nexport function getIndent(depth: number, isLast = false): string {\n if (depth === 0) return \"\";\n\n const baseIndent = \" \".repeat(depth - 1);\n const connector = isLast ? \"└─ \" : \"├─ \";\n return baseIndent + connector;\n}\n\n/**\n * Creates continuation indent for expanded content.\n */\nexport function getContinuationIndent(depth: number): string {\n if (depth === 0) return \"\";\n return \" \".repeat(depth) + \" \";\n}\n","/**\n * TUI approval dialog for gadget execution approvals.\n *\n * Shows a modal popup for dangerous gadgets (WriteFile, RunCommand, etc.)\n * that require user confirmation before execution.\n */\n\nimport { Box, type Screen } from \"@unblessed/node\";\nimport type { ApprovalResponse, ApprovalContext } from \"./types.js\";\n\n/** Maximum lines to show in preview */\nconst MAX_PREVIEW_LINES = 10;\n\n/** Maximum width for parameter values */\nconst MAX_PARAM_VALUE_LENGTH = 60;\n\n/**\n * Shows an approval dialog and waits for user response.\n *\n * @param screen - The blessed Screen instance\n * @param context - Approval context (gadget name, parameters, preview)\n * @returns Promise resolving to user's response\n */\nexport function showApprovalDialog(\n screen: Screen,\n context: ApprovalContext,\n): Promise<ApprovalResponse> {\n return new Promise((resolve) => {\n // Build dialog content\n const content = buildDialogContent(context);\n\n // Create modal dialog box\n const dialog = new Box({\n parent: screen,\n top: \"center\",\n left: \"center\",\n width: \"70%\",\n height: \"shrink\",\n // Content\n content,\n tags: true,\n // Visual style\n border: {\n type: \"line\",\n },\n style: {\n fg: \"white\",\n bg: \"black\",\n border: {\n fg: \"yellow\",\n },\n },\n // Padding inside border\n padding: {\n left: 1,\n right: 1,\n top: 0,\n bottom: 0,\n },\n // Ensure it's on top\n // Note: blessed doesn't have zIndex, but later-added elements render on top\n });\n\n // Focus the dialog to capture key events\n dialog.focus();\n\n // Handle key presses\n const handleKey = (ch: string, key: { name: string }) => {\n let response: ApprovalResponse | null = null;\n\n switch (key.name) {\n case \"y\":\n response = \"yes\";\n break;\n case \"n\":\n response = \"no\";\n break;\n case \"a\":\n response = \"always\";\n break;\n case \"d\":\n response = \"deny\";\n break;\n case \"escape\":\n response = \"cancel\";\n break;\n }\n\n if (response) {\n // Clean up\n dialog.destroy();\n screen.render();\n\n // Resolve with response\n resolve(response);\n }\n };\n\n dialog.on(\"keypress\", handleKey);\n screen.render();\n });\n}\n\n/**\n * Build the dialog content string.\n */\nfunction buildDialogContent(context: ApprovalContext): string {\n const lines: string[] = [];\n\n // Title\n lines.push(`{bold}{yellow-fg}Approve ${context.gadgetName}?{/}`);\n lines.push(\"\");\n\n // Parameters\n if (Object.keys(context.parameters).length > 0) {\n lines.push(\"{bold}Parameters:{/}\");\n for (const [key, value] of Object.entries(context.parameters)) {\n const valueStr = formatParamValue(value);\n lines.push(` {cyan-fg}${key}{/}: ${valueStr}`);\n }\n lines.push(\"\");\n }\n\n // Preview (if available)\n if (context.preview) {\n lines.push(\"{bold}Preview:{/}\");\n const previewLines = context.preview.split(\"\\n\").slice(0, MAX_PREVIEW_LINES);\n for (const line of previewLines) {\n lines.push(` {gray-fg}${escapeContent(line)}{/}`);\n }\n if (context.preview.split(\"\\n\").length > MAX_PREVIEW_LINES) {\n lines.push(\" {gray-fg}...{/}\");\n }\n lines.push(\"\");\n }\n\n // Options\n lines.push(\"{bold}Options:{/}\");\n lines.push(\" {green-fg}[y]{/}es - Execute this time\");\n lines.push(\" {red-fg}[n]{/}o - Skip this time\");\n lines.push(\" {blue-fg}[a]{/}lways - Always allow this gadget\");\n lines.push(\" {magenta-fg}[d]{/}eny - Always deny this gadget\");\n lines.push(\" {gray-fg}[ESC]{/} - Cancel\");\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format a parameter value for display.\n */\nfunction formatParamValue(value: unknown): string {\n let str: string;\n\n if (typeof value === \"string\") {\n str = value;\n } else if (value === null || value === undefined) {\n str = String(value);\n } else {\n str = JSON.stringify(value);\n }\n\n // Truncate if too long\n if (str.length > MAX_PARAM_VALUE_LENGTH) {\n str = str.slice(0, MAX_PARAM_VALUE_LENGTH - 1) + \"…\";\n }\n\n // Escape blessed tags\n return escapeContent(str);\n}\n\n/**\n * Escape content for blessed tags.\n */\nfunction escapeContent(str: string): string {\n // Escape curly braces that could be interpreted as blessed tags\n return str.replace(/\\{/g, \"{{\").replace(/\\}/g, \"}}\");\n}\n","/**\n * Full-screen raw request/response viewer for LLM calls and gadgets.\n *\n * Features:\n * - Scrollable content with arrow keys, PgUp/PgDn, Home/End\n * - Message formatting with role headers (LLM calls)\n * - JSON formatting for gadget parameters\n * - Escape or \"q\" to close\n */\n\nimport { Box, type Screen } from \"@unblessed/node\";\nimport type { LLMMessage } from \"../../core/messages.js\";\n\nexport type RawViewerMode = \"request\" | \"response\";\n\ninterface RawViewerOptions {\n screen: Screen;\n mode: RawViewerMode;\n // For LLM calls\n request?: LLMMessage[];\n response?: string;\n iteration?: number;\n model?: string;\n // For gadgets\n gadgetName?: string;\n parameters?: Record<string, unknown>;\n result?: string;\n error?: string;\n}\n\n// ANSI color codes\nconst RESET = \"\\x1b[0m\";\nconst BOLD = \"\\x1b[1m\";\nconst DIM = \"\\x1b[2m\";\nconst RED = \"\\x1b[31m\";\nconst MAGENTA = \"\\x1b[35m\";\nconst GREEN = \"\\x1b[32m\";\nconst CYAN = \"\\x1b[36m\";\nconst YELLOW = \"\\x1b[33m\";\nconst WHITE = \"\\x1b[37m\";\nconst BG_BLUE = \"\\x1b[44m\";\n\n/** Return type for showRawViewer */\nexport interface RawViewerHandle {\n /** Promise that resolves when the viewer is closed */\n closed: Promise<void>;\n /** Function to programmatically close the viewer */\n close: () => void;\n}\n\n/**\n * Shows a full-screen viewer for raw LLM request/response or gadget parameters/result.\n * Returns a handle with a promise and a close function.\n */\nexport function showRawViewer(options: RawViewerOptions): RawViewerHandle {\n let closeCallback: () => void = () => {};\n\n const closed = new Promise<void>((resolve) => {\n const {\n screen,\n mode,\n request,\n response,\n iteration,\n model,\n gadgetName,\n parameters,\n result,\n error,\n } = options;\n\n // Format content based on mode and node type\n let content: string;\n let title: string;\n\n // Determine if this is a gadget viewer (gadgetName is provided)\n const isGadget = gadgetName !== undefined;\n\n if (isGadget) {\n // Gadget viewer\n if (mode === \"request\") {\n title = ` Raw Parameters - ${gadgetName} `;\n if (!parameters || Object.keys(parameters).length === 0) {\n content = `${DIM}No parameters${RESET}`;\n } else {\n content = formatGadgetParameters(parameters);\n }\n } else {\n title = ` Raw Result - ${gadgetName} `;\n if (error) {\n content = `${RED}${BOLD}Error:${RESET}\\n${error}`;\n } else if (!result) {\n content = `${DIM}No result data available${RESET}`;\n } else {\n content = formatGadgetResult(result);\n }\n }\n } else {\n // LLM call viewer\n if (mode === \"request\") {\n title = ` Raw Request - #${iteration} ${model} `;\n if (!request || request.length === 0) {\n content = `${DIM}No request data available${RESET}`;\n } else {\n content = formatMessages(request);\n }\n } else {\n title = ` Raw Response - #${iteration} ${model} `;\n if (!response) {\n content = `${DIM}No response data available${RESET}`;\n } else {\n content = response;\n }\n }\n }\n\n // Create full-screen modal\n const viewer = new Box({\n parent: screen,\n top: 0,\n left: 0,\n width: \"100%\",\n height: \"100%-1\", // Leave room for help bar\n scrollable: true,\n alwaysScroll: true,\n keys: true,\n vi: true,\n mouse: true,\n scrollbar: {\n ch: \" \",\n style: { bg: \"blue\" },\n },\n border: { type: \"line\" },\n label: title,\n style: {\n fg: \"white\",\n bg: \"black\",\n border: { fg: \"cyan\" },\n label: { fg: \"cyan\", bold: true },\n },\n padding: { left: 1, right: 1 },\n content,\n tags: false, // We use ANSI codes directly\n });\n\n // Add help bar at the bottom\n const helpBar = new Box({\n parent: screen,\n bottom: 0,\n left: 0,\n width: \"100%\",\n height: 1,\n content: `${DIM} [${WHITE}↑/↓/PgUp/PgDn${DIM}] Scroll [${WHITE}Home/End${DIM}] Jump [${WHITE}Escape/q${DIM}] Close${RESET}`,\n tags: false,\n style: { fg: \"white\", bg: \"black\" },\n });\n\n viewer.focus();\n\n // Handle close\n const close = () => {\n helpBar.destroy();\n viewer.destroy();\n screen.render();\n resolve();\n };\n\n // Expose close function for external use\n closeCallback = close;\n\n viewer.key([\"escape\", \"q\"], close);\n\n // Additional scroll shortcuts\n viewer.key([\"home\", \"g\"], () => {\n viewer.setScrollPerc?.(0);\n screen.render();\n });\n\n viewer.key([\"end\", \"S-g\"], () => {\n viewer.setScrollPerc?.(100);\n screen.render();\n });\n\n screen.render();\n });\n\n return { closed, close: closeCallback };\n}\n\n/**\n * Format LLM messages array for display.\n * Shows role headers and content with color coding.\n */\nfunction formatMessages(messages: LLMMessage[]): string {\n const lines: string[] = [];\n const separator = \"─\".repeat(78);\n\n for (let i = 0; i < messages.length; i++) {\n const msg = messages[i];\n const roleColor = getRoleColor(msg.role);\n const roleName = msg.role.toUpperCase();\n\n // Message header\n lines.push(`${DIM}${separator}${RESET}`);\n lines.push(\n `${roleColor}${BOLD}[${roleName}]${RESET} ${DIM}Message ${i + 1} of ${messages.length}${RESET}`,\n );\n lines.push(`${DIM}${separator}${RESET}`);\n lines.push(\"\");\n\n // Message content\n const contentLines = formatMessageContent(msg.content);\n lines.push(...contentLines);\n lines.push(\"\");\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format message content (handles string and multimodal content).\n */\nfunction formatMessageContent(content: string | unknown[]): string[] {\n if (typeof content === \"string\") {\n return content.split(\"\\n\");\n }\n\n if (!Array.isArray(content)) {\n return [JSON.stringify(content, null, 2)];\n }\n\n const lines: string[] = [];\n\n for (const part of content) {\n if (typeof part === \"string\") {\n lines.push(...part.split(\"\\n\"));\n } else if (isTextPart(part)) {\n lines.push(...part.text.split(\"\\n\"));\n } else if (isImagePart(part)) {\n const mediaType = part.source?.media_type || \"unknown\";\n lines.push(`${DIM}[Image: ${mediaType}]${RESET}`);\n } else if (isAudioPart(part)) {\n const mediaType = part.source?.media_type || \"unknown\";\n lines.push(`${DIM}[Audio: ${mediaType}]${RESET}`);\n } else if (isToolUsePart(part)) {\n lines.push(`${YELLOW}${BOLD}[Tool Use: ${part.name}]${RESET}`);\n lines.push(`${DIM}ID: ${part.id}${RESET}`);\n lines.push(`${DIM}Input:${RESET}`);\n const inputStr = JSON.stringify(part.input, null, 2);\n lines.push(...inputStr.split(\"\\n\").map((l) => ` ${l}`));\n } else if (isToolResultPart(part)) {\n lines.push(`${CYAN}${BOLD}[Tool Result]${RESET}`);\n lines.push(`${DIM}Tool Use ID: ${part.tool_use_id}${RESET}`);\n if (typeof part.content === \"string\") {\n lines.push(...part.content.split(\"\\n\"));\n } else {\n lines.push(JSON.stringify(part.content, null, 2));\n }\n } else {\n // Unknown part type - show as JSON\n const partType = (part as { type?: string }).type || \"unknown\";\n lines.push(`${DIM}[${partType}]${RESET}`);\n lines.push(JSON.stringify(part, null, 2));\n }\n }\n\n return lines;\n}\n\n/**\n * Get ANSI color code for a message role.\n */\nfunction getRoleColor(role: string): string {\n switch (role) {\n case \"system\":\n return MAGENTA;\n case \"user\":\n return GREEN;\n case \"assistant\":\n return CYAN;\n default:\n return WHITE;\n }\n}\n\n// Type guards for content parts\nfunction isTextPart(part: unknown): part is { type: \"text\"; text: string } {\n return (\n typeof part === \"object\" &&\n part !== null &&\n (part as { type?: string }).type === \"text\" &&\n typeof (part as { text?: unknown }).text === \"string\"\n );\n}\n\nfunction isImagePart(\n part: unknown,\n): part is { type: \"image\"; source?: { media_type?: string } } {\n return (\n typeof part === \"object\" &&\n part !== null &&\n (part as { type?: string }).type === \"image\"\n );\n}\n\nfunction isAudioPart(\n part: unknown,\n): part is { type: \"audio\"; source?: { media_type?: string } } {\n return (\n typeof part === \"object\" &&\n part !== null &&\n (part as { type?: string }).type === \"audio\"\n );\n}\n\nfunction isToolUsePart(\n part: unknown,\n): part is { type: \"tool_use\"; id: string; name: string; input: unknown } {\n return (\n typeof part === \"object\" &&\n part !== null &&\n (part as { type?: string }).type === \"tool_use\"\n );\n}\n\nfunction isToolResultPart(\n part: unknown,\n): part is { type: \"tool_result\"; tool_use_id: string; content: unknown } {\n return (\n typeof part === \"object\" &&\n part !== null &&\n (part as { type?: string }).type === \"tool_result\"\n );\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Gadget Formatting\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Format gadget parameters as pretty-printed JSON with syntax highlighting.\n */\nfunction formatGadgetParameters(params: Record<string, unknown>): string {\n const lines: string[] = [];\n const separator = \"─\".repeat(78);\n\n lines.push(`${DIM}${separator}${RESET}`);\n lines.push(`${CYAN}${BOLD}Parameters${RESET}`);\n lines.push(`${DIM}${separator}${RESET}`);\n lines.push(\"\");\n\n // Pretty-print the parameters with syntax highlighting\n const json = JSON.stringify(params, null, 2);\n const highlighted = highlightJson(json);\n lines.push(highlighted);\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format gadget result for display.\n * Attempts JSON parsing for pretty-printing if the result looks like JSON.\n */\nfunction formatGadgetResult(result: string): string {\n const lines: string[] = [];\n const separator = \"─\".repeat(78);\n\n lines.push(`${DIM}${separator}${RESET}`);\n lines.push(`${GREEN}${BOLD}Result${RESET}`);\n lines.push(`${DIM}${separator}${RESET}`);\n lines.push(\"\");\n\n // Try to parse as JSON for pretty-printing\n const trimmed = result.trim();\n if (\n (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) ||\n (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\"))\n ) {\n try {\n const parsed = JSON.parse(trimmed);\n const json = JSON.stringify(parsed, null, 2);\n lines.push(highlightJson(json));\n return lines.join(\"\\n\");\n } catch {\n // Not valid JSON, display as plain text\n }\n }\n\n // Display as plain text\n lines.push(result);\n return lines.join(\"\\n\");\n}\n\n/**\n * Add basic syntax highlighting to JSON string.\n */\nfunction highlightJson(json: string): string {\n // Highlight keys (strings followed by :)\n let result = json.replace(/\"([^\"]+)\":/g, `${CYAN}\"$1\"${RESET}:`);\n // Highlight string values\n result = result.replace(/: \"([^\"]*)\"/g, `: ${GREEN}\"$1\"${RESET}`);\n // Highlight numbers\n result = result.replace(/: (-?\\d+\\.?\\d*)/g, `: ${YELLOW}$1${RESET}`);\n // Highlight booleans and null\n result = result.replace(/: (true|false|null)/g, `: ${MAGENTA}$1${RESET}`);\n return result;\n}\n","/**\n * TUI Application - Main entry point for the blessed-based terminal interface.\n *\n * Provides a complete TUI experience with:\n * - Interactive selectable/expandable blocks for LLM calls and gadgets\n * - Always-visible input field for AskUser responses\n * - Status bar showing token counts, elapsed time, and cost\n * - Modal dialogs for gadget approval\n *\n * @example\n * ```typescript\n * import { TUIApp } from './tui/index.js';\n *\n * const tui = await TUIApp.create({ model: 'claude-sonnet-4' });\n *\n * // Handle events from agent\n * for await (const event of agent.run()) {\n * tui.handleEvent(event);\n * }\n *\n * tui.destroy();\n * ```\n */\n\nimport type { Screen } from \"@unblessed/node\";\nimport type { ExecutionTree } from \"../../core/execution-tree.js\";\nimport type { StreamEvent, SubagentEvent } from \"../../gadgets/types.js\";\nimport type {\n TUIOptions,\n TUIScreenContext,\n TUIBlockLayout,\n ApprovalContext,\n ApprovalResponse,\n FocusMode,\n} from \"./types.js\";\nimport { createScreen } from \"./screen.js\";\nimport { createBlockLayout, setupBlockNavigationKeys } from \"./layout.js\";\nimport { StatusBar } from \"./status-bar.js\";\nimport { InputHandler } from \"./input-handler.js\";\nimport { BlockRenderer } from \"./block-renderer.js\";\nimport { showApprovalDialog } from \"./approval-dialog.js\";\nimport { showRawViewer, type RawViewerMode } from \"./raw-viewer.js\";\nimport type { LLMCallDisplayInfo } from \"../ui/formatters.js\";\nimport type { LLMMessage } from \"../../core/messages.js\";\n\n/** Window for double Ctrl+C detection (ms) */\nconst CTRL_C_WINDOW_MS = 1000;\n\n/**\n * Main TUI application class with interactive selectable/expandable blocks.\n *\n * Renders LLM calls and gadgets as selectable Box widgets that users\n * can navigate with up/down arrows and expand to see details.\n */\nexport class TUIApp {\n private screenCtx: TUIScreenContext;\n private layout: TUIBlockLayout;\n private statusBar: StatusBar;\n private inputHandler: InputHandler;\n private blockRenderer: BlockRenderer;\n\n /** Abort controller for cancellation */\n private abortController: AbortController | null = null;\n\n /** Last Ctrl+C timestamp for double-press detection */\n private lastCtrlC = 0;\n\n /** Callback for quit events */\n private onQuitCallback: (() => void) | null = null;\n\n /** Callback for cancel events */\n private onCancelCallback: (() => void) | null = null;\n\n /** Track current LLM call ID for gadget parenting */\n private currentLLMCallId: string | null = null;\n\n /** Track current iteration number for status bar */\n private currentIteration = 0;\n\n /** Map gadget invocationId to block renderer's internal ID */\n private gadgetIdMap = new Map<string, string>();\n\n /** Map subagent LLM call key to block renderer's internal ID */\n private subagentLLMCallMap = new Map<string, string>();\n\n /** Current focus mode (browse = navigate blocks, input = type in input field) */\n private focusMode: FocusMode = \"browse\";\n\n /** Close function for currently open raw viewer (if any) */\n private closeRawViewer: (() => void) | null = null;\n\n private constructor(\n screenCtx: TUIScreenContext,\n layout: TUIBlockLayout,\n statusBar: StatusBar,\n inputHandler: InputHandler,\n blockRenderer: BlockRenderer,\n ) {\n this.screenCtx = screenCtx;\n this.layout = layout;\n this.statusBar = statusBar;\n this.inputHandler = inputHandler;\n this.blockRenderer = blockRenderer;\n }\n\n /**\n * Create a new TUI application instance.\n */\n static async create(options: TUIOptions): Promise<TUIApp> {\n const screenCtx = createScreen({\n stdin: options.stdin,\n stdout: options.stdout,\n title: \"llmist\",\n });\n\n const { screen } = screenCtx;\n\n // Create block-based layout with ScrollableBox\n const layout = createBlockLayout(screen);\n\n // Create status bar with both debounced and immediate render callbacks\n const statusBar = new StatusBar(\n layout.statusBar,\n options.model,\n () => screenCtx.requestRender(),\n () => screenCtx.renderNow(),\n );\n\n // Create input handler with both debounced and immediate render callbacks\n // Cast ScrollableBox to Box for InputHandler compatibility\n const inputHandler = new InputHandler(\n layout.inputBar,\n layout.body as unknown as import(\"@unblessed/node\").Box,\n screen,\n () => screenCtx.requestRender(),\n () => screenCtx.renderNow(),\n );\n\n // Create block renderer\n const blockRenderer = new BlockRenderer(\n layout.body,\n () => screenCtx.requestRender(),\n );\n\n const app = new TUIApp(screenCtx, layout, statusBar, inputHandler, blockRenderer);\n\n // Set up keyboard handlers\n app.setupKeyHandlers(screen);\n\n // Wire up Ctrl+C from input handler to same quit logic\n inputHandler.onCtrlC(() => app.handleCtrlC());\n\n // Wire up Ctrl+B from input handler to toggle focus mode\n inputHandler.onCtrlB(() => app.toggleFocusMode());\n\n // Set up block navigation keys (pass focus mode getter)\n setupBlockNavigationKeys(\n screen,\n {\n onSelectNext: () => blockRenderer.selectNext(),\n onSelectPrevious: () => blockRenderer.selectPrevious(),\n onToggleExpand: () => blockRenderer.toggleExpand(),\n onCollapse: () => blockRenderer.collapseOrDeselect(),\n onSelectFirst: () => blockRenderer.selectFirst(),\n onSelectLast: () => {\n blockRenderer.selectLast();\n blockRenderer.enableFollowMode(); // Re-enable follow mode when jumping to end\n },\n onShowRawRequest: () => app.showRawViewer(\"request\"),\n onShowRawResponse: () => app.showRawViewer(\"response\"),\n },\n () => app.focusMode,\n );\n\n // Wire scroll event to detect user scrolling (for smart follow mode)\n layout.body.on(\"scroll\", () => {\n blockRenderer.handleUserScroll();\n });\n\n // Wire resize event to recalculate bottom alignment\n screen.on(\"resize\", () => {\n blockRenderer.handleResize();\n });\n\n // Initialize in browse mode (input bar hidden)\n app.applyFocusMode();\n\n // Initial render\n screenCtx.requestRender();\n\n return app;\n }\n\n /**\n * Set up keyboard event handlers.\n */\n private setupKeyHandlers(screen: Screen): void {\n // ESC to cancel current operation\n screen.key([\"escape\"], () => {\n if (this.inputHandler.hasPendingInput()) {\n // Don't cancel input - let user continue typing\n return;\n }\n\n // Check if a block is selected and expanded\n const selected = this.blockRenderer.getSelectedBlock();\n if (selected?.expanded) {\n // Let the block navigation handler deal with collapse\n return;\n }\n\n // Cancel current operation (streaming, etc.)\n if (this.onCancelCallback) {\n this.onCancelCallback();\n }\n\n // Abort if controller exists\n if (this.abortController && !this.abortController.signal.aborted) {\n this.abortController.abort();\n }\n });\n\n // Ctrl+C for quit (double-press)\n screen.key([\"C-c\"], () => {\n this.handleCtrlC();\n });\n\n // Ctrl+B to toggle focus mode (browse <-> input)\n screen.key([\"C-b\"], () => {\n this.toggleFocusMode();\n });\n }\n\n /**\n * Handle Ctrl+C keypress (double-press to quit).\n * This is public so it can be called from InputHandler.\n */\n handleCtrlC(): void {\n const now = Date.now();\n\n if (now - this.lastCtrlC < CTRL_C_WINDOW_MS) {\n // Second press within window - quit\n if (this.onQuitCallback) {\n this.onQuitCallback();\n }\n this.destroy();\n process.exit(130);\n } else {\n // First press - show hint and record time\n this.lastCtrlC = now;\n this.showHint(\"Press Ctrl+C again to quit\");\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Focus Mode Management\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Toggle between browse and input modes.\n * Called by Tab key handler.\n */\n toggleFocusMode(): void {\n this.focusMode = this.focusMode === \"browse\" ? \"input\" : \"browse\";\n this.applyFocusMode();\n }\n\n /**\n * Set focus mode programmatically.\n * Used by AskUser to force input mode.\n */\n setFocusMode(mode: FocusMode): void {\n if (this.focusMode !== mode) {\n this.focusMode = mode;\n this.applyFocusMode();\n }\n }\n\n /**\n * Apply current focus mode to UI components.\n * - Browse mode: Hide input bar, body takes full space minus status bar\n * - Input mode: Show input bar, body shrinks to make room\n */\n private applyFocusMode(): void {\n // Update status bar FIRST (before input gets focus, which may affect event processing)\n this.statusBar.setFocusMode(this.focusMode);\n\n // Update layout\n if (this.focusMode === \"input\") {\n // Input mode: show input bar, body height = 100%-2\n this.layout.body.height = \"100%-2\";\n } else {\n // Browse mode: hide input bar, body height = 100%-1\n this.layout.body.height = \"100%-1\";\n }\n\n // Render the layout changes\n this.screenCtx.renderNow();\n\n // Now activate/deactivate input handler (this changes focus)\n if (this.focusMode === \"input\") {\n this.inputHandler.activate();\n } else {\n this.inputHandler.deactivate();\n }\n }\n\n /**\n * Handle an agent stream event.\n * Converts events to interactive block operations.\n *\n * When tree subscription is active, only handles text events.\n * Gadgets and subagent events are handled automatically by tree.\n */\n handleEvent(event: StreamEvent): void {\n switch (event.type) {\n case \"text\":\n // Text flows as non-selectable content (tree doesn't track text)\n this.blockRenderer.addText(event.content);\n break;\n\n case \"gadget_call\": {\n // Tree handles gadget creation when subscribed\n if (this.blockRenderer.isTreeSubscribed()) break;\n\n // Legacy path: create gadget block as child of current LLM call\n const gadgetId = this.blockRenderer.addGadget(\n event.call.invocationId,\n event.call.gadgetName,\n event.call.parameters,\n );\n this.gadgetIdMap.set(event.call.invocationId, gadgetId);\n // Track in status bar\n this.statusBar.startGadget(event.call.gadgetName);\n break;\n }\n\n case \"gadget_result\":\n // Tree handles gadget completion when subscribed\n if (this.blockRenderer.isTreeSubscribed()) break;\n\n // Legacy path: complete the gadget block\n this.blockRenderer.completeGadget(\n event.result.invocationId,\n event.result.result,\n event.result.error,\n event.result.executionTimeMs,\n event.result.cost,\n );\n // Remove from status bar\n this.statusBar.endGadget(event.result.gadgetName);\n break;\n\n case \"subagent_event\":\n // Tree handles nested events automatically via parent-child relationships\n if (this.blockRenderer.isTreeSubscribed()) break;\n\n // Legacy path: handle nested events within gadgets\n this.handleSubagentEvent(event.subagentEvent);\n break;\n\n case \"stream_complete\":\n // Nothing special needed for blocks\n break;\n\n case \"human_input_required\":\n // Handled by InputHandler, not here\n break;\n\n default:\n // Other events (gadget_skipped, compaction, etc.)\n break;\n }\n }\n\n /**\n * Handle subagent events (nested LLM calls and gadgets within gadgets).\n */\n private handleSubagentEvent(subEvent: SubagentEvent): void {\n // Find the parent gadget block\n const parentGadgetId = this.gadgetIdMap.get(subEvent.gadgetInvocationId);\n if (!parentGadgetId) return;\n\n switch (subEvent.type) {\n case \"llm_call_start\": {\n // Create nested LLM call as child of the gadget\n const info = subEvent.event as import(\"../../gadgets/types.js\").LLMCallInfo;\n // Unique key: gadgetInvocationId + iteration (uses raw iteration for tracking)\n const key = `${subEvent.gadgetInvocationId}_${info.iteration}`;\n\n // Deduplicate: skip if we already have this subagent LLM call\n if (this.subagentLLMCallMap.has(key)) {\n break;\n }\n\n const llmCallId = this.blockRenderer.addLLMCall(\n info.iteration + 1, // Display as 1-indexed (consistent with main agent)\n info.model,\n parentGadgetId, // Parent is the gadget\n );\n this.subagentLLMCallMap.set(key, llmCallId);\n // Track in status bar with subagent label\n const subLabel = `#${this.currentIteration}.${info.iteration + 1}`;\n this.statusBar.startLLMCall(subLabel, info.model);\n break;\n }\n\n case \"llm_call_end\": {\n const info = subEvent.event as import(\"../../gadgets/types.js\").LLMCallInfo;\n const key = `${subEvent.gadgetInvocationId}_${info.iteration}`;\n const llmCallId = this.subagentLLMCallMap.get(key);\n if (llmCallId) {\n this.blockRenderer.completeLLMCall(llmCallId, {\n inputTokens: info.usage?.inputTokens ?? info.inputTokens,\n cachedInputTokens: info.usage?.cachedInputTokens,\n outputTokens: info.usage?.outputTokens ?? info.outputTokens,\n elapsedSeconds: info.elapsedMs ? info.elapsedMs / 1000 : undefined,\n cost: info.cost,\n finishReason: info.finishReason ?? undefined,\n });\n // Remove from status bar\n const subLabel = `#${this.currentIteration}.${info.iteration + 1}`;\n this.statusBar.endLLMCall(subLabel);\n // Accumulate subagent LLM call cost in status bar\n if (info.cost && info.cost > 0) {\n this.statusBar.addGadgetCost(info.cost);\n }\n }\n break;\n }\n\n case \"gadget_call\": {\n // Subagent gadget call - create as child of the subagent's LLM call\n const gadgetEvent = subEvent.event as { call?: { gadgetName: string; parameters: Record<string, unknown>; invocationId: string } };\n if (gadgetEvent.call) {\n // Deduplicate: skip if we already have this gadget\n if (this.gadgetIdMap.has(gadgetEvent.call.invocationId)) {\n break;\n }\n\n // Set correct LLM call context for parenting\n // Use the iteration from subagent event to find the correct subagent LLM call\n if (subEvent.iteration !== undefined) {\n const key = `${subEvent.gadgetInvocationId}_${subEvent.iteration}`;\n const subagentLLMCallId = this.subagentLLMCallMap.get(key);\n if (subagentLLMCallId) {\n this.blockRenderer.setCurrentLLMCall(subagentLLMCallId);\n }\n }\n\n const gadgetId = this.blockRenderer.addGadget(\n gadgetEvent.call.invocationId,\n gadgetEvent.call.gadgetName,\n gadgetEvent.call.parameters,\n );\n this.gadgetIdMap.set(gadgetEvent.call.invocationId, gadgetId);\n // Track in status bar\n this.statusBar.startGadget(gadgetEvent.call.gadgetName);\n }\n break;\n }\n\n case \"gadget_result\": {\n const gadgetEvent = subEvent.event as { result?: { invocationId: string; gadgetName?: string; executionTimeMs?: number; error?: string; result?: string; cost?: number } };\n if (gadgetEvent.result) {\n this.blockRenderer.completeGadget(\n gadgetEvent.result.invocationId,\n gadgetEvent.result.result,\n gadgetEvent.result.error,\n gadgetEvent.result.executionTimeMs,\n gadgetEvent.result.cost,\n );\n // Remove from status bar\n if (gadgetEvent.result.gadgetName) {\n this.statusBar.endGadget(gadgetEvent.result.gadgetName);\n }\n // Track subagent gadget cost\n if (gadgetEvent.result.cost && gadgetEvent.result.cost > 0) {\n this.statusBar.addGadgetCost(gadgetEvent.result.cost);\n }\n }\n break;\n }\n }\n }\n\n /**\n * Show an LLM call starting.\n * @param iteration - Current iteration number\n * @param model - Model name\n * @param estimatedInputTokens - Estimated input tokens for real-time display\n */\n showLLMCallStart(iteration: number, _model: string, _estimatedInputTokens = 0): void {\n // Tree subscription handles block creation and activity tracking via handleTreeEvent\n // We only track IDs for raw response attachment in raw viewer\n this.currentIteration = iteration;\n this.currentLLMCallId = this.blockRenderer.getCurrentLLMCallId();\n }\n\n /**\n * Update streaming token estimates (call during streaming).\n * @param estimatedOutputTokens - Estimated output tokens so far\n */\n updateStreamingTokens(estimatedOutputTokens: number): void {\n this.statusBar.updateStreaming(estimatedOutputTokens);\n }\n\n /**\n * Show an LLM call completion.\n */\n showLLMCallComplete(info: LLMCallDisplayInfo & { rawResponse?: string }): void {\n // Skip when tree subscription is active - tree handles raw data correctly\n // using proper block IDs. Hook-based path uses stale currentLLMCallId.\n if (this.blockRenderer.isTreeSubscribed()) return;\n\n if (this.currentLLMCallId && info.rawResponse) {\n this.blockRenderer.setLLMCallResponse(this.currentLLMCallId, info.rawResponse);\n }\n }\n\n /**\n * Store raw request messages for the current LLM call.\n * Called from onLLMCallReady hook after controller modifications.\n */\n setLLMCallRequest(messages: LLMMessage[]): void {\n // Skip when tree subscription is active - tree handles raw data correctly\n // using proper block IDs. Hook-based path uses stale currentLLMCallId.\n if (this.blockRenderer.isTreeSubscribed()) return;\n\n if (this.currentLLMCallId) {\n this.blockRenderer.setLLMCallRequest(this.currentLLMCallId, messages);\n }\n }\n\n /**\n * Show raw request or response viewer for selected LLM call or gadget.\n * Only works in browse mode when an LLM call or gadget is selected.\n * If a viewer is already open, closes it first (single-instance modal).\n *\n * For LLM calls: shows raw request messages / raw response text\n * For gadgets: shows raw parameters / raw result\n */\n async showRawViewer(mode: RawViewerMode): Promise<void> {\n if (this.focusMode !== \"browse\") return;\n\n const selected = this.blockRenderer.getSelectedBlock();\n if (!selected) return;\n\n // Close any existing viewer first (single-instance modal pattern)\n if (this.closeRawViewer) {\n this.closeRawViewer();\n this.closeRawViewer = null;\n }\n\n let handle: import(\"./raw-viewer.js\").RawViewerHandle;\n\n if (selected.node.type === \"llm_call\") {\n // LLM call viewer\n const node = selected.node as import(\"./types.js\").LLMCallNode;\n handle = showRawViewer({\n screen: this.screenCtx.screen,\n mode,\n request: node.rawRequest,\n response: node.rawResponse,\n iteration: node.iteration,\n model: node.model,\n });\n } else if (selected.node.type === \"gadget\") {\n // Gadget viewer\n const node = selected.node as import(\"./types.js\").GadgetNode;\n handle = showRawViewer({\n screen: this.screenCtx.screen,\n mode,\n gadgetName: node.name,\n parameters: node.parameters,\n result: node.result,\n error: node.error,\n });\n } else {\n // Unsupported node type\n return;\n }\n\n // Store close function for potential replacement\n this.closeRawViewer = handle.close;\n\n // Wait for viewer to close and clear the reference\n await handle.closed;\n this.closeRawViewer = null;\n }\n\n /**\n * Request user input for AskUser gadget.\n * Auto-activates input mode and restores browse mode after.\n */\n async waitForInput(question: string, gadgetName: string): Promise<string> {\n // Force input mode for AskUser\n const previousMode = this.focusMode;\n this.setFocusMode(\"input\");\n\n try {\n const result = await this.inputHandler.waitForInput(question, gadgetName);\n return result;\n } finally {\n // Restore previous mode after input\n this.setFocusMode(previousMode);\n }\n }\n\n /**\n * Wait for user to enter a new prompt (REPL mode).\n * Used between agent runs to get the next user prompt.\n * Stays in current mode (browse) - user can Tab to input or Enter to start typing.\n */\n async waitForPrompt(): Promise<string> {\n // Don't force input mode - let user review output in browse mode first\n // User can press Tab to switch to input mode, or Enter to start typing\n const result = await this.inputHandler.waitForPrompt();\n // Return to browse mode after prompt is entered (in case user was in input mode)\n this.setFocusMode(\"browse\");\n return result;\n }\n\n /**\n * Show approval dialog for gadget execution.\n */\n async showApproval(context: ApprovalContext): Promise<ApprovalResponse> {\n return showApprovalDialog(this.screenCtx.screen, context);\n }\n\n /**\n * Add cost from gadget execution.\n */\n addGadgetCost(cost: number): void {\n this.statusBar.addGadgetCost(cost);\n }\n\n /** Unsubscribe function for tree subscription */\n private treeUnsubscribe: (() => void) | null = null;\n\n /**\n * Subscribe to an ExecutionTree for automatic block updates.\n *\n * When subscribed, blocks for LLM calls and gadgets are automatically\n * created and updated based on tree events. This eliminates the need\n * to manually handle subagent events via handleEvent().\n *\n * The subscription is automatically cleaned up when destroy() is called.\n *\n * @param tree - The ExecutionTree from agent.getTree()\n * @returns Unsubscribe function\n *\n * @example\n * ```typescript\n * const agent = builder.ask(\"Hello\");\n * tui.subscribeToTree(agent.getTree());\n *\n * for await (const event of agent.run()) {\n * // LLM/gadget blocks are auto-managed via tree subscription\n * // Only handle text events manually\n * if (event.type === \"text\") {\n * tui.handleEvent(event);\n * }\n * }\n * ```\n */\n subscribeToTree(tree: ExecutionTree): () => void {\n // Unsubscribe from previous tree\n if (this.treeUnsubscribe) {\n this.treeUnsubscribe();\n }\n\n // Subscribe block renderer to tree (for block creation)\n const unsubBlock = this.blockRenderer.subscribeToTree(tree);\n\n // Subscribe status bar to tree (for activity tracking)\n const unsubStatus = this.statusBar.subscribeToTree(tree);\n\n // Combined unsubscribe\n this.treeUnsubscribe = () => {\n unsubBlock();\n unsubStatus();\n };\n\n return () => {\n if (this.treeUnsubscribe) {\n this.treeUnsubscribe();\n this.treeUnsubscribe = null;\n }\n };\n }\n\n /**\n * Get the abort signal for cancellation support.\n */\n getAbortSignal(): AbortSignal {\n if (!this.abortController) {\n this.abortController = new AbortController();\n }\n return this.abortController.signal;\n }\n\n /**\n * Reset the abort controller for a new agent run.\n * Called at the start of each REPL iteration.\n */\n resetAbort(): void {\n this.abortController = new AbortController();\n }\n\n /**\n * Check if aborted.\n */\n isAborted(): boolean {\n return this.abortController?.signal.aborted ?? false;\n }\n\n /**\n * Set callback for quit events.\n */\n onQuit(callback: () => void): void {\n this.onQuitCallback = callback;\n }\n\n /**\n * Set callback for cancel events (ESC).\n */\n onCancel(callback: () => void): void {\n this.onCancelCallback = callback;\n }\n\n /**\n * Show a temporary hint in the body.\n */\n private showHint(message: string): void {\n this.blockRenderer.addText(`\\n[${message}]\\n`);\n }\n\n /**\n * Get current metrics from status bar.\n */\n getMetrics() {\n return this.statusBar.getMetrics();\n }\n\n /**\n * Get elapsed session time in seconds.\n */\n getElapsedSeconds(): number {\n return this.statusBar.getElapsedSeconds();\n }\n\n /**\n * Flush any buffered text (no-op for block-based rendering).\n */\n flushText(): void {\n // Block-based rendering doesn't buffer text\n // Also clear activity tracking when agent run completes\n this.statusBar.clearActivity();\n }\n\n /**\n * Clean up and restore terminal.\n */\n destroy(): void {\n // Unsubscribe from tree events\n if (this.treeUnsubscribe) {\n this.treeUnsubscribe();\n this.treeUnsubscribe = null;\n }\n\n // Cancel any pending input\n this.inputHandler.cancelPending();\n\n // Destroy screen (restores terminal)\n this.screenCtx.destroy();\n }\n}\n\n// Re-export types for convenience\nexport type { TUIOptions, ApprovalContext, ApprovalResponse } from \"./types.js\";\n\n// Re-export utilities\nexport { StatusBar } from \"./status-bar.js\";\n","import type { Command } from \"commander\";\n\nimport type { ContentPart } from \"../core/input-content.js\";\nimport { text } from \"../core/input-content.js\";\nimport { LLMMessageBuilder } from \"../core/messages.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { TokenUsage } from \"../core/options.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"../providers/constants.js\";\nimport type { CompleteConfig } from \"./config.js\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { readAudioFile, readImageFile } from \"./file-utils.js\";\nimport { createSessionDir, formatLlmRequest, resolveLogDir, writeLogFile } from \"./llm-logging.js\";\nimport { addCompleteOptions, type CLICompleteOptions } from \"./option-helpers.js\";\nimport {\n executeAction,\n renderSummary,\n resolvePrompt,\n StreamPrinter,\n StreamProgress,\n} from \"./utils.js\";\n\n/**\n * Executes the complete command.\n * Streams a single LLM response without agent loop or gadgets.\n *\n * @param promptArg - User prompt from command line argument (optional if using stdin)\n * @param options - Complete command options (model, system prompt, temperature, etc.)\n * @param env - CLI environment for I/O operations\n */\nexport async function executeComplete(\n promptArg: string | undefined,\n options: CLICompleteOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const prompt = await resolvePrompt(promptArg, env);\n const client = env.createClient();\n const model = resolveModel(options.model);\n\n const builder = new LLMMessageBuilder();\n if (options.system) {\n builder.addSystem(options.system);\n }\n\n // Build multimodal message if --image or --audio flags are present\n if (options.image || options.audio) {\n const parts: ContentPart[] = [text(prompt)];\n\n if (options.image) {\n parts.push(await readImageFile(options.image));\n }\n if (options.audio) {\n parts.push(await readAudioFile(options.audio));\n }\n\n builder.addUserMultimodal(parts);\n } else {\n builder.addUser(prompt);\n }\n\n const messages = builder.build();\n\n // Resolve LLM debug log directory (if enabled)\n const llmLogsBaseDir = resolveLogDir(options.logLlmRequests, \"requests\");\n let llmSessionDir: string | undefined;\n\n // Log request before streaming\n if (llmLogsBaseDir) {\n llmSessionDir = await createSessionDir(llmLogsBaseDir);\n if (llmSessionDir) {\n const filename = \"0001.request\";\n const content = formatLlmRequest(messages);\n await writeLogFile(llmSessionDir, filename, content);\n }\n }\n\n const stream = client.stream({\n model,\n messages,\n temperature: options.temperature,\n maxTokens: options.maxTokens,\n });\n\n const printer = new StreamPrinter(env.stdout);\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n const progress = new StreamProgress(env.stderr, stderrTTY, client.modelRegistry);\n\n // Start call with model and estimate based on prompt length\n const estimatedInputTokens = Math.round(prompt.length / FALLBACK_CHARS_PER_TOKEN);\n progress.startCall(model, estimatedInputTokens);\n\n let finishReason: string | null | undefined;\n let usage: TokenUsage | undefined;\n let accumulatedResponse = \"\";\n\n for await (const chunk of stream) {\n // Capture actual usage from stream\n if (chunk.usage) {\n usage = chunk.usage;\n if (chunk.usage.inputTokens) {\n progress.setInputTokens(chunk.usage.inputTokens, false);\n }\n if (chunk.usage.outputTokens) {\n progress.setOutputTokens(chunk.usage.outputTokens, false);\n }\n }\n if (chunk.text) {\n progress.pause(); // Must pause to avoid stderr/stdout interleaving\n accumulatedResponse += chunk.text;\n progress.update(accumulatedResponse.length); // Update token estimate from chars\n printer.write(chunk.text);\n }\n if (chunk.finishReason !== undefined) {\n finishReason = chunk.finishReason;\n }\n }\n\n progress.endCall(usage); // Calculate cost before completing\n progress.complete();\n printer.ensureNewline();\n\n // Log response after streaming\n if (llmSessionDir) {\n const filename = \"0001.response\";\n await writeLogFile(llmSessionDir, filename, accumulatedResponse);\n }\n\n // Only show summary if stderr is a TTY (not redirected) and not in quiet mode\n if (stderrTTY && !options.quiet) {\n const summary = renderSummary({ finishReason, usage, cost: progress.getTotalCost() });\n if (summary) {\n env.stderr.write(`${summary}\\n`);\n }\n }\n}\n\n/**\n * Registers the complete command with the CLI program.\n * Configures options for model, system prompt, temperature, and max tokens.\n *\n * @param program - Commander program to register the command with\n * @param env - CLI environment for dependencies and I/O\n * @param config - Optional configuration defaults from config file\n */\nexport function registerCompleteCommand(\n program: Command,\n env: CLIEnvironment,\n config?: CompleteConfig,\n): void {\n const cmd = program\n .command(COMMANDS.complete)\n .description(\"Stream a single completion from a specified model.\")\n .argument(\"[prompt]\", \"Prompt to send to the LLM. If omitted, stdin is used when available.\");\n\n addCompleteOptions(cmd, config);\n\n cmd.action((prompt, options) =>\n executeAction(() => executeComplete(prompt, options as CLICompleteOptions, env), env),\n );\n}\n","import type { Command } from \"commander\";\nimport { existsSync, mkdirSync, writeFileSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nimport { getConfigPath } from \"./config.js\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { executeAction } from \"./utils.js\";\n\n/**\n * Options for the init command.\n * Empty for now, but structured for future extensibility (e.g., --force flag).\n */\nexport type InitCommandOptions = Record<string, never>;\n\n/**\n * Starter configuration template with helpful comments.\n * Points users to the comprehensive example for more options.\n */\nconst STARTER_CONFIG = `# ~/.llmist/cli.toml\n# llmist CLI configuration file\n#\n# This is a minimal starter config. For a comprehensive example with all options:\n# https://github.com/zbigniewsobiecki/llmist/blob/main/examples/cli.example.toml\n#\n# Key concepts:\n# - Any section can inherit from others using: inherits = \"section-name\"\n# - Prompts can use templates with Eta syntax: <%~ include(\"@prompt-name\") %>\n# - Custom sections become CLI commands: [my-command] -> llmist my-command\n\n#──────────────────────────────────────────────────────────────────────────────\n# GLOBAL OPTIONS\n# These apply to all commands. CLI flags override these settings.\n#──────────────────────────────────────────────────────────────────────────────\n[global]\n# log-level = \"info\" # silly, trace, debug, info, warn, error, fatal\n# log-file = \"/tmp/llmist.log\" # Enable file logging (JSON format)\n\n#──────────────────────────────────────────────────────────────────────────────\n# COMPLETE COMMAND DEFAULTS\n# For single LLM responses: llmist complete \"prompt\"\n# Model format: provider:model (e.g., openai:gpt-4o, anthropic:claude-sonnet-4-5)\n#──────────────────────────────────────────────────────────────────────────────\n[complete]\n# model = \"openai:gpt-4o\"\n# temperature = 0.7 # 0-2, higher = more creative\n# max-tokens = 4096 # Maximum response length\n\n#──────────────────────────────────────────────────────────────────────────────\n# AGENT COMMAND DEFAULTS\n# For tool-using agents: llmist agent \"prompt\"\n#──────────────────────────────────────────────────────────────────────────────\n[agent]\n# model = \"anthropic:claude-sonnet-4-5\"\n# max-iterations = 15 # Max tool-use loops before stopping\n# gadgets = [ # Tools the agent can use\n# \"ListDirectory\",\n# \"ReadFile\",\n# \"WriteFile\",\n# ]\n\n#──────────────────────────────────────────────────────────────────────────────\n# CUSTOM COMMANDS\n# Any other section becomes a new CLI command!\n# Uncomment below to create: llmist summarize \"your text\"\n#──────────────────────────────────────────────────────────────────────────────\n# [summarize]\n# type = \"complete\" # \"complete\" or \"agent\"\n# description = \"Summarize text concisely.\"\n# system = \"Summarize the following text in 2-3 bullet points.\"\n# temperature = 0.3\n`;\n\n/**\n * Executes the init command - creates ~/.llmist/cli.toml with a starter config.\n */\nexport async function executeInit(\n _options: InitCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const configPath = getConfigPath();\n const configDir = dirname(configPath);\n\n // Check if config already exists\n if (existsSync(configPath)) {\n env.stderr.write(`Configuration already exists at ${configPath}\\n`);\n env.stderr.write(\"\\n\");\n env.stderr.write(`To view it: cat ${configPath}\\n`);\n env.stderr.write(`To reset: rm ${configPath} && llmist init\\n`);\n return;\n }\n\n // Create directory if needed\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n\n // Write starter config\n writeFileSync(configPath, STARTER_CONFIG, \"utf-8\");\n\n // Success message with next steps\n env.stderr.write(`Created ${configPath}\\n`);\n env.stderr.write(\"\\n\");\n env.stderr.write(\"Next steps:\\n\");\n env.stderr.write(\" 1. Set your API key:\\n\");\n env.stderr.write(\" export OPENAI_API_KEY=sk-...\\n\");\n env.stderr.write(\" export ANTHROPIC_API_KEY=sk-...\\n\");\n env.stderr.write(\" export GEMINI_API_KEY=...\\n\");\n env.stderr.write(\"\\n\");\n env.stderr.write(` 2. Customize your config:\\n`);\n env.stderr.write(` $EDITOR ${configPath}\\n`);\n env.stderr.write(\"\\n\");\n env.stderr.write(\" 3. See all options:\\n\");\n env.stderr.write(\n \" https://github.com/zbigniewsobiecki/llmist/blob/main/examples/cli.example.toml\\n\",\n );\n env.stderr.write(\"\\n\");\n env.stderr.write('Try it: llmist complete \"Hello, world!\"\\n');\n}\n\n/**\n * Registers the init command with the program.\n */\nexport function registerInitCommand(program: Command, env: CLIEnvironment): void {\n program\n .command(COMMANDS.init)\n .description(\"Initialize llmist configuration at ~/.llmist/cli.toml\")\n .action((options: InitCommandOptions) => executeAction(() => executeInit(options, env), env));\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { load as parseToml } from \"js-toml\";\nimport type { SubagentConfig, SubagentConfigMap } from \"../gadgets/types.js\";\nimport type { GlobalSubagentConfig } from \"./subagent-config.js\";\n\n// Re-export subagent config types for consumers\nexport type { SubagentConfig, SubagentConfigMap } from \"../gadgets/types.js\";\nexport type { GlobalSubagentConfig } from \"./subagent-config.js\";\nimport {\n createTemplateEngine,\n hasTemplateSyntax,\n type PromptsConfig,\n resolveTemplate,\n TemplateError,\n validateEnvVars,\n validatePrompts,\n} from \"./templates.js\";\n\n// Re-export PromptsConfig for consumers\nexport type { PromptsConfig } from \"./templates.js\";\n\n/**\n * Valid log level names.\n */\nexport type LogLevel = \"silly\" | \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n\n/**\n * Gadget permission level determines how a gadget execution is handled.\n * - \"allowed\": Auto-proceed without prompting\n * - \"denied\": Auto-reject, return denial message to LLM\n * - \"approval-required\": Prompt user for approval before execution\n */\nexport type GadgetPermissionLevel = \"allowed\" | \"denied\" | \"approval-required\";\n\n/**\n * Valid gadget permission levels.\n */\nconst VALID_PERMISSION_LEVELS: GadgetPermissionLevel[] = [\"allowed\", \"denied\", \"approval-required\"];\n\n/**\n * Configuration for per-gadget permission behavior.\n * Keys are gadget names (case-insensitive), values are permission levels.\n * Special key \"*\" sets the default for unconfigured gadgets.\n */\nexport type GadgetPermissionPolicy = Record<string, GadgetPermissionLevel>;\n\n/**\n * Global CLI options that apply to all commands.\n */\nexport interface GlobalConfig {\n \"log-level\"?: LogLevel;\n \"log-file\"?: string;\n \"log-reset\"?: boolean;\n}\n\n/**\n * Shared options used by both complete and agent command configurations.\n */\nexport interface SharedCommandConfig {\n model?: string;\n system?: string;\n temperature?: number;\n inherits?: string | string[];\n}\n\n/**\n * Configuration for the complete command.\n */\nexport interface CompleteConfig extends SharedCommandConfig {\n \"max-tokens\"?: number;\n quiet?: boolean;\n \"log-level\"?: LogLevel;\n \"log-file\"?: string;\n \"log-reset\"?: boolean;\n \"log-llm-requests\"?: string | boolean;\n}\n\n/**\n * Configuration for the image command.\n */\nexport interface ImageConfig {\n model?: string;\n size?: string;\n quality?: string;\n count?: number;\n output?: string;\n quiet?: boolean;\n}\n\n/**\n * Configuration for the speech command.\n */\nexport interface SpeechConfig {\n model?: string;\n voice?: string;\n format?: string;\n speed?: number;\n output?: string;\n quiet?: boolean;\n}\n\n/**\n * Configuration for the agent command.\n */\nexport interface AgentConfig extends SharedCommandConfig {\n \"max-iterations\"?: number;\n gadgets?: string[]; // Full replacement (preferred)\n \"gadget-add\"?: string[]; // Add to inherited gadgets\n \"gadget-remove\"?: string[]; // Remove from inherited gadgets\n gadget?: string[]; // DEPRECATED: alias for gadgets\n builtins?: boolean;\n \"builtin-interaction\"?: boolean;\n \"gadget-start-prefix\"?: string;\n \"gadget-end-prefix\"?: string;\n \"gadget-arg-prefix\"?: string;\n \"gadget-approval\"?: GadgetPermissionPolicy;\n /** Per-subagent configuration overrides for this profile/command */\n subagents?: SubagentConfigMap;\n quiet?: boolean;\n \"log-level\"?: LogLevel;\n \"log-file\"?: string;\n \"log-reset\"?: boolean;\n \"log-llm-requests\"?: string | boolean;\n}\n\n/**\n * Command type determines execution behavior.\n */\nexport type CommandType = \"agent\" | \"complete\";\n\n/**\n * Custom command configuration from config file.\n * Extends both agent and complete configs, with type determining behavior.\n */\nexport interface CustomCommandConfig extends AgentConfig, CompleteConfig {\n type?: CommandType;\n description?: string;\n}\n\n/**\n * Root configuration structure matching ~/.llmist/cli.toml.\n */\nexport interface CLIConfig {\n global?: GlobalConfig;\n complete?: CompleteConfig;\n agent?: AgentConfig;\n image?: ImageConfig;\n speech?: SpeechConfig;\n prompts?: PromptsConfig;\n /** Global subagent configuration defaults */\n subagents?: GlobalSubagentConfig;\n [customCommand: string]:\n | CustomCommandConfig\n | CompleteConfig\n | AgentConfig\n | ImageConfig\n | SpeechConfig\n | GlobalConfig\n | PromptsConfig\n | GlobalSubagentConfig\n | undefined;\n}\n\n/** Valid keys for global config */\nconst GLOBAL_CONFIG_KEYS = new Set([\"log-level\", \"log-file\", \"log-reset\"]);\n\n/** Valid log levels */\nconst VALID_LOG_LEVELS: LogLevel[] = [\"silly\", \"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"];\n\n/** Valid keys for complete command config */\nconst COMPLETE_CONFIG_KEYS = new Set([\n \"model\",\n \"system\",\n \"temperature\",\n \"max-tokens\",\n \"quiet\",\n \"inherits\",\n \"log-level\",\n \"log-file\",\n \"log-reset\",\n \"log-llm-requests\",\n \"type\", // Allowed for inheritance compatibility, ignored for built-in commands\n]);\n\n/** Valid keys for agent command config */\nconst AGENT_CONFIG_KEYS = new Set([\n \"model\",\n \"system\",\n \"temperature\",\n \"max-iterations\",\n \"gadgets\", // Full replacement (preferred)\n \"gadget-add\", // Add to inherited gadgets\n \"gadget-remove\", // Remove from inherited gadgets\n \"gadget\", // DEPRECATED: alias for gadgets\n \"builtins\",\n \"builtin-interaction\",\n \"gadget-start-prefix\",\n \"gadget-end-prefix\",\n \"gadget-arg-prefix\",\n \"gadget-approval\",\n \"subagents\", // Per-subagent configuration overrides\n \"quiet\",\n \"inherits\",\n \"log-level\",\n \"log-file\",\n \"log-reset\",\n \"log-llm-requests\",\n \"type\", // Allowed for inheritance compatibility, ignored for built-in commands\n]);\n\n/** Valid keys for image command config */\nconst IMAGE_CONFIG_KEYS = new Set([\"model\", \"size\", \"quality\", \"count\", \"output\", \"quiet\"]);\n\n/** Valid keys for speech command config */\nconst SPEECH_CONFIG_KEYS = new Set([\"model\", \"voice\", \"format\", \"speed\", \"output\", \"quiet\"]);\n\n/** Valid keys for custom command config (union of complete + agent + type + description) */\nconst CUSTOM_CONFIG_KEYS = new Set([\n ...COMPLETE_CONFIG_KEYS,\n ...AGENT_CONFIG_KEYS,\n \"type\",\n \"description\",\n]);\n\n/**\n * Returns the default config file path: ~/.llmist/cli.toml\n */\nexport function getConfigPath(): string {\n return join(homedir(), \".llmist\", \"cli.toml\");\n}\n\n/**\n * Configuration validation error.\n */\nexport class ConfigError extends Error {\n constructor(\n message: string,\n public readonly path?: string,\n ) {\n super(path ? `${path}: ${message}` : message);\n this.name = \"ConfigError\";\n }\n}\n\n/**\n * Validates that a value is a string.\n */\nfunction validateString(value: unknown, key: string, section: string): string {\n if (typeof value !== \"string\") {\n throw new ConfigError(`[${section}].${key} must be a string`);\n }\n return value;\n}\n\n/**\n * Validates that a value is a number within optional bounds.\n */\nfunction validateNumber(\n value: unknown,\n key: string,\n section: string,\n opts?: { min?: number; max?: number; integer?: boolean },\n): number {\n if (typeof value !== \"number\") {\n throw new ConfigError(`[${section}].${key} must be a number`);\n }\n if (opts?.integer && !Number.isInteger(value)) {\n throw new ConfigError(`[${section}].${key} must be an integer`);\n }\n if (opts?.min !== undefined && value < opts.min) {\n throw new ConfigError(`[${section}].${key} must be >= ${opts.min}`);\n }\n if (opts?.max !== undefined && value > opts.max) {\n throw new ConfigError(`[${section}].${key} must be <= ${opts.max}`);\n }\n return value;\n}\n\n/**\n * Validates that a value is a boolean.\n */\nfunction validateBoolean(value: unknown, key: string, section: string): boolean {\n if (typeof value !== \"boolean\") {\n throw new ConfigError(`[${section}].${key} must be a boolean`);\n }\n return value;\n}\n\n/**\n * Validates that a value is an array of strings.\n */\nfunction validateStringArray(value: unknown, key: string, section: string): string[] {\n if (!Array.isArray(value)) {\n throw new ConfigError(`[${section}].${key} must be an array`);\n }\n for (let i = 0; i < value.length; i++) {\n if (typeof value[i] !== \"string\") {\n throw new ConfigError(`[${section}].${key}[${i}] must be a string`);\n }\n }\n return value as string[];\n}\n\n/**\n * Validates that a value is a string or array of strings (for inherits field).\n */\nfunction validateInherits(value: unknown, section: string): string | string[] {\n if (typeof value === \"string\") {\n return value;\n }\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n if (typeof value[i] !== \"string\") {\n throw new ConfigError(`[${section}].inherits[${i}] must be a string`);\n }\n }\n return value as string[];\n }\n throw new ConfigError(`[${section}].inherits must be a string or array of strings`);\n}\n\n/**\n * Validates a single subagent configuration.\n * Subagent configs are flexible objects with optional model and maxIterations.\n */\nfunction validateSingleSubagentConfig(\n value: unknown,\n subagentName: string,\n section: string,\n): SubagentConfig {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new ConfigError(\n `[${section}].${subagentName} must be a table (e.g., { model = \"inherit\", maxIterations = 20 })`,\n );\n }\n\n const result: SubagentConfig = {};\n const rawObj = value as Record<string, unknown>;\n\n for (const [key, val] of Object.entries(rawObj)) {\n if (key === \"model\") {\n if (typeof val !== \"string\") {\n throw new ConfigError(`[${section}].${subagentName}.model must be a string`);\n }\n result.model = val;\n } else if (key === \"maxIterations\") {\n if (typeof val !== \"number\" || !Number.isInteger(val) || val < 1) {\n throw new ConfigError(\n `[${section}].${subagentName}.maxIterations must be a positive integer`,\n );\n }\n result.maxIterations = val;\n } else {\n // Allow arbitrary additional options (headless, etc.)\n result[key] = val;\n }\n }\n\n return result;\n}\n\n/**\n * Validates a subagent configuration map (per-profile subagents).\n */\nfunction validateSubagentConfigMap(value: unknown, section: string): SubagentConfigMap {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new ConfigError(\n `[${section}].subagents must be a table (e.g., { BrowseWeb = { model = \"inherit\" } })`,\n );\n }\n\n const result: SubagentConfigMap = {};\n for (const [subagentName, config] of Object.entries(value as Record<string, unknown>)) {\n result[subagentName] = validateSingleSubagentConfig(config, subagentName, `${section}.subagents`);\n }\n return result;\n}\n\n/**\n * Validates the global [subagents] section.\n * Contains default-model and per-subagent configurations.\n */\nfunction validateGlobalSubagentConfig(value: unknown, section: string): GlobalSubagentConfig {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const result: GlobalSubagentConfig = {};\n const rawObj = value as Record<string, unknown>;\n\n for (const [key, val] of Object.entries(rawObj)) {\n if (key === \"default-model\") {\n if (typeof val !== \"string\") {\n throw new ConfigError(`[${section}].default-model must be a string`);\n }\n result[\"default-model\"] = val;\n } else {\n // Per-subagent config (nested table)\n result[key] = validateSingleSubagentConfig(val, key, section);\n }\n }\n\n return result;\n}\n\n/**\n * Validates that a value is a gadget approval config (object mapping gadget names to modes).\n */\nfunction validateGadgetApproval(value: unknown, section: string): GadgetPermissionPolicy {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new ConfigError(\n `[${section}].gadget-approval must be a table (e.g., { WriteFile = \"approval-required\" })`,\n );\n }\n\n const result: GadgetPermissionPolicy = {};\n for (const [gadgetName, mode] of Object.entries(value as Record<string, unknown>)) {\n if (typeof mode !== \"string\") {\n throw new ConfigError(`[${section}].gadget-approval.${gadgetName} must be a string`);\n }\n if (!VALID_PERMISSION_LEVELS.includes(mode as GadgetPermissionLevel)) {\n throw new ConfigError(\n `[${section}].gadget-approval.${gadgetName} must be one of: ${VALID_PERMISSION_LEVELS.join(\", \")}`,\n );\n }\n result[gadgetName] = mode as GadgetPermissionLevel;\n }\n return result;\n}\n\n/**\n * Validates and extracts logging config fields from a raw object.\n */\nfunction validateLoggingConfig(\n raw: Record<string, unknown>,\n section: string,\n): { \"log-level\"?: LogLevel; \"log-file\"?: string; \"log-reset\"?: boolean } {\n const result: { \"log-level\"?: LogLevel; \"log-file\"?: string; \"log-reset\"?: boolean } = {};\n\n if (\"log-level\" in raw) {\n const level = validateString(raw[\"log-level\"], \"log-level\", section);\n if (!VALID_LOG_LEVELS.includes(level as LogLevel)) {\n throw new ConfigError(\n `[${section}].log-level must be one of: ${VALID_LOG_LEVELS.join(\", \")}`,\n );\n }\n result[\"log-level\"] = level as LogLevel;\n }\n if (\"log-file\" in raw) {\n result[\"log-file\"] = validateString(raw[\"log-file\"], \"log-file\", section);\n }\n if (\"log-reset\" in raw) {\n result[\"log-reset\"] = validateBoolean(raw[\"log-reset\"], \"log-reset\", section);\n }\n\n return result;\n}\n\n/**\n * Validates and extracts base command config fields.\n */\nfunction validateBaseConfig(\n raw: Record<string, unknown>,\n section: string,\n): Partial<SharedCommandConfig> {\n const result: Partial<SharedCommandConfig> = {};\n\n if (\"model\" in raw) {\n result.model = validateString(raw.model, \"model\", section);\n }\n if (\"system\" in raw) {\n result.system = validateString(raw.system, \"system\", section);\n }\n if (\"temperature\" in raw) {\n result.temperature = validateNumber(raw.temperature, \"temperature\", section, {\n min: 0,\n max: 2,\n });\n }\n if (\"inherits\" in raw) {\n result.inherits = validateInherits(raw.inherits, section);\n }\n\n return result;\n}\n\n/**\n * Validates the global config section.\n */\nfunction validateGlobalConfig(raw: unknown, section: string): GlobalConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!GLOBAL_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n return validateLoggingConfig(rawObj, section);\n}\n\n/**\n * Validates a complete command config section.\n */\nfunction validateCompleteConfig(raw: unknown, section: string): CompleteConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!COMPLETE_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n const result: CompleteConfig = {\n ...validateBaseConfig(rawObj, section),\n ...validateLoggingConfig(rawObj, section),\n };\n\n if (\"max-tokens\" in rawObj) {\n result[\"max-tokens\"] = validateNumber(rawObj[\"max-tokens\"], \"max-tokens\", section, {\n integer: true,\n min: 1,\n });\n }\n if (\"quiet\" in rawObj) {\n result.quiet = validateBoolean(rawObj.quiet, \"quiet\", section);\n }\n if (\"log-llm-requests\" in rawObj) {\n result[\"log-llm-requests\"] = validateStringOrBoolean(\n rawObj[\"log-llm-requests\"],\n \"log-llm-requests\",\n section,\n );\n }\n\n return result;\n}\n\n/**\n * Validates an agent command config section.\n */\nfunction validateAgentConfig(raw: unknown, section: string): AgentConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!AGENT_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n const result: AgentConfig = {\n ...validateBaseConfig(rawObj, section),\n ...validateLoggingConfig(rawObj, section),\n };\n\n if (\"max-iterations\" in rawObj) {\n result[\"max-iterations\"] = validateNumber(rawObj[\"max-iterations\"], \"max-iterations\", section, {\n integer: true,\n min: 1,\n });\n }\n // Gadget configuration (new plural form preferred)\n if (\"gadgets\" in rawObj) {\n result.gadgets = validateStringArray(rawObj.gadgets, \"gadgets\", section);\n }\n if (\"gadget-add\" in rawObj) {\n result[\"gadget-add\"] = validateStringArray(rawObj[\"gadget-add\"], \"gadget-add\", section);\n }\n if (\"gadget-remove\" in rawObj) {\n result[\"gadget-remove\"] = validateStringArray(\n rawObj[\"gadget-remove\"],\n \"gadget-remove\",\n section,\n );\n }\n // Legacy singular form (deprecated)\n if (\"gadget\" in rawObj) {\n result.gadget = validateStringArray(rawObj.gadget, \"gadget\", section);\n }\n if (\"builtins\" in rawObj) {\n result.builtins = validateBoolean(rawObj.builtins, \"builtins\", section);\n }\n if (\"builtin-interaction\" in rawObj) {\n result[\"builtin-interaction\"] = validateBoolean(\n rawObj[\"builtin-interaction\"],\n \"builtin-interaction\",\n section,\n );\n }\n if (\"gadget-start-prefix\" in rawObj) {\n result[\"gadget-start-prefix\"] = validateString(\n rawObj[\"gadget-start-prefix\"],\n \"gadget-start-prefix\",\n section,\n );\n }\n if (\"gadget-end-prefix\" in rawObj) {\n result[\"gadget-end-prefix\"] = validateString(\n rawObj[\"gadget-end-prefix\"],\n \"gadget-end-prefix\",\n section,\n );\n }\n if (\"gadget-arg-prefix\" in rawObj) {\n result[\"gadget-arg-prefix\"] = validateString(\n rawObj[\"gadget-arg-prefix\"],\n \"gadget-arg-prefix\",\n section,\n );\n }\n if (\"gadget-approval\" in rawObj) {\n result[\"gadget-approval\"] = validateGadgetApproval(rawObj[\"gadget-approval\"], section);\n }\n if (\"subagents\" in rawObj) {\n result.subagents = validateSubagentConfigMap(rawObj.subagents, section);\n }\n if (\"quiet\" in rawObj) {\n result.quiet = validateBoolean(rawObj.quiet, \"quiet\", section);\n }\n if (\"log-llm-requests\" in rawObj) {\n result[\"log-llm-requests\"] = validateStringOrBoolean(\n rawObj[\"log-llm-requests\"],\n \"log-llm-requests\",\n section,\n );\n }\n\n return result;\n}\n\n/**\n * Validates an image command config section.\n */\nfunction validateImageConfig(raw: unknown, section: string): ImageConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!IMAGE_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n const result: ImageConfig = {};\n\n if (\"model\" in rawObj) {\n result.model = validateString(rawObj.model, \"model\", section);\n }\n if (\"size\" in rawObj) {\n result.size = validateString(rawObj.size, \"size\", section);\n }\n if (\"quality\" in rawObj) {\n result.quality = validateString(rawObj.quality, \"quality\", section);\n }\n if (\"count\" in rawObj) {\n result.count = validateNumber(rawObj.count, \"count\", section, {\n integer: true,\n min: 1,\n max: 10,\n });\n }\n if (\"output\" in rawObj) {\n result.output = validateString(rawObj.output, \"output\", section);\n }\n if (\"quiet\" in rawObj) {\n result.quiet = validateBoolean(rawObj.quiet, \"quiet\", section);\n }\n\n return result;\n}\n\n/**\n * Validates a speech command config section.\n */\nfunction validateSpeechConfig(raw: unknown, section: string): SpeechConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!SPEECH_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n const result: SpeechConfig = {};\n\n if (\"model\" in rawObj) {\n result.model = validateString(rawObj.model, \"model\", section);\n }\n if (\"voice\" in rawObj) {\n result.voice = validateString(rawObj.voice, \"voice\", section);\n }\n if (\"format\" in rawObj) {\n result.format = validateString(rawObj.format, \"format\", section);\n }\n if (\"speed\" in rawObj) {\n result.speed = validateNumber(rawObj.speed, \"speed\", section, {\n min: 0.25,\n max: 4.0,\n });\n }\n if (\"output\" in rawObj) {\n result.output = validateString(rawObj.output, \"output\", section);\n }\n if (\"quiet\" in rawObj) {\n result.quiet = validateBoolean(rawObj.quiet, \"quiet\", section);\n }\n\n return result;\n}\n\n/**\n * Validates a value is either a string or boolean.\n */\nfunction validateStringOrBoolean(value: unknown, field: string, section: string): string | boolean {\n if (typeof value === \"string\" || typeof value === \"boolean\") {\n return value;\n }\n throw new ConfigError(`[${section}].${field} must be a string or boolean`);\n}\n\n/**\n * Validates a custom command config section.\n */\nfunction validateCustomConfig(raw: unknown, section: string): CustomCommandConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!CUSTOM_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n // Get the type first to validate properly\n let type: CommandType = \"agent\"; // Default\n if (\"type\" in rawObj) {\n const typeValue = validateString(rawObj.type, \"type\", section);\n if (typeValue !== \"agent\" && typeValue !== \"complete\") {\n throw new ConfigError(`[${section}].type must be \"agent\" or \"complete\"`);\n }\n type = typeValue;\n }\n\n // Validate base fields + type-specific fields\n const result: CustomCommandConfig = {\n ...validateBaseConfig(rawObj, section),\n type,\n };\n\n if (\"description\" in rawObj) {\n result.description = validateString(rawObj.description, \"description\", section);\n }\n\n // Always allow agent-specific fields (they'll be ignored for complete type)\n if (\"max-iterations\" in rawObj) {\n result[\"max-iterations\"] = validateNumber(rawObj[\"max-iterations\"], \"max-iterations\", section, {\n integer: true,\n min: 1,\n });\n }\n // Gadget configuration (new plural form preferred)\n if (\"gadgets\" in rawObj) {\n result.gadgets = validateStringArray(rawObj.gadgets, \"gadgets\", section);\n }\n if (\"gadget-add\" in rawObj) {\n result[\"gadget-add\"] = validateStringArray(rawObj[\"gadget-add\"], \"gadget-add\", section);\n }\n if (\"gadget-remove\" in rawObj) {\n result[\"gadget-remove\"] = validateStringArray(\n rawObj[\"gadget-remove\"],\n \"gadget-remove\",\n section,\n );\n }\n // Legacy singular form (deprecated)\n if (\"gadget\" in rawObj) {\n result.gadget = validateStringArray(rawObj.gadget, \"gadget\", section);\n }\n if (\"builtins\" in rawObj) {\n result.builtins = validateBoolean(rawObj.builtins, \"builtins\", section);\n }\n if (\"builtin-interaction\" in rawObj) {\n result[\"builtin-interaction\"] = validateBoolean(\n rawObj[\"builtin-interaction\"],\n \"builtin-interaction\",\n section,\n );\n }\n if (\"gadget-start-prefix\" in rawObj) {\n result[\"gadget-start-prefix\"] = validateString(\n rawObj[\"gadget-start-prefix\"],\n \"gadget-start-prefix\",\n section,\n );\n }\n if (\"gadget-end-prefix\" in rawObj) {\n result[\"gadget-end-prefix\"] = validateString(\n rawObj[\"gadget-end-prefix\"],\n \"gadget-end-prefix\",\n section,\n );\n }\n if (\"gadget-arg-prefix\" in rawObj) {\n result[\"gadget-arg-prefix\"] = validateString(\n rawObj[\"gadget-arg-prefix\"],\n \"gadget-arg-prefix\",\n section,\n );\n }\n if (\"gadget-approval\" in rawObj) {\n result[\"gadget-approval\"] = validateGadgetApproval(rawObj[\"gadget-approval\"], section);\n }\n if (\"subagents\" in rawObj) {\n result.subagents = validateSubagentConfigMap(rawObj.subagents, section);\n }\n\n // Complete-specific fields\n if (\"max-tokens\" in rawObj) {\n result[\"max-tokens\"] = validateNumber(rawObj[\"max-tokens\"], \"max-tokens\", section, {\n integer: true,\n min: 1,\n });\n }\n\n // Shared fields\n if (\"quiet\" in rawObj) {\n result.quiet = validateBoolean(rawObj.quiet, \"quiet\", section);\n }\n\n // Logging options\n Object.assign(result, validateLoggingConfig(rawObj, section));\n\n return result;\n}\n\n/**\n * Validates the prompts config section.\n * Each key must be a string (prompt name) and each value must be a string (template).\n */\nfunction validatePromptsConfig(raw: unknown, section: string): PromptsConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const result: PromptsConfig = {};\n for (const [key, value] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof value !== \"string\") {\n throw new ConfigError(`[${section}].${key} must be a string`);\n }\n result[key] = value;\n }\n return result;\n}\n\n/**\n * Validates and normalizes raw TOML object to CLIConfig.\n *\n * @throws ConfigError if validation fails\n */\nexport function validateConfig(raw: unknown, configPath?: string): CLIConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(\"Config must be a TOML table\", configPath);\n }\n\n const rawObj = raw as Record<string, unknown>;\n const result: CLIConfig = {};\n\n for (const [key, value] of Object.entries(rawObj)) {\n try {\n if (key === \"global\") {\n result.global = validateGlobalConfig(value, key);\n } else if (key === \"complete\") {\n result.complete = validateCompleteConfig(value, key);\n } else if (key === \"agent\") {\n result.agent = validateAgentConfig(value, key);\n } else if (key === \"image\") {\n result.image = validateImageConfig(value, key);\n } else if (key === \"speech\") {\n result.speech = validateSpeechConfig(value, key);\n } else if (key === \"prompts\") {\n result.prompts = validatePromptsConfig(value, key);\n } else if (key === \"subagents\") {\n result.subagents = validateGlobalSubagentConfig(value, key);\n } else {\n // Custom command section\n result[key] = validateCustomConfig(value, key);\n }\n } catch (error) {\n if (error instanceof ConfigError) {\n throw new ConfigError(error.message, configPath);\n }\n throw error;\n }\n }\n\n return result;\n}\n\n/**\n * Loads configuration from the default path (~/.llmist/cli.toml).\n * Returns empty config if file doesn't exist.\n *\n * @throws ConfigError if file exists but has invalid syntax or unknown fields\n */\nexport function loadConfig(): CLIConfig {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n return {};\n }\n\n let content: string;\n try {\n content = readFileSync(configPath, \"utf-8\");\n } catch (error) {\n throw new ConfigError(\n `Failed to read config file: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n configPath,\n );\n }\n\n let raw: unknown;\n try {\n raw = parseToml(content);\n } catch (error) {\n throw new ConfigError(\n `Invalid TOML syntax: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n configPath,\n );\n }\n\n const validated = validateConfig(raw, configPath);\n const inherited = resolveInheritance(validated, configPath);\n return resolveTemplatesInConfig(inherited, configPath);\n}\n\n/**\n * Gets list of custom command names from config (excludes built-in sections).\n */\nexport function getCustomCommandNames(config: CLIConfig): string[] {\n const reserved = new Set([\n \"global\",\n \"complete\",\n \"agent\",\n \"image\",\n \"speech\",\n \"prompts\",\n \"subagents\",\n ]);\n return Object.keys(config).filter((key) => !reserved.has(key));\n}\n\n/**\n * Resolves Eta templates in system prompts throughout the config.\n * Templates are resolved using the [prompts] section as named partials.\n *\n * @param config - Config with inheritance already resolved\n * @param configPath - Path to config file for error messages\n * @returns Config with all templates resolved in system prompts\n * @throws ConfigError if template resolution fails\n */\nexport function resolveTemplatesInConfig(config: CLIConfig, configPath?: string): CLIConfig {\n const prompts = config.prompts ?? {};\n\n // If no prompts and no templates used, return as-is\n const hasPrompts = Object.keys(prompts).length > 0;\n\n // Check if any section uses template syntax\n let hasTemplates = false;\n for (const [sectionName, section] of Object.entries(config)) {\n if (sectionName === \"global\" || sectionName === \"prompts\") continue;\n if (!section || typeof section !== \"object\") continue;\n\n const sectionObj = section as Record<string, unknown>;\n if (typeof sectionObj.system === \"string\" && hasTemplateSyntax(sectionObj.system)) {\n hasTemplates = true;\n break;\n }\n }\n\n // Also check prompts for template syntax (they may reference each other)\n for (const template of Object.values(prompts)) {\n if (hasTemplateSyntax(template)) {\n hasTemplates = true;\n break;\n }\n }\n\n // Quick return if nothing to do\n if (!hasPrompts && !hasTemplates) {\n return config;\n }\n\n // Validate all prompts compile correctly and env vars exist\n try {\n validatePrompts(prompts, configPath);\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(error.message, configPath);\n }\n throw error;\n }\n\n // Validate environment variables in all prompts\n for (const [name, template] of Object.entries(prompts)) {\n try {\n validateEnvVars(template, name, configPath);\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(error.message, configPath);\n }\n throw error;\n }\n }\n\n // Create template engine with all prompts registered\n const eta = createTemplateEngine(prompts, configPath);\n const result = { ...config };\n\n // Resolve templates in all sections with system fields\n for (const [sectionName, section] of Object.entries(config)) {\n if (sectionName === \"global\" || sectionName === \"prompts\") continue;\n if (!section || typeof section !== \"object\") continue;\n\n const sectionObj = section as Record<string, unknown>;\n if (typeof sectionObj.system === \"string\" && hasTemplateSyntax(sectionObj.system)) {\n // Validate env vars in the system prompt itself\n try {\n validateEnvVars(sectionObj.system, undefined, configPath);\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(`[${sectionName}].system: ${error.message}`, configPath);\n }\n throw error;\n }\n\n // Resolve the template\n try {\n const resolved = resolveTemplate(eta, sectionObj.system, {}, configPath);\n result[sectionName] = {\n ...sectionObj,\n system: resolved,\n };\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(`[${sectionName}].system: ${error.message}`, configPath);\n }\n throw error;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Resolves gadget configuration with inheritance support.\n * Handles gadgets (full replacement), gadget-add (append), and gadget-remove (filter).\n *\n * Resolution order:\n * 1. If `gadgets` is present (or deprecated `gadget`), use it as full replacement\n * 2. Otherwise, start with inherited gadgets and apply add/remove\n *\n * @param section - The section's own values (not yet merged)\n * @param inheritedGadgets - Gadgets from parent sections\n * @param sectionName - Name of section for error messages\n * @param configPath - Path to config file for error messages\n * @returns Resolved gadget array\n * @throws ConfigError if conflicting gadget options\n */\nfunction resolveGadgets(\n section: Record<string, unknown>,\n inheritedGadgets: string[],\n sectionName: string,\n configPath?: string,\n): string[] {\n const hasGadgets = \"gadgets\" in section;\n const hasGadgetLegacy = \"gadget\" in section;\n const hasGadgetAdd = \"gadget-add\" in section;\n const hasGadgetRemove = \"gadget-remove\" in section;\n\n // Warn on deprecated 'gadget' usage\n if (hasGadgetLegacy && !hasGadgets) {\n console.warn(\n `[config] Warning: [${sectionName}].gadget is deprecated, use 'gadgets' (plural) instead`,\n );\n }\n\n // Error if both full replacement AND add/remove\n if ((hasGadgets || hasGadgetLegacy) && (hasGadgetAdd || hasGadgetRemove)) {\n throw new ConfigError(\n `[${sectionName}] Cannot use 'gadgets' with 'gadget-add'/'gadget-remove'. ` +\n `Use either full replacement (gadgets) OR modification (gadget-add/gadget-remove).`,\n configPath,\n );\n }\n\n // Full replacement mode (new `gadgets` takes precedence over deprecated `gadget`)\n if (hasGadgets) {\n return section.gadgets as string[];\n }\n if (hasGadgetLegacy) {\n return section.gadget as string[];\n }\n\n // Modification mode: start with inherited\n let result = [...inheritedGadgets];\n\n // Apply removes first\n if (hasGadgetRemove) {\n const toRemove = new Set(section[\"gadget-remove\"] as string[]);\n result = result.filter((g) => !toRemove.has(g));\n }\n\n // Then apply adds\n if (hasGadgetAdd) {\n const toAdd = section[\"gadget-add\"] as string[];\n result.push(...toAdd);\n }\n\n return result;\n}\n\n/**\n * Resolves inheritance chains for all sections in the config.\n * Each section can specify `inherits` as a string or array of strings.\n * Resolution follows these rules:\n * - For multiple parents, later parents override earlier ones (last wins)\n * - Section's own values always override inherited values\n * - Arrays are replaced, not merged (except gadgets with add/remove support)\n * - Circular inheritance is detected and throws an error\n *\n * @param config - Validated config with possible unresolved inheritance\n * @param configPath - Path to config file for error messages\n * @returns Config with all inheritance resolved\n * @throws ConfigError if circular inheritance or unknown parent section\n */\nexport function resolveInheritance(config: CLIConfig, configPath?: string): CLIConfig {\n const resolved: Record<string, Record<string, unknown>> = {};\n const resolving = new Set<string>(); // For cycle detection\n\n function resolveSection(name: string): Record<string, unknown> {\n // Return cached if already resolved\n if (name in resolved) {\n return resolved[name];\n }\n\n // Cycle detection\n if (resolving.has(name)) {\n throw new ConfigError(`Circular inheritance detected: ${name}`, configPath);\n }\n\n const section = config[name];\n if (section === undefined || typeof section !== \"object\") {\n throw new ConfigError(`Cannot inherit from unknown section: ${name}`, configPath);\n }\n\n resolving.add(name);\n\n // Get inheritance list (normalize to array)\n const sectionObj = section as Record<string, unknown>;\n const inheritsRaw = sectionObj.inherits;\n const inheritsList: string[] = inheritsRaw\n ? Array.isArray(inheritsRaw)\n ? inheritsRaw\n : [inheritsRaw]\n : [];\n\n // Resolve all parents first (recursive), merge in order (last wins)\n let merged: Record<string, unknown> = {};\n for (const parent of inheritsList) {\n const parentResolved = resolveSection(parent);\n merged = { ...merged, ...parentResolved };\n }\n\n // Get inherited gadgets before applying own values\n const inheritedGadgets = (merged.gadgets as string[] | undefined) ?? [];\n\n // Apply own values on top (excluding metadata and gadget-related keys handled specially)\n const {\n inherits: _inherits,\n gadgets: _gadgets,\n gadget: _gadget,\n \"gadget-add\": _gadgetAdd,\n \"gadget-remove\": _gadgetRemove,\n ...ownValues\n } = sectionObj;\n merged = { ...merged, ...ownValues };\n\n // Resolve gadgets with add/remove support\n const resolvedGadgets = resolveGadgets(sectionObj, inheritedGadgets, name, configPath);\n if (resolvedGadgets.length > 0) {\n merged.gadgets = resolvedGadgets;\n }\n\n // Clean up legacy/modification fields from output\n delete merged[\"gadget\"];\n delete merged[\"gadget-add\"];\n delete merged[\"gadget-remove\"];\n\n resolving.delete(name);\n resolved[name] = merged;\n return merged;\n }\n\n // Resolve all sections\n for (const name of Object.keys(config)) {\n resolveSection(name);\n }\n\n return resolved as unknown as CLIConfig;\n}\n","import { Eta } from \"eta\";\n\n/**\n * Configuration for reusable prompt templates.\n * Each key is a prompt name, value is the template string.\n */\nexport interface PromptsConfig {\n [name: string]: string;\n}\n\n/**\n * Error thrown when template processing fails.\n */\nexport class TemplateError extends Error {\n constructor(\n message: string,\n public readonly promptName?: string,\n public readonly configPath?: string,\n ) {\n super(promptName ? `[prompts.${promptName}]: ${message}` : message);\n this.name = \"TemplateError\";\n }\n}\n\n/**\n * Creates an Eta instance configured with prompts as named templates.\n * Templates are registered with an @ prefix (e.g., @base-assistant).\n *\n * @param prompts - Map of prompt names to template strings\n * @param configPath - Path to config file for error messages\n * @returns Configured Eta instance\n * @throws TemplateError if a template has invalid syntax\n */\nexport function createTemplateEngine(prompts: PromptsConfig, configPath?: string): Eta {\n const eta = new Eta({\n views: \"/\", // Required but we use named templates\n autoEscape: false, // Don't escape - these are prompts, not HTML\n autoTrim: false, // Preserve whitespace in prompts\n });\n\n // Register all prompts as named templates with @ prefix\n // loadTemplate parses the template and will throw on syntax errors\n for (const [name, template] of Object.entries(prompts)) {\n try {\n eta.loadTemplate(`@${name}`, template);\n } catch (error) {\n throw new TemplateError(\n error instanceof Error ? error.message : String(error),\n name,\n configPath,\n );\n }\n }\n\n return eta;\n}\n\n/**\n * Resolves a template string using the configured Eta engine.\n * Injects environment variables into the context.\n *\n * @param eta - Configured Eta instance\n * @param template - Template string to resolve\n * @param context - Additional context variables\n * @param configPath - Path to config file for error messages\n * @returns Resolved template string\n */\nexport function resolveTemplate(\n eta: Eta,\n template: string,\n context: Record<string, unknown> = {},\n configPath?: string,\n): string {\n try {\n // Merge env vars and built-in variables into context\n const fullContext = {\n ...context,\n env: process.env,\n date: new Date().toISOString().split(\"T\")[0], // \"2025-12-01\"\n };\n return eta.renderString(template, fullContext);\n } catch (error) {\n throw new TemplateError(\n error instanceof Error ? error.message : String(error),\n undefined,\n configPath,\n );\n }\n}\n\n/**\n * Validates that all prompts can be compiled and references exist.\n * This is called at config load time to fail fast on errors.\n *\n * @param prompts - Map of prompt names to template strings\n * @param configPath - Path to config file for error messages\n * @throws TemplateError if validation fails\n */\nexport function validatePrompts(prompts: PromptsConfig, configPath?: string): void {\n // createTemplateEngine will throw TemplateError on syntax errors during loadTemplate\n const eta = createTemplateEngine(prompts, configPath);\n\n // Also try to render each template to catch missing includes\n for (const [name, template] of Object.entries(prompts)) {\n try {\n // Try to render with empty context to catch missing includes\n // (references to undefined prompts)\n eta.renderString(template, { env: {} });\n } catch (error) {\n throw new TemplateError(\n error instanceof Error ? error.message : String(error),\n name,\n configPath,\n );\n }\n }\n}\n\n/**\n * Validates that all environment variables referenced in a template are defined.\n *\n * @param template - Template string to check\n * @param promptName - Name of the prompt for error messages\n * @param configPath - Path to config file for error messages\n * @throws TemplateError if an undefined env var is referenced\n */\nexport function validateEnvVars(template: string, promptName?: string, configPath?: string): void {\n // Match <%= it.env.VAR_NAME %> patterns\n const envVarPattern = /<%=\\s*it\\.env\\.(\\w+)\\s*%>/g;\n const matches = template.matchAll(envVarPattern);\n\n for (const match of matches) {\n const varName = match[1] as string;\n if (process.env[varName] === undefined) {\n throw new TemplateError(\n `Environment variable '${varName}' is not set`,\n promptName,\n configPath,\n );\n }\n }\n}\n\n/**\n * Checks if a string contains Eta template syntax.\n * Used to determine if a system prompt needs template resolution.\n *\n * @param str - String to check\n * @returns true if the string contains template syntax\n */\nexport function hasTemplateSyntax(str: string): boolean {\n return str.includes(\"<%\");\n}\n","import readline from \"node:readline\";\nimport chalk from \"chalk\";\nimport type { ILogObj, Logger } from \"tslog\";\nimport { LLMist } from \"../core/client.js\";\nimport type { LoggerOptions } from \"../logging/logger.js\";\nimport { createLogger } from \"../logging/logger.js\";\n\n/**\n * Stream type that may have TTY detection capability.\n */\nexport type TTYAwareStream = NodeJS.ReadableStream & { isTTY?: boolean };\n\n/**\n * Logger configuration for CLI commands.\n */\nexport interface CLILoggerConfig {\n logLevel?: string;\n logFile?: string;\n logReset?: boolean;\n}\n\n/**\n * Environment abstraction for CLI dependencies and I/O.\n * Allows dependency injection for testing.\n */\nexport interface CLIEnvironment {\n argv: string[];\n stdin: TTYAwareStream;\n stdout: NodeJS.WritableStream;\n stderr: NodeJS.WritableStream;\n createClient: () => LLMist;\n setExitCode: (code: number) => void;\n loggerConfig?: CLILoggerConfig;\n createLogger: (name: string) => Logger<ILogObj>;\n /** Whether stdin is a TTY (interactive terminal) */\n isTTY: boolean;\n /** Prompt the user for input (only works when isTTY is true) */\n prompt: (question: string) => Promise<string>;\n}\n\nconst LOG_LEVEL_MAP: Record<string, number> = {\n silly: 0,\n trace: 1,\n debug: 2,\n info: 3,\n warn: 4,\n error: 5,\n fatal: 6,\n};\n\n/**\n * Creates a logger factory based on CLI configuration.\n * Priority: CLI options > environment variables > defaults\n */\nexport function createLoggerFactory(config?: CLILoggerConfig): (name: string) => Logger<ILogObj> {\n return (name: string) => {\n const options: LoggerOptions = { name };\n\n // CLI --log-level takes priority over LLMIST_LOG_LEVEL env var\n if (config?.logLevel) {\n const level = config.logLevel.toLowerCase();\n if (level in LOG_LEVEL_MAP) {\n options.minLevel = LOG_LEVEL_MAP[level];\n }\n }\n\n // CLI --log-reset takes priority over LLMIST_LOG_RESET env var\n if (config?.logReset !== undefined) {\n options.logReset = config.logReset;\n }\n\n // CLI --log-file takes priority over LLMIST_LOG_FILE env var\n // When log file is set via CLI, we temporarily set the env var\n // so createLogger picks it up\n if (config?.logFile) {\n const originalLogFile = process.env.LLMIST_LOG_FILE;\n process.env.LLMIST_LOG_FILE = config.logFile;\n const logger = createLogger(options);\n // Restore original (or delete if it wasn't set)\n if (originalLogFile === undefined) {\n delete process.env.LLMIST_LOG_FILE;\n } else {\n process.env.LLMIST_LOG_FILE = originalLogFile;\n }\n return logger;\n }\n\n // If no log file, default to pretty output (not hidden)\n if (!process.env.LLMIST_LOG_FILE) {\n options.type = \"pretty\";\n }\n\n return createLogger(options);\n };\n}\n\n/**\n * Creates a readline-based prompt function for user input.\n */\nfunction createPromptFunction(\n stdin: NodeJS.ReadableStream,\n stdout: NodeJS.WritableStream,\n): (question: string) => Promise<string> {\n return (question: string) => {\n return new Promise((resolve) => {\n const rl = readline.createInterface({\n input: stdin,\n output: stdout,\n });\n // Display question with visual styling\n stdout.write(\"\\n\");\n stdout.write(`${chalk.cyan(\"─\".repeat(60))}\\n`);\n stdout.write(chalk.cyan.bold(\"🤖 Agent asks:\\n\"));\n stdout.write(`${question}\\n`);\n stdout.write(`${chalk.cyan(\"─\".repeat(60))}\\n`);\n rl.question(chalk.green.bold(\"You: \"), (answer) => {\n rl.close();\n resolve(answer);\n });\n });\n };\n}\n\n/**\n * Creates the default CLI environment using Node.js process globals.\n * Uses process.argv, process.stdin/stdout/stderr, and creates a new LLMist client.\n *\n * @param loggerConfig - Optional logger configuration from CLI options\n * @returns Default CLI environment\n */\nexport function createDefaultEnvironment(loggerConfig?: CLILoggerConfig): CLIEnvironment {\n const isTTY = Boolean(process.stdin.isTTY);\n\n return {\n argv: process.argv,\n stdin: process.stdin,\n stdout: process.stdout,\n stderr: process.stderr,\n createClient: () => new LLMist(),\n setExitCode: (code: number) => {\n process.exitCode = code;\n },\n loggerConfig,\n createLogger: createLoggerFactory(loggerConfig),\n isTTY,\n prompt: isTTY\n ? createPromptFunction(process.stdin, process.stdout)\n : async () => {\n throw new Error(\"Cannot prompt for input: stdin is not a TTY\");\n },\n };\n}\n","import type { Command } from \"commander\";\nimport { executeAgent } from \"./agent-command.js\";\nimport { executeComplete } from \"./complete-command.js\";\nimport type { CustomCommandConfig, GlobalSubagentConfig } from \"./config.js\";\nimport { type CLIEnvironment, type CLILoggerConfig, createLoggerFactory } from \"./environment.js\";\nimport {\n type CLIAgentOptions,\n addAgentOptions,\n addCompleteOptions,\n type CLICompleteOptions,\n configToAgentOptions,\n configToCompleteOptions,\n} from \"./option-helpers.js\";\nimport { executeAction } from \"./utils.js\";\n\n/**\n * Creates an environment with per-command logging config merged in.\n * If the command has logging options, creates a new environment; otherwise returns the original.\n */\nfunction createCommandEnvironment(\n baseEnv: CLIEnvironment,\n config: CustomCommandConfig,\n): CLIEnvironment {\n // Check if command has any logging overrides\n const hasLoggingConfig =\n config[\"log-level\"] !== undefined ||\n config[\"log-file\"] !== undefined ||\n config[\"log-reset\"] !== undefined;\n\n if (!hasLoggingConfig) {\n return baseEnv;\n }\n\n // Merge per-command logging config with base environment's config\n const loggerConfig: CLILoggerConfig = {\n logLevel: config[\"log-level\"] ?? baseEnv.loggerConfig?.logLevel,\n logFile: config[\"log-file\"] ?? baseEnv.loggerConfig?.logFile,\n logReset: config[\"log-reset\"] ?? baseEnv.loggerConfig?.logReset,\n };\n\n // Preserve all baseEnv properties, only override logging config\n return {\n ...baseEnv,\n loggerConfig,\n createLogger: createLoggerFactory(loggerConfig),\n };\n}\n\n/**\n * Registers a custom command from config file.\n *\n * Custom commands are defined in ~/.llmist/cli.toml as sections like [code-review].\n * Each section can specify `type = \"agent\"` (default) or `type = \"complete\"` to\n * determine the execution behavior.\n *\n * @param program - Commander program to register the command with\n * @param name - Command name (e.g., \"code-review\")\n * @param config - Command configuration from TOML file\n * @param env - CLI environment for I/O operations\n */\nexport function registerCustomCommand(\n program: Command,\n name: string,\n config: CustomCommandConfig,\n env: CLIEnvironment,\n globalSubagents?: GlobalSubagentConfig,\n): void {\n const type = config.type ?? \"agent\";\n const description = config.description ?? `Custom ${type} command`;\n\n const cmd = program\n .command(name)\n .description(description)\n .argument(\"[prompt]\", \"Prompt for the command. Falls back to stdin when available.\");\n\n if (type === \"complete\") {\n // Complete type command\n addCompleteOptions(cmd, config);\n\n cmd.action((prompt, cliOptions) => {\n // Create environment with per-command logging config\n const cmdEnv = createCommandEnvironment(env, config);\n return executeAction(async () => {\n // Config values are base, CLI options override\n const configDefaults = configToCompleteOptions(config);\n const options: CLICompleteOptions = {\n ...configDefaults,\n ...(cliOptions as Partial<CLICompleteOptions>),\n } as CLICompleteOptions;\n await executeComplete(prompt, options, cmdEnv);\n }, cmdEnv);\n });\n } else {\n // Agent type command (default)\n addAgentOptions(cmd, config);\n\n cmd.action((prompt, cliOptions) => {\n // Create environment with per-command logging config\n const cmdEnv = createCommandEnvironment(env, config);\n return executeAction(async () => {\n // Config values are base, CLI options override\n const configDefaults = configToAgentOptions(config);\n const options: CLIAgentOptions = {\n ...configDefaults,\n ...(cliOptions as Partial<CLIAgentOptions>),\n globalSubagents,\n } as CLIAgentOptions;\n await executeAgent(prompt, options, cmdEnv);\n }, cmdEnv);\n });\n }\n}\n","/**\n * CLI command for testing and inspecting gadgets outside the agent loop.\n * Provides `gadget run`, `gadget info`, and `gadget validate` subcommands.\n *\n * @module cli/gadget-command\n */\n\nimport chalk from \"chalk\";\nimport type { Command } from \"commander\";\n\nimport type { AbstractGadget } from \"../gadgets/gadget.js\";\nimport { schemaToJSONSchema } from \"../gadgets/schema-to-json.js\";\nimport { validateGadgetSchema } from \"../gadgets/schema-validator.js\";\n\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { promptForParameters, readStdinJson } from \"./gadget-prompts.js\";\nimport { loadGadgets } from \"./gadgets.js\";\nimport { executeAction } from \"./utils.js\";\n\n/**\n * Result of selecting a gadget from a file.\n */\ninterface GadgetSelection {\n gadget: AbstractGadget;\n name: string;\n}\n\n/**\n * Options for the `gadget run` subcommand.\n */\ninterface GadgetRunOptions {\n name?: string;\n json?: boolean;\n raw?: boolean;\n}\n\n/**\n * Options for the `gadget info` subcommand.\n */\ninterface GadgetInfoOptions {\n name?: string;\n json?: boolean;\n}\n\n/**\n * Loads and selects a gadget from a file.\n * - Single gadget: returns it directly\n * - Multiple gadgets without --name: throws error listing available names\n * - Multiple gadgets with --name: finds matching gadget\n *\n * @param file - Path to gadget file\n * @param nameOption - Optional gadget name for selection\n * @param cwd - Current working directory\n * @returns Selected gadget with its name\n */\nasync function selectGadget(\n file: string,\n nameOption: string | undefined,\n cwd: string,\n): Promise<GadgetSelection> {\n const gadgets = await loadGadgets([file], cwd);\n\n if (gadgets.length === 0) {\n throw new Error(\n `No gadgets found in '${file}'.\\n` + \"Ensure the file exports a Gadget class or instance.\",\n );\n }\n\n // Single gadget - return it\n if (gadgets.length === 1) {\n const gadget = gadgets[0];\n const name = gadget.name ?? gadget.constructor.name;\n return { gadget, name };\n }\n\n // Multiple gadgets - need --name selection\n const names = gadgets.map((g) => g.name ?? g.constructor.name);\n\n if (!nameOption) {\n throw new Error(\n `File '${file}' exports ${gadgets.length} gadgets.\\n` +\n `Use --name to select one:\\n` +\n names.map((n) => ` - ${n}`).join(\"\\n\"),\n );\n }\n\n // Find by name (case-sensitive)\n const found = gadgets.find((g) => (g.name ?? g.constructor.name) === nameOption);\n\n if (!found) {\n throw new Error(\n `Gadget '${nameOption}' not found in '${file}'.\\n` +\n `Available gadgets:\\n` +\n names.map((n) => ` - ${n}`).join(\"\\n\"),\n );\n }\n\n return { gadget: found, name: nameOption };\n}\n\n/**\n * Executes the `gadget run` subcommand.\n * Loads a gadget, prompts for parameters (or reads from stdin), and executes it.\n */\nasync function executeGadgetRun(\n file: string,\n options: GadgetRunOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const cwd = process.cwd();\n const { gadget, name } = await selectGadget(file, options.name, cwd);\n\n env.stderr.write(chalk.cyan.bold(`\\n🔧 Running gadget: ${name}\\n`));\n\n // Get parameters - either interactive or from stdin\n let params: Record<string, unknown>;\n\n if (env.isTTY) {\n // Interactive mode: prompt for each parameter\n params = await promptForParameters(gadget.parameterSchema, {\n stdin: env.stdin,\n stdout: env.stderr, // Prompts go to stderr to keep stdout clean\n });\n } else {\n // Non-TTY mode: read JSON from stdin\n env.stderr.write(chalk.dim(\"Reading parameters from stdin...\\n\"));\n const stdinParams = await readStdinJson(env.stdin);\n\n // Validate through Zod if schema exists\n if (gadget.parameterSchema) {\n const result = gadget.parameterSchema.safeParse(stdinParams);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid parameters:\\n${issues}`);\n }\n params = result.data as Record<string, unknown>;\n } else {\n params = stdinParams;\n }\n }\n\n env.stderr.write(chalk.dim(\"\\nExecuting...\\n\"));\n\n // Execute with timeout if configured\n const startTime = Date.now();\n let result: string;\n let cost: number | undefined;\n\n try {\n let rawResult: string | { result: string; cost?: number };\n if (gadget.timeoutMs && gadget.timeoutMs > 0) {\n rawResult = await Promise.race([\n Promise.resolve(gadget.execute(params)),\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`Gadget timed out after ${gadget.timeoutMs}ms`)),\n gadget.timeoutMs,\n ),\n ),\n ]);\n } else {\n rawResult = await Promise.resolve(gadget.execute(params));\n }\n // Normalize result: handle both string and { result, cost } return types\n result = typeof rawResult === \"string\" ? rawResult : rawResult.result;\n cost = typeof rawResult === \"object\" ? rawResult.cost : undefined;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Execution failed: ${message}`);\n }\n\n const elapsed = Date.now() - startTime;\n const costInfo = cost !== undefined && cost > 0 ? ` (Cost: $${cost.toFixed(6)})` : \"\";\n env.stderr.write(chalk.green(`\\n✓ Completed in ${elapsed}ms${costInfo}\\n\\n`));\n\n // Output result\n formatOutput(result, options, env.stdout);\n}\n\n/**\n * Formats and writes the gadget execution result to stdout.\n */\nfunction formatOutput(\n result: string,\n options: GadgetRunOptions,\n stdout: NodeJS.WritableStream,\n): void {\n // Raw mode: output as-is\n if (options.raw) {\n stdout.write(result);\n if (!result.endsWith(\"\\n\")) stdout.write(\"\\n\");\n return;\n }\n\n // JSON mode or auto-detect JSON\n if (options.json || looksLikeJson(result)) {\n try {\n const parsed = JSON.parse(result);\n stdout.write(JSON.stringify(parsed, null, 2) + \"\\n\");\n return;\n } catch {\n // Not valid JSON, output as-is\n }\n }\n\n // Default: output as-is with trailing newline\n stdout.write(result);\n if (!result.endsWith(\"\\n\")) stdout.write(\"\\n\");\n}\n\n/**\n * Checks if a string looks like JSON (starts with { or [).\n */\nfunction looksLikeJson(str: string): boolean {\n const trimmed = str.trim();\n return (\n (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) ||\n (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\"))\n );\n}\n\n/**\n * Executes the `gadget info` subcommand.\n * Displays gadget description, schema, and examples.\n */\nasync function executeGadgetInfo(\n file: string,\n options: GadgetInfoOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const cwd = process.cwd();\n const { gadget, name } = await selectGadget(file, options.name, cwd);\n\n if (options.json) {\n // JSON output for programmatic use\n const info = buildGadgetInfo(gadget, name);\n env.stdout.write(JSON.stringify(info, null, 2) + \"\\n\");\n return;\n }\n\n // Pretty-printed output\n env.stdout.write(\"\\n\");\n env.stdout.write(chalk.cyan.bold(`${name}\\n`));\n env.stdout.write(chalk.cyan(\"═\".repeat(name.length)) + \"\\n\\n\");\n\n // Description\n env.stdout.write(chalk.bold(\"Description:\\n\"));\n env.stdout.write(` ${gadget.description}\\n\\n`);\n\n // Parameters\n if (gadget.parameterSchema) {\n env.stdout.write(chalk.bold(\"Parameters:\\n\"));\n const jsonSchema = schemaToJSONSchema(gadget.parameterSchema, { target: \"draft-7\" });\n env.stdout.write(formatSchemaAsText(jsonSchema, \" \") + \"\\n\\n\");\n } else {\n env.stdout.write(chalk.dim(\"No parameters required.\\n\\n\"));\n }\n\n // Timeout\n if (gadget.timeoutMs) {\n env.stdout.write(chalk.bold(\"Timeout:\\n\"));\n env.stdout.write(` ${gadget.timeoutMs}ms\\n\\n`);\n }\n\n // Examples\n if (gadget.examples && gadget.examples.length > 0) {\n env.stdout.write(chalk.bold(\"Examples:\\n\"));\n for (const example of gadget.examples) {\n if (example.comment) {\n env.stdout.write(chalk.dim(` # ${example.comment}\\n`));\n }\n env.stdout.write(` Input: ${chalk.cyan(JSON.stringify(example.params))}\\n`);\n if (example.output !== undefined) {\n env.stdout.write(` Output: ${chalk.green(example.output)}\\n`);\n }\n env.stdout.write(\"\\n\");\n }\n }\n}\n\n/**\n * Builds a JSON-serializable info object for a gadget.\n */\nfunction buildGadgetInfo(gadget: AbstractGadget, name: string): Record<string, unknown> {\n const info: Record<string, unknown> = {\n name,\n description: gadget.description,\n };\n\n if (gadget.parameterSchema) {\n info.schema = schemaToJSONSchema(gadget.parameterSchema, { target: \"draft-7\" });\n }\n\n if (gadget.timeoutMs) {\n info.timeoutMs = gadget.timeoutMs;\n }\n\n if (gadget.examples && gadget.examples.length > 0) {\n info.examples = gadget.examples;\n }\n\n return info;\n}\n\n/**\n * Formats a JSON Schema as readable text with indentation.\n */\nfunction formatSchemaAsText(schema: Record<string, unknown>, indent = \"\"): string {\n const lines: string[] = [];\n const properties = (schema.properties || {}) as Record<string, Record<string, unknown>>;\n const required = (schema.required || []) as string[];\n\n for (const [key, prop] of Object.entries(properties)) {\n const type = prop.type as string;\n const description = prop.description as string | undefined;\n const isRequired = required.includes(key);\n const enumValues = prop.enum as string[] | undefined;\n const defaultValue = prop.default;\n\n // Build the line\n let line = `${indent}${chalk.cyan(key)}`;\n\n // Required marker\n if (isRequired) {\n line += chalk.red(\"*\");\n }\n\n // Type info\n if (type === \"array\") {\n const items = prop.items as Record<string, unknown> | undefined;\n const itemType = items?.type || \"any\";\n line += chalk.dim(` (${itemType}[])`);\n } else if (type === \"object\" && prop.properties) {\n line += chalk.dim(\" (object)\");\n } else {\n line += chalk.dim(` (${type})`);\n }\n\n // Default value\n if (defaultValue !== undefined) {\n line += chalk.dim(` [default: ${JSON.stringify(defaultValue)}]`);\n }\n\n // Description\n if (description) {\n line += `: ${description}`;\n }\n\n // Enum values\n if (enumValues) {\n line += chalk.yellow(` - one of: ${enumValues.join(\", \")}`);\n }\n\n lines.push(line);\n\n // Recurse for nested objects\n if (type === \"object\" && prop.properties) {\n lines.push(formatSchemaAsText(prop, indent + \" \"));\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Executes the `gadget validate` subcommand.\n * Checks if a file exports valid gadget(s).\n */\nasync function executeGadgetValidate(file: string, env: CLIEnvironment): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const gadgets = await loadGadgets([file], cwd);\n\n if (gadgets.length === 0) {\n throw new Error(\n \"No gadgets exported from file.\\n\" +\n \"A valid gadget must have:\\n\" +\n \" - execute() method\\n\" +\n \" - description property\\n\" +\n \" - parameterSchema (optional)\",\n );\n }\n\n // Validate each gadget's structure and schema\n const issues: string[] = [];\n\n for (const gadget of gadgets) {\n const name = gadget.name ?? gadget.constructor.name;\n\n // Check required fields\n if (!gadget.description) {\n issues.push(`${name}: Missing 'description' property.`);\n }\n\n // Validate schema if present\n if (gadget.parameterSchema) {\n try {\n validateGadgetSchema(gadget.parameterSchema, name);\n } catch (schemaError) {\n const message = schemaError instanceof Error ? schemaError.message : String(schemaError);\n issues.push(`${name}: ${message}`);\n }\n }\n\n // Check execute method\n if (typeof gadget.execute !== \"function\") {\n issues.push(`${name}: Missing 'execute()' method.`);\n }\n }\n\n if (issues.length > 0) {\n throw new Error(`Validation issues:\\n${issues.map((i) => ` - ${i}`).join(\"\\n\")}`);\n }\n\n // Success output\n env.stdout.write(chalk.green.bold(\"\\n✓ Valid\\n\\n\"));\n env.stdout.write(chalk.bold(\"Gadgets found:\\n\"));\n\n for (const gadget of gadgets) {\n const name = gadget.name ?? gadget.constructor.name;\n const schemaInfo = gadget.parameterSchema\n ? chalk.cyan(\"(with schema)\")\n : chalk.dim(\"(no schema)\");\n env.stdout.write(` ${chalk.bold(name)} ${schemaInfo}\\n`);\n env.stdout.write(chalk.dim(` ${gadget.description}\\n`));\n }\n\n env.stdout.write(\"\\n\");\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n env.stdout.write(chalk.red.bold(`\\n✗ Invalid\\n\\n`));\n env.stdout.write(`${message}\\n\\n`);\n env.setExitCode(1);\n }\n}\n\n/**\n * Registers the `gadget` command group with run/info/validate subcommands.\n *\n * @param program - Commander program to register on\n * @param env - CLI environment for I/O\n */\nexport function registerGadgetCommand(program: Command, env: CLIEnvironment): void {\n const gadgetCmd = program\n .command(\"gadget\")\n .description(\"Test and inspect gadgets outside the agent loop.\");\n\n // Subcommand: run\n gadgetCmd\n .command(\"run <file>\")\n .description(\"Execute a gadget with interactive prompts or stdin JSON.\")\n .option(\"--name <gadget>\", \"Select gadget by name (required if file exports multiple)\")\n .option(\"--json\", \"Format output as pretty-printed JSON\")\n .option(\"--raw\", \"Output result as raw string without formatting\")\n .action((file: string, options: GadgetRunOptions) =>\n executeAction(() => executeGadgetRun(file, options, env), env),\n );\n\n // Subcommand: info\n gadgetCmd\n .command(\"info <file>\")\n .description(\"Display gadget description, schema, and examples.\")\n .option(\"--name <gadget>\", \"Select gadget by name (required if file exports multiple)\")\n .option(\"--json\", \"Output as JSON instead of formatted text\")\n .action((file: string, options: GadgetInfoOptions) =>\n executeAction(() => executeGadgetInfo(file, options, env), env),\n );\n\n // Subcommand: validate\n gadgetCmd\n .command(\"validate <file>\")\n .description(\"Check if file exports valid gadget(s).\")\n .action((file: string) => executeAction(() => executeGadgetValidate(file, env), env));\n}\n","/**\n * Interactive prompts for schema-driven gadget parameter input.\n * Converts Zod schemas to JSON Schema for introspection and prompts\n * users for each parameter with type hints, descriptions, and defaults.\n *\n * @module cli/gadget-prompts\n */\n\nimport { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport type { ZodTypeAny } from \"zod\";\n\nimport { schemaToJSONSchema } from \"../gadgets/schema-to-json.js\";\n\n/**\n * Context for interactive prompting.\n */\nexport interface PromptContext {\n stdin: NodeJS.ReadableStream;\n stdout: NodeJS.WritableStream;\n}\n\n/**\n * JSON Schema property representation for a single field.\n */\ninterface JsonSchemaProperty {\n type?: string;\n description?: string;\n enum?: string[];\n default?: unknown;\n items?: { type?: string; enum?: string[] };\n properties?: Record<string, JsonSchemaProperty>;\n required?: string[];\n}\n\n/**\n * Prompts user for parameter values based on Zod schema.\n * Displays type hints, descriptions, and defaults for each field.\n * Returns validated and transformed parameters.\n *\n * @param schema - Zod schema describing expected parameters\n * @param ctx - I/O context for prompts\n * @returns Object containing user-provided parameter values\n */\nexport async function promptForParameters(\n schema: ZodTypeAny | undefined,\n ctx: PromptContext,\n): Promise<Record<string, unknown>> {\n if (!schema) {\n return {}; // No parameters required\n }\n\n const jsonSchema = schemaToJSONSchema(schema, { target: \"draft-7\" }) as {\n properties?: Record<string, JsonSchemaProperty>;\n required?: string[];\n };\n\n if (!jsonSchema.properties || Object.keys(jsonSchema.properties).length === 0) {\n return {};\n }\n\n const rl = createInterface({ input: ctx.stdin, output: ctx.stdout });\n const params: Record<string, unknown> = {};\n\n try {\n for (const [key, prop] of Object.entries(jsonSchema.properties)) {\n const value = await promptForField(rl, key, prop, jsonSchema.required ?? []);\n if (value !== undefined) {\n params[key] = value;\n }\n }\n } finally {\n rl.close();\n }\n\n // Validate and apply defaults/transforms through Zod\n const result = schema.safeParse(params);\n if (!result.success) {\n const issues = result.error.issues.map((i) => ` ${i.path.join(\".\")}: ${i.message}`).join(\"\\n\");\n throw new Error(`Invalid parameters:\\n${issues}`);\n }\n\n return result.data as Record<string, unknown>;\n}\n\n/**\n * Prompts for a single field value with type-aware formatting.\n */\nasync function promptForField(\n rl: ReturnType<typeof createInterface>,\n key: string,\n prop: JsonSchemaProperty,\n required: string[],\n): Promise<unknown> {\n const isRequired = required.includes(key);\n const typeHint = formatTypeHint(prop);\n const defaultHint =\n prop.default !== undefined ? chalk.dim(` [default: ${JSON.stringify(prop.default)}]`) : \"\";\n const requiredMarker = isRequired ? chalk.red(\"*\") : \"\";\n\n // Build prompt with description\n let prompt = `\\n${chalk.cyan.bold(key)}${requiredMarker}`;\n if (prop.description) {\n prompt += chalk.dim(` - ${prop.description}`);\n }\n prompt += `\\n ${typeHint}${defaultHint}\\n ${chalk.green(\">\")} `;\n\n const answer = await rl.question(prompt);\n const trimmed = answer.trim();\n\n // Handle empty input\n if (!trimmed) {\n if (prop.default !== undefined) {\n return undefined; // Let Zod apply default\n }\n if (!isRequired) {\n return undefined; // Optional field, skip\n }\n throw new Error(`Parameter '${key}' is required.`);\n }\n\n // Parse based on type\n return parseValue(trimmed, prop, key);\n}\n\n/**\n * Formats the type hint for display (e.g., \"(number)\", \"(add | subtract)\").\n */\nfunction formatTypeHint(prop: JsonSchemaProperty): string {\n // Enum types: show allowed values\n if (prop.enum) {\n return chalk.yellow(`(${prop.enum.join(\" | \")})`);\n }\n\n // Array types: show item type\n if (prop.type === \"array\") {\n const items = prop.items;\n if (items?.enum) {\n return chalk.yellow(`(${items.enum.join(\" | \")})[] comma-separated`);\n }\n const itemType = items?.type ?? \"any\";\n return chalk.yellow(`(${itemType}[]) comma-separated`);\n }\n\n // Object types: indicate nested structure\n if (prop.type === \"object\" && prop.properties) {\n return chalk.yellow(\"(object) enter as JSON\");\n }\n\n // Simple types\n return chalk.yellow(`(${prop.type ?? \"any\"})`);\n}\n\n/**\n * Parses a string value into the appropriate type based on schema.\n */\nfunction parseValue(input: string, prop: JsonSchemaProperty, key: string): unknown {\n const type = prop.type;\n\n // Numbers\n if (type === \"number\" || type === \"integer\") {\n const num = Number(input);\n if (Number.isNaN(num)) {\n throw new Error(`Invalid number for '${key}': ${input}`);\n }\n if (type === \"integer\" && !Number.isInteger(num)) {\n throw new Error(`Expected integer for '${key}', got: ${input}`);\n }\n return num;\n }\n\n // Booleans\n if (type === \"boolean\") {\n const lower = input.toLowerCase();\n if ([\"true\", \"yes\", \"1\", \"y\"].includes(lower)) return true;\n if ([\"false\", \"no\", \"0\", \"n\"].includes(lower)) return false;\n throw new Error(`Invalid boolean for '${key}': ${input} (use true/false, yes/no, 1/0)`);\n }\n\n // Arrays (comma-separated)\n if (type === \"array\") {\n const items = input\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n const itemType = prop.items?.type;\n\n // Convert array items to appropriate type\n if (itemType === \"number\" || itemType === \"integer\") {\n return items.map((item) => {\n const num = Number(item);\n if (Number.isNaN(num)) throw new Error(`Invalid number in '${key}' array: ${item}`);\n return num;\n });\n }\n if (itemType === \"boolean\") {\n return items.map((item) => {\n const lower = item.toLowerCase();\n if ([\"true\", \"yes\", \"1\", \"y\"].includes(lower)) return true;\n if ([\"false\", \"no\", \"0\", \"n\"].includes(lower)) return false;\n throw new Error(`Invalid boolean in '${key}' array: ${item}`);\n });\n }\n return items; // String array\n }\n\n // Objects (parse as JSON)\n if (type === \"object\") {\n try {\n return JSON.parse(input);\n } catch {\n throw new Error(`Invalid JSON for '${key}': ${input}`);\n }\n }\n\n // String (default) - also handles enums which are validated by Zod\n return input;\n}\n\n/**\n * Reads JSON parameters from stdin (for non-TTY piped input).\n *\n * @param stdin - Readable stream to read from\n * @returns Parsed JSON object\n */\nexport async function readStdinJson(\n stdin: NodeJS.ReadableStream,\n): Promise<Record<string, unknown>> {\n const chunks: string[] = [];\n\n for await (const chunk of stdin) {\n if (typeof chunk === \"string\") {\n chunks.push(chunk);\n } else {\n chunks.push(chunk.toString(\"utf8\"));\n }\n }\n\n const content = chunks.join(\"\").trim();\n\n if (!content) {\n return {}; // Empty stdin, use defaults\n }\n\n try {\n const parsed = JSON.parse(content);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(\"Stdin must contain a JSON object, not an array or primitive.\");\n }\n return parsed as Record<string, unknown>;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid JSON from stdin: ${error.message}`);\n }\n throw error;\n }\n}\n","import { writeFileSync } from \"node:fs\";\nimport type { Command } from \"commander\";\n\nimport type { ImageConfig } from \"./config.js\";\nimport { COMMANDS, OPTION_DESCRIPTIONS, OPTION_FLAGS, SUMMARY_PREFIX } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { formatCost } from \"./ui/formatters.js\";\nimport { executeAction, resolvePrompt } from \"./utils.js\";\n\n/**\n * Default image generation model.\n */\nconst DEFAULT_IMAGE_MODEL = \"dall-e-3\";\n\n/**\n * Options for the image command.\n */\nexport interface ImageCommandOptions {\n model: string;\n size?: string;\n quality?: string;\n count?: string;\n output?: string;\n quiet?: boolean;\n}\n\n/**\n * Executes the image command.\n * Generates images from a text prompt using the specified model.\n *\n * @param promptArg - Prompt from command line argument (optional if using stdin)\n * @param options - Image command options\n * @param env - CLI environment for I/O operations\n */\nexport async function executeImage(\n promptArg: string | undefined,\n options: ImageCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const prompt = await resolvePrompt(promptArg, env);\n const client = env.createClient();\n\n const model = options.model;\n const n = options.count ? Number.parseInt(options.count, 10) : 1;\n\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n\n if (!options.quiet && stderrTTY) {\n env.stderr.write(`${SUMMARY_PREFIX} Generating image with ${model}...\\n`);\n }\n\n const result = await client.image.generate({\n model,\n prompt,\n size: options.size,\n quality: options.quality,\n n,\n responseFormat: options.output ? \"b64_json\" : \"url\",\n });\n\n // Handle output\n if (options.output) {\n // Save to file\n const imageData = result.images[0];\n if (imageData.b64Json) {\n const buffer = Buffer.from(imageData.b64Json, \"base64\");\n writeFileSync(options.output, buffer);\n if (!options.quiet) {\n env.stderr.write(`${SUMMARY_PREFIX} Image saved to ${options.output}\\n`);\n }\n } else if (imageData.url) {\n // If we got URL but requested file, write the URL\n env.stdout.write(`${imageData.url}\\n`);\n }\n } else {\n // Output URLs to stdout\n for (const image of result.images) {\n if (image.url) {\n env.stdout.write(`${image.url}\\n`);\n } else if (image.b64Json) {\n // For base64, output the raw data (can be piped to file)\n env.stdout.write(image.b64Json);\n }\n }\n }\n\n // Show summary\n if (!options.quiet && stderrTTY) {\n const parts = [\n `${result.images.length} image(s)`,\n `size: ${result.usage.size}`,\n `quality: ${result.usage.quality}`,\n ];\n if (result.cost !== undefined) {\n parts.push(`cost: ${formatCost(result.cost)}`);\n }\n env.stderr.write(`${SUMMARY_PREFIX} ${parts.join(\" | \")}\\n`);\n }\n}\n\n/**\n * Registers the image command with the CLI program.\n *\n * @param program - Commander program to register the command with\n * @param env - CLI environment for dependencies and I/O\n * @param config - Optional configuration defaults from config file\n */\nexport function registerImageCommand(\n program: Command,\n env: CLIEnvironment,\n config?: ImageConfig,\n): void {\n program\n .command(COMMANDS.image)\n .description(\"Generate images from a text prompt.\")\n .argument(\"[prompt]\", \"Image generation prompt. If omitted, stdin is used when available.\")\n .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, config?.model ?? DEFAULT_IMAGE_MODEL)\n .option(OPTION_FLAGS.imageSize, OPTION_DESCRIPTIONS.imageSize, config?.size)\n .option(OPTION_FLAGS.imageQuality, OPTION_DESCRIPTIONS.imageQuality, config?.quality)\n .option(OPTION_FLAGS.imageCount, OPTION_DESCRIPTIONS.imageCount, config?.count?.toString())\n .option(OPTION_FLAGS.imageOutput, OPTION_DESCRIPTIONS.imageOutput, config?.output)\n .option(OPTION_FLAGS.quiet, OPTION_DESCRIPTIONS.quiet, config?.quiet ?? false)\n .action((prompt, options) =>\n executeAction(() => executeImage(prompt, options as ImageCommandOptions, env), env),\n );\n}\n","import chalk from \"chalk\";\nimport type { Command } from \"commander\";\nimport type { ImageModelSpec, SpeechModelSpec } from \"../core/media-types.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport { MODEL_ALIASES } from \"../core/model-shortcuts.js\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { executeAction } from \"./utils.js\";\n\ninterface ModelsCommandOptions {\n provider?: string;\n format?: \"table\" | \"json\";\n verbose?: boolean;\n text?: boolean;\n image?: boolean;\n speech?: boolean;\n all?: boolean;\n}\n\nasync function handleModelsCommand(\n options: ModelsCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const client = env.createClient();\n\n // Determine which model types to show\n // Default: text models if no specific flag is set\n const showText = options.all || options.text || (!options.image && !options.speech);\n const showImage = options.all || options.image;\n const showSpeech = options.all || options.speech;\n\n // Collect models\n const textModels = showText ? client.modelRegistry.listModels(options.provider) : [];\n const imageModels = showImage\n ? client.image.listModels().filter((m) => !options.provider || m.provider === options.provider)\n : [];\n const speechModels = showSpeech\n ? client.speech.listModels().filter((m) => !options.provider || m.provider === options.provider)\n : [];\n\n if (options.format === \"json\") {\n renderJSON(textModels, imageModels, speechModels, env.stdout);\n } else {\n renderAllTables(textModels, imageModels, speechModels, options.verbose || false, env.stdout);\n }\n}\n\n/**\n * Main rendering orchestrator for all model types.\n */\nfunction renderAllTables(\n textModels: ModelSpec[],\n imageModels: ImageModelSpec[],\n speechModels: SpeechModelSpec[],\n verbose: boolean,\n stream: NodeJS.WritableStream,\n): void {\n const hasAnyModels = textModels.length > 0 || imageModels.length > 0 || speechModels.length > 0;\n\n if (!hasAnyModels) {\n stream.write(chalk.yellow(\"\\nNo models found matching the specified criteria.\\n\\n\"));\n return;\n }\n\n stream.write(chalk.bold.cyan(\"\\nAvailable Models\\n\"));\n stream.write(chalk.cyan(\"=\".repeat(80)) + \"\\n\\n\");\n\n // Text models\n if (textModels.length > 0) {\n renderTextTable(textModels, verbose, stream);\n }\n\n // Image models\n if (imageModels.length > 0) {\n renderImageTable(imageModels, verbose, stream);\n }\n\n // Speech models\n if (speechModels.length > 0) {\n renderSpeechTable(speechModels, verbose, stream);\n }\n\n // Display shortcuts (only if showing text models)\n if (textModels.length > 0) {\n stream.write(chalk.bold.magenta(\"Model Shortcuts\\n\"));\n stream.write(chalk.dim(\"─\".repeat(80)) + \"\\n\");\n\n const shortcuts = Object.entries(MODEL_ALIASES).sort((a, b) => a[0].localeCompare(b[0]));\n for (const [shortcut, fullName] of shortcuts) {\n stream.write(\n chalk.cyan(` ${shortcut.padEnd(15)}`) + chalk.dim(\" → \") + chalk.white(fullName) + \"\\n\",\n );\n }\n stream.write(\"\\n\");\n }\n}\n\n/**\n * Render text/LLM models grouped by provider.\n */\nfunction renderTextTable(\n models: ModelSpec[],\n verbose: boolean,\n stream: NodeJS.WritableStream,\n): void {\n // Group models by provider\n const grouped = new Map<string, ModelSpec[]>();\n for (const model of models) {\n const provider = model.provider;\n if (!grouped.has(provider)) {\n grouped.set(provider, []);\n }\n grouped.get(provider)!.push(model);\n }\n\n stream.write(chalk.bold.blue(\"📝 Text/LLM Models\\n\"));\n stream.write(chalk.dim(\"─\".repeat(80)) + \"\\n\\n\");\n\n // Display each provider's models\n const providers = Array.from(grouped.keys()).sort();\n for (const provider of providers) {\n const providerModels = grouped.get(provider)!;\n const providerName = provider.charAt(0).toUpperCase() + provider.slice(1);\n\n stream.write(chalk.bold.yellow(`${providerName}\\n`));\n\n if (verbose) {\n renderVerboseTable(providerModels, stream);\n } else {\n renderCompactTable(providerModels, stream);\n }\n\n stream.write(\"\\n\");\n }\n}\n\nfunction renderCompactTable(models: ModelSpec[], stream: NodeJS.WritableStream): void {\n // Column widths\n const idWidth = 25;\n const nameWidth = 22;\n const contextWidth = 13;\n const inputWidth = 10;\n const outputWidth = 10;\n\n // Header\n stream.write(\n chalk.dim(\"─\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\n\",\n );\n stream.write(\n chalk.bold(\n \"Model ID\".padEnd(idWidth) +\n \" \" +\n \"Display Name\".padEnd(nameWidth) +\n \" \" +\n \"Context\".padEnd(contextWidth) +\n \" \" +\n \"Input\".padEnd(inputWidth) +\n \" \" +\n \"Output\".padEnd(outputWidth),\n ) + \"\\n\",\n );\n stream.write(\n chalk.dim(\"─\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\n\",\n );\n\n // Rows\n for (const model of models) {\n const contextFormatted = formatTokens(model.contextWindow);\n const inputPrice = `$${model.pricing.input.toFixed(2)}`;\n const outputPrice = `$${model.pricing.output.toFixed(2)}`;\n\n stream.write(\n chalk.green(model.modelId.padEnd(idWidth)) +\n \" \" +\n chalk.white(model.displayName.padEnd(nameWidth)) +\n \" \" +\n chalk.yellow(contextFormatted.padEnd(contextWidth)) +\n \" \" +\n chalk.cyan(inputPrice.padEnd(inputWidth)) +\n \" \" +\n chalk.cyan(outputPrice.padEnd(outputWidth)) +\n \"\\n\",\n );\n }\n\n stream.write(\n chalk.dim(\"─\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\n\",\n );\n stream.write(chalk.dim(` * Prices are per 1M tokens\\n`));\n}\n\nfunction renderVerboseTable(models: ModelSpec[], stream: NodeJS.WritableStream): void {\n for (const model of models) {\n stream.write(chalk.bold.green(`\\n ${model.modelId}\\n`));\n stream.write(chalk.dim(\" \" + \"─\".repeat(60)) + \"\\n\");\n stream.write(` ${chalk.dim(\"Name:\")} ${chalk.white(model.displayName)}\\n`);\n stream.write(\n ` ${chalk.dim(\"Context:\")} ${chalk.yellow(formatTokens(model.contextWindow))}\\n`,\n );\n stream.write(\n ` ${chalk.dim(\"Max Output:\")} ${chalk.yellow(formatTokens(model.maxOutputTokens))}\\n`,\n );\n stream.write(\n ` ${chalk.dim(\"Pricing:\")} ${chalk.cyan(`$${model.pricing.input.toFixed(2)} input`)} ${chalk.dim(\"/\")} ${chalk.cyan(`$${model.pricing.output.toFixed(2)} output`)} ${chalk.dim(\"(per 1M tokens)\")}\\n`,\n );\n\n if (model.pricing.cachedInput !== undefined) {\n stream.write(\n ` ${chalk.dim(\"Cached Input:\")} ${chalk.cyan(`$${model.pricing.cachedInput.toFixed(2)} per 1M tokens`)}\\n`,\n );\n }\n\n if (model.knowledgeCutoff) {\n stream.write(` ${chalk.dim(\"Knowledge:\")} ${model.knowledgeCutoff}\\n`);\n }\n\n // Features\n const features: string[] = [];\n if (model.features.streaming) features.push(\"streaming\");\n if (model.features.functionCalling) features.push(\"function-calling\");\n if (model.features.vision) features.push(\"vision\");\n if (model.features.reasoning) features.push(\"reasoning\");\n if (model.features.structuredOutputs) features.push(\"structured-outputs\");\n if (model.features.fineTuning) features.push(\"fine-tuning\");\n\n if (features.length > 0) {\n stream.write(` ${chalk.dim(\"Features:\")} ${chalk.blue(features.join(\", \"))}\\n`);\n }\n\n // Metadata\n if (model.metadata) {\n if (model.metadata.family) {\n stream.write(` ${chalk.dim(\"Family:\")} ${model.metadata.family}\\n`);\n }\n if (model.metadata.releaseDate) {\n stream.write(` ${chalk.dim(\"Released:\")} ${model.metadata.releaseDate}\\n`);\n }\n if (model.metadata.notes) {\n stream.write(` ${chalk.dim(\"Notes:\")} ${chalk.italic(model.metadata.notes)}\\n`);\n }\n }\n }\n stream.write(\"\\n\");\n}\n\n/**\n * Render image generation models table.\n */\nfunction renderImageTable(\n models: ImageModelSpec[],\n verbose: boolean,\n stream: NodeJS.WritableStream,\n): void {\n stream.write(chalk.bold.green(\"🎨 Image Generation Models\\n\"));\n stream.write(chalk.dim(\"─\".repeat(80)) + \"\\n\\n\");\n\n // Group by provider\n const grouped = new Map<string, ImageModelSpec[]>();\n for (const model of models) {\n if (!grouped.has(model.provider)) {\n grouped.set(model.provider, []);\n }\n grouped.get(model.provider)!.push(model);\n }\n\n for (const [provider, providerModels] of Array.from(grouped.entries()).sort()) {\n const providerName = provider.charAt(0).toUpperCase() + provider.slice(1);\n stream.write(chalk.bold.yellow(`${providerName}\\n`));\n\n if (verbose) {\n for (const model of providerModels) {\n stream.write(chalk.bold.green(`\\n ${model.modelId}\\n`));\n stream.write(chalk.dim(\" \" + \"─\".repeat(60)) + \"\\n\");\n stream.write(` ${chalk.dim(\"Name:\")} ${chalk.white(model.displayName)}\\n`);\n stream.write(\n ` ${chalk.dim(\"Sizes:\")} ${chalk.yellow(model.supportedSizes.join(\", \"))}\\n`,\n );\n if (model.supportedQualities) {\n stream.write(\n ` ${chalk.dim(\"Qualities:\")} ${chalk.yellow(model.supportedQualities.join(\", \"))}\\n`,\n );\n }\n stream.write(` ${chalk.dim(\"Max Images:\")} ${chalk.yellow(model.maxImages.toString())}\\n`);\n stream.write(` ${chalk.dim(\"Pricing:\")} ${chalk.cyan(formatImagePrice(model))}\\n`);\n if (model.features) {\n const features: string[] = [];\n if (model.features.textRendering) features.push(\"text-rendering\");\n if (model.features.transparency) features.push(\"transparency\");\n if (model.features.conversational) features.push(\"conversational\");\n if (features.length > 0) {\n stream.write(` ${chalk.dim(\"Features:\")} ${chalk.blue(features.join(\", \"))}\\n`);\n }\n }\n }\n } else {\n const idWidth = 32;\n const nameWidth = 25;\n const sizesWidth = 20;\n const priceWidth = 15;\n\n stream.write(chalk.dim(\"─\".repeat(idWidth + nameWidth + sizesWidth + priceWidth + 6)) + \"\\n\");\n stream.write(\n chalk.bold(\n \"Model ID\".padEnd(idWidth) +\n \" \" +\n \"Display Name\".padEnd(nameWidth) +\n \" \" +\n \"Sizes\".padEnd(sizesWidth) +\n \" \" +\n \"Price\".padEnd(priceWidth),\n ) + \"\\n\",\n );\n stream.write(chalk.dim(\"─\".repeat(idWidth + nameWidth + sizesWidth + priceWidth + 6)) + \"\\n\");\n\n for (const model of providerModels) {\n const sizes =\n model.supportedSizes.length > 2\n ? model.supportedSizes.slice(0, 2).join(\", \") + \"...\"\n : model.supportedSizes.join(\", \");\n\n stream.write(\n chalk.green(model.modelId.padEnd(idWidth)) +\n \" \" +\n chalk.white(model.displayName.substring(0, nameWidth - 1).padEnd(nameWidth)) +\n \" \" +\n chalk.yellow(sizes.padEnd(sizesWidth)) +\n \" \" +\n chalk.cyan(formatImagePrice(model).padEnd(priceWidth)) +\n \"\\n\",\n );\n }\n stream.write(chalk.dim(\"─\".repeat(idWidth + nameWidth + sizesWidth + priceWidth + 6)) + \"\\n\");\n }\n\n stream.write(\"\\n\");\n }\n}\n\n/**\n * Render speech/TTS models table.\n */\nfunction renderSpeechTable(\n models: SpeechModelSpec[],\n verbose: boolean,\n stream: NodeJS.WritableStream,\n): void {\n stream.write(chalk.bold.magenta(\"🎤 Speech (TTS) Models\\n\"));\n stream.write(chalk.dim(\"─\".repeat(80)) + \"\\n\\n\");\n\n // Group by provider\n const grouped = new Map<string, SpeechModelSpec[]>();\n for (const model of models) {\n if (!grouped.has(model.provider)) {\n grouped.set(model.provider, []);\n }\n grouped.get(model.provider)!.push(model);\n }\n\n for (const [provider, providerModels] of Array.from(grouped.entries()).sort()) {\n const providerName = provider.charAt(0).toUpperCase() + provider.slice(1);\n stream.write(chalk.bold.yellow(`${providerName}\\n`));\n\n if (verbose) {\n for (const model of providerModels) {\n stream.write(chalk.bold.green(`\\n ${model.modelId}\\n`));\n stream.write(chalk.dim(\" \" + \"─\".repeat(60)) + \"\\n\");\n stream.write(` ${chalk.dim(\"Name:\")} ${chalk.white(model.displayName)}\\n`);\n stream.write(\n ` ${chalk.dim(\"Voices:\")} ${chalk.yellow(model.voices.length.toString())} voices\\n`,\n );\n if (model.voices.length <= 6) {\n stream.write(` ${chalk.dim(model.voices.join(\", \"))}\\n`);\n } else {\n stream.write(` ${chalk.dim(model.voices.slice(0, 6).join(\", \") + \"...\")}\\n`);\n }\n stream.write(` ${chalk.dim(\"Formats:\")} ${chalk.yellow(model.formats.join(\", \"))}\\n`);\n stream.write(\n ` ${chalk.dim(\"Max Input:\")} ${chalk.yellow(model.maxInputLength.toString())} chars\\n`,\n );\n stream.write(` ${chalk.dim(\"Pricing:\")} ${chalk.cyan(formatSpeechPrice(model))}\\n`);\n if (model.features) {\n const features: string[] = [];\n if (model.features.multiSpeaker) features.push(\"multi-speaker\");\n if (model.features.voiceInstructions) features.push(\"voice-instructions\");\n if (model.features.languages) features.push(`${model.features.languages} languages`);\n if (features.length > 0) {\n stream.write(` ${chalk.dim(\"Features:\")} ${chalk.blue(features.join(\", \"))}\\n`);\n }\n }\n }\n } else {\n const idWidth = 30;\n const nameWidth = 28;\n const voicesWidth = 12;\n const priceWidth = 18;\n\n stream.write(\n chalk.dim(\"─\".repeat(idWidth + nameWidth + voicesWidth + priceWidth + 6)) + \"\\n\",\n );\n stream.write(\n chalk.bold(\n \"Model ID\".padEnd(idWidth) +\n \" \" +\n \"Display Name\".padEnd(nameWidth) +\n \" \" +\n \"Voices\".padEnd(voicesWidth) +\n \" \" +\n \"Price\".padEnd(priceWidth),\n ) + \"\\n\",\n );\n stream.write(\n chalk.dim(\"─\".repeat(idWidth + nameWidth + voicesWidth + priceWidth + 6)) + \"\\n\",\n );\n\n for (const model of providerModels) {\n stream.write(\n chalk.green(model.modelId.padEnd(idWidth)) +\n \" \" +\n chalk.white(model.displayName.substring(0, nameWidth - 1).padEnd(nameWidth)) +\n \" \" +\n chalk.yellow(`${model.voices.length} voices`.padEnd(voicesWidth)) +\n \" \" +\n chalk.cyan(formatSpeechPrice(model).padEnd(priceWidth)) +\n \"\\n\",\n );\n }\n stream.write(\n chalk.dim(\"─\".repeat(idWidth + nameWidth + voicesWidth + priceWidth + 6)) + \"\\n\",\n );\n }\n\n stream.write(\"\\n\");\n }\n}\n\n/**\n * Format image model pricing for display.\n */\nfunction formatImagePrice(model: ImageModelSpec): string {\n if (model.pricing.perImage !== undefined) {\n return `$${model.pricing.perImage.toFixed(2)}/img`;\n }\n if (model.pricing.bySize) {\n const prices = Object.values(model.pricing.bySize);\n const minPrice = Math.min(\n ...prices.flatMap((p) => (typeof p === \"number\" ? [p] : Object.values(p))),\n );\n const maxPrice = Math.max(\n ...prices.flatMap((p) => (typeof p === \"number\" ? [p] : Object.values(p))),\n );\n if (minPrice === maxPrice) {\n return `$${minPrice.toFixed(2)}/img`;\n }\n return `$${minPrice.toFixed(2)}-${maxPrice.toFixed(2)}`;\n }\n return \"varies\";\n}\n\n/**\n * Format speech model pricing for display.\n */\nfunction formatSpeechPrice(model: SpeechModelSpec): string {\n if (model.pricing.perCharacter !== undefined) {\n const perMillion = model.pricing.perCharacter * 1_000_000;\n return `$${perMillion.toFixed(0)}/1M chars`;\n }\n if (model.pricing.perMinute !== undefined) {\n return `~$${model.pricing.perMinute.toFixed(2)}/min`;\n }\n return \"varies\";\n}\n\nfunction renderJSON(\n textModels: ModelSpec[],\n imageModels: ImageModelSpec[],\n speechModels: SpeechModelSpec[],\n stream: NodeJS.WritableStream,\n): void {\n const output: Record<string, unknown> = {};\n\n if (textModels.length > 0) {\n output.textModels = textModels.map((model) => ({\n provider: model.provider,\n modelId: model.modelId,\n displayName: model.displayName,\n contextWindow: model.contextWindow,\n maxOutputTokens: model.maxOutputTokens,\n pricing: {\n input: model.pricing.input,\n output: model.pricing.output,\n cachedInput: model.pricing.cachedInput,\n currency: \"USD\",\n per: \"1M tokens\",\n },\n knowledgeCutoff: model.knowledgeCutoff,\n features: model.features,\n metadata: model.metadata,\n }));\n output.shortcuts = MODEL_ALIASES;\n }\n\n if (imageModels.length > 0) {\n output.imageModels = imageModels.map((model) => ({\n provider: model.provider,\n modelId: model.modelId,\n displayName: model.displayName,\n supportedSizes: model.supportedSizes,\n supportedQualities: model.supportedQualities,\n maxImages: model.maxImages,\n pricing: model.pricing,\n features: model.features,\n }));\n }\n\n if (speechModels.length > 0) {\n output.speechModels = speechModels.map((model) => ({\n provider: model.provider,\n modelId: model.modelId,\n displayName: model.displayName,\n voices: model.voices,\n formats: model.formats,\n maxInputLength: model.maxInputLength,\n pricing: model.pricing,\n features: model.features,\n }));\n }\n\n stream.write(JSON.stringify(output, null, 2) + \"\\n\");\n}\n\nfunction formatTokens(count: number): string {\n if (count >= 1_000_000) {\n return `${(count / 1_000_000).toFixed(1)}M tokens`;\n } else if (count >= 1_000) {\n return `${(count / 1_000).toFixed(0)}K tokens`;\n } else {\n return `${count} tokens`;\n }\n}\n\nexport function registerModelsCommand(program: Command, env: CLIEnvironment): void {\n program\n .command(COMMANDS.models)\n .description(\"List available models with pricing and capabilities.\")\n .option(\"--provider <name>\", \"Filter by provider (openai, anthropic, gemini)\")\n .option(\"--format <format>\", \"Output format: table or json\", \"table\")\n .option(\"--verbose\", \"Show detailed model information\", false)\n .option(\"--text\", \"Show text/LLM models (default if no type specified)\")\n .option(\"--image\", \"Show image generation models\")\n .option(\"--speech\", \"Show speech/TTS models\")\n .option(\"--all\", \"Show all model types (text, image, speech)\")\n .action((options) =>\n executeAction(() => handleModelsCommand(options as ModelsCommandOptions, env), env),\n );\n}\n","import { writeFileSync } from \"node:fs\";\nimport type { Command } from \"commander\";\n\nimport type { SpeechConfig } from \"./config.js\";\nimport { COMMANDS, OPTION_DESCRIPTIONS, OPTION_FLAGS, SUMMARY_PREFIX } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { formatCost } from \"./ui/formatters.js\";\nimport { executeAction, resolvePrompt } from \"./utils.js\";\n\n/**\n * Default speech generation model.\n */\nconst DEFAULT_SPEECH_MODEL = \"tts-1\";\n\n/**\n * Default voice for speech generation.\n */\nconst DEFAULT_VOICE = \"nova\";\n\n/**\n * Options for the speech command.\n */\nexport interface SpeechCommandOptions {\n model: string;\n voice?: string;\n format?: string;\n speed?: string;\n output?: string;\n quiet?: boolean;\n}\n\n/**\n * Executes the speech command.\n * Generates speech audio from text using the specified model and voice.\n *\n * @param textArg - Text from command line argument (optional if using stdin)\n * @param options - Speech command options\n * @param env - CLI environment for I/O operations\n */\nexport async function executeSpeech(\n textArg: string | undefined,\n options: SpeechCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const text = await resolvePrompt(textArg, env);\n const client = env.createClient();\n\n const model = options.model;\n const voice = options.voice ?? DEFAULT_VOICE;\n const speed = options.speed ? Number.parseFloat(options.speed) : undefined;\n\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n\n if (!options.quiet && stderrTTY) {\n env.stderr.write(`${SUMMARY_PREFIX} Generating speech with ${model} (voice: ${voice})...\\n`);\n }\n\n const result = await client.speech.generate({\n model,\n input: text,\n voice,\n responseFormat: options.format as \"mp3\" | \"opus\" | \"aac\" | \"flac\" | \"wav\" | \"pcm\" | undefined,\n speed,\n });\n\n // Get the audio data as a Buffer\n const audioBuffer = Buffer.from(result.audio);\n\n // Handle output\n if (options.output) {\n // Save to file\n writeFileSync(options.output, audioBuffer);\n if (!options.quiet) {\n env.stderr.write(`${SUMMARY_PREFIX} Audio saved to ${options.output}\\n`);\n }\n } else {\n // Output raw audio to stdout (for piping)\n env.stdout.write(audioBuffer);\n }\n\n // Show summary\n if (!options.quiet && stderrTTY) {\n const parts = [`${result.usage.characterCount} characters`, `format: ${result.format}`];\n if (result.cost !== undefined) {\n parts.push(`cost: ${formatCost(result.cost)}`);\n }\n env.stderr.write(`${SUMMARY_PREFIX} ${parts.join(\" | \")}\\n`);\n }\n}\n\n/**\n * Registers the speech command with the CLI program.\n *\n * @param program - Commander program to register the command with\n * @param env - CLI environment for dependencies and I/O\n * @param config - Optional configuration defaults from config file\n */\nexport function registerSpeechCommand(\n program: Command,\n env: CLIEnvironment,\n config?: SpeechConfig,\n): void {\n program\n .command(COMMANDS.speech)\n .description(\"Generate speech audio from text.\")\n .argument(\"[text]\", \"Text to convert to speech. If omitted, stdin is used when available.\")\n .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, config?.model ?? DEFAULT_SPEECH_MODEL)\n .option(OPTION_FLAGS.voice, OPTION_DESCRIPTIONS.voice, config?.voice ?? DEFAULT_VOICE)\n .option(OPTION_FLAGS.speechFormat, OPTION_DESCRIPTIONS.speechFormat, config?.format)\n .option(OPTION_FLAGS.speechSpeed, OPTION_DESCRIPTIONS.speechSpeed, config?.speed?.toString())\n .option(OPTION_FLAGS.speechOutput, OPTION_DESCRIPTIONS.speechOutput, config?.output)\n .option(OPTION_FLAGS.quiet, OPTION_DESCRIPTIONS.quiet, config?.quiet ?? false)\n .action((text, options) =>\n executeAction(() => executeSpeech(text, options as SpeechCommandOptions, env), env),\n );\n}\n","/**\n * Vision command for image analysis.\n *\n * Provides a dedicated CLI for one-shot image analysis using vision-capable models.\n *\n * @example\n * ```bash\n * llmist vision photo.jpg -p \"Describe this image\"\n * llmist vision screenshot.png --model gpt-4o -p \"Extract all text from this image\"\n * ```\n */\n\nimport type { Command } from \"commander\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport { COMMANDS, OPTION_DESCRIPTIONS, OPTION_FLAGS, SUMMARY_PREFIX } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { readFileBuffer } from \"./file-utils.js\";\nimport { createNumericParser, executeAction } from \"./utils.js\";\n\n/**\n * Options for the vision command.\n */\nexport interface VisionCommandOptions {\n /** Model to use for vision analysis */\n model: string;\n /** Analysis prompt */\n prompt?: string;\n /** Maximum tokens in response */\n maxTokens?: number;\n /** Suppress progress output */\n quiet?: boolean;\n}\n\n/**\n * Execute vision analysis on an image.\n *\n * @param imagePath - Path to the image file\n * @param options - Vision command options\n * @param env - CLI environment\n */\nexport async function executeVision(\n imagePath: string,\n options: VisionCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const client = env.createClient();\n const model = resolveModel(options.model);\n\n // Read image file\n const imageBuffer = await readFileBuffer(imagePath);\n\n // Default prompt for vision analysis\n const prompt = options.prompt ?? \"Describe this image in detail.\";\n\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n\n if (!options.quiet && stderrTTY) {\n env.stderr.write(`${SUMMARY_PREFIX} Analyzing image with ${model}...\\n`);\n }\n\n // Use vision namespace for one-shot analysis\n const result = await client.vision.analyze({\n model,\n image: imageBuffer,\n prompt,\n maxTokens: options.maxTokens,\n });\n\n // Output result\n env.stdout.write(result);\n env.stdout.write(\"\\n\");\n}\n\n/**\n * Register the vision command with the CLI program.\n *\n * @param program - Commander program instance\n * @param env - CLI environment\n */\nexport function registerVisionCommand(program: Command, env: CLIEnvironment): void {\n program\n .command(COMMANDS.vision ?? \"vision\")\n .description(\"Analyze an image using vision-capable models\")\n .argument(\"<image>\", \"Path to image file to analyze\")\n .option(\n OPTION_FLAGS.model,\n OPTION_DESCRIPTIONS.model,\n \"gpt-4o\", // Default to a vision-capable model\n )\n .option(\"-p, --prompt <prompt>\", \"Analysis prompt describing what to extract or describe\")\n .option(\n OPTION_FLAGS.maxTokens,\n OPTION_DESCRIPTIONS.maxTokens,\n createNumericParser({ label: \"Max tokens\", integer: true, min: 1 }),\n )\n .option(OPTION_FLAGS.quiet, OPTION_DESCRIPTIONS.quiet)\n .action((imagePath: string, options: VisionCommandOptions) =>\n executeAction(() => executeVision(imagePath, options, env), env),\n );\n}\n","#!/usr/bin/env node\nimport { SUMMARY_PREFIX } from \"./cli/constants.js\";\nimport { runCLI } from \"./cli/program.js\";\n\nrunCLI().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`${SUMMARY_PREFIX} Error: ${message}\\n`);\n process.exitCode = 1;\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACO,IAAM,WAAW;AAGjB,IAAM,kBAAkB;AAGxB,IAAM,WAAW;AAAA,EACtB,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,MAAM;AACR;AAGO,IAAM,aAAa,CAAC,SAAS,SAAS,SAAS,QAAQ,QAAQ,SAAS,OAAO;AAI/E,IAAM,gBAAgB;AAGtB,IAAM,eAAe;AAAA,EAC1B,OAAO;AAAA,EACP,cAAc;AAAA,EACd,aAAa;AAAA,EACb,WAAW;AAAA,EACX,eAAe;AAAA,EACf,cAAc;AAAA,EACd,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,sBAAsB;AAAA,EACtB,OAAO;AAAA;AAAA,EAEP,YAAY;AAAA,EACZ,YAAY;AAAA;AAAA,EAEZ,WAAW;AAAA,EACX,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,aAAa;AAAA;AAAA,EAEb,OAAO;AAAA,EACP,cAAc;AAAA,EACd,aAAa;AAAA,EACb,cAAc;AAChB;AAGO,IAAM,sBAAsB;AAAA,EACjC,OAAO;AAAA,EACP,cAAc;AAAA,EACd,aAAa;AAAA,EACb,WAAW;AAAA,EACX,eAAe;AAAA,EACf,cACE;AAAA,EACF,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,gBACE;AAAA,EACF,YAAY;AAAA,EACZ,sBAAsB;AAAA,EACtB,OAAO;AAAA;AAAA,EAEP,YAAY;AAAA,EACZ,YAAY;AAAA;AAAA,EAEZ,WAAW;AAAA,EACX,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,aAAa;AAAA;AAAA,EAEb,OAAO;AAAA,EACP,cAAc;AAAA,EACd,aAAa;AAAA,EACb,cAAc;AAChB;AAGO,IAAM,iBAAiB;;;ACxF9B,SAAS,SAAS,wBAAAA,6BAA4B;;;ACA9C;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,MAAQ;AAAA,EACR,QAAU;AAAA,EACV,OAAS;AAAA,EACT,SAAW;AAAA,IACT,KAAK;AAAA,MACH,QAAU;AAAA,QACR,OAAS;AAAA,QACT,SAAW;AAAA,MACb;AAAA,MACA,SAAW;AAAA,QACT,OAAS;AAAA,QACT,SAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,aAAa;AAAA,MACX,QAAU;AAAA,QACR,OAAS;AAAA,QACT,SAAW;AAAA,MACb;AAAA,MACA,SAAW;AAAA,QACT,OAAS;AAAA,QACT,SAAW;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAAA,EACA,SAAW;AAAA,IACT,KAAO;AAAA,IACP,OAAS;AAAA,IACT,WAAa;AAAA,IACb,MAAQ;AAAA,IACR,QAAU;AAAA,IACV,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,aAAa;AAAA,IACb,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,YAAY;AAAA,IACZ,OAAS;AAAA,IACT,SAAW;AAAA,IACX,eAAe;AAAA,IACf,mBAAmB;AAAA,EACrB;AAAA,EACA,KAAO;AAAA,IACL,QAAU;AAAA,EACZ;AAAA,EACA,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,eAAiB;AAAA,IACf,QAAU;AAAA,EACZ;AAAA,EACA,OAAS;AAAA,IACP;AAAA,EACF;AAAA,EACA,UAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAU;AAAA,EACV,SAAW;AAAA,EACX,cAAgB;AAAA,IACd,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,mBAAmB;AAAA,IACnB,OAAS;AAAA,IACT,WAAa;AAAA,IACb,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAU;AAAA,IACV,mBAAmB;AAAA,IACnB,QAAU;AAAA,IACV,UAAY;AAAA,IACZ,OAAS;AAAA,IACT,KAAO;AAAA,EACT;AAAA,EACA,iBAAmB;AAAA,IACjB,kBAAkB;AAAA,IAClB,mBAAmB;AAAA,IACnB,mCAAmC;AAAA,IACnC,+BAA+B;AAAA,IAC/B,yBAAyB;AAAA,IACzB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,0BAA0B;AAAA,IAC1B,eAAe;AAAA,IACf,aAAa;AAAA,IACb,QAAU;AAAA,IACV,QAAU;AAAA,IACV,oBAAoB;AAAA,IACpB,MAAQ;AAAA,IACR,YAAc;AAAA,EAChB;AACF;;;AC1HA;;;ACkCO,SAAS,aAAa,OAAyB;AACpD,MAAI,EAAE,iBAAiB,OAAQ,QAAO;AAGtC,MAAI,MAAM,SAAS,aAAc,QAAO;AAGxC,MAAI,MAAM,SAAS,4BAA6B,QAAO;AAGvD,MAAI,MAAM,SAAS,oBAAqB,QAAO;AAG/C,QAAM,UAAU,MAAM,QAAQ,YAAY;AAC1C,MAAI,QAAQ,SAAS,OAAO,EAAG,QAAO;AACtC,MAAI,QAAQ,SAAS,WAAW,EAAG,QAAO;AAC1C,MAAI,QAAQ,SAAS,UAAU,EAAG,QAAO;AAEzC,SAAO;AACT;;;ADlDA;AAGA;AACA;;;AEHA;AACA;AAHA,SAAS,SAAS;AAUX,IAAM,UAAU,aAAa;AAAA,EAClC,MAAM;AAAA,EACN,aACE;AAAA,EACF,QAAQ,EAAE,OAAO;AAAA,IACf,UAAU,EAAE,OAAO,EAAE,SAAS,wDAAwD;AAAA,EACxF,CAAC;AAAA,EACD,UAAU;AAAA,IACR;AAAA,MACE,SAAS;AAAA,MACT,QAAQ,EAAE,UAAU,0CAA0C;AAAA,IAChE;AAAA,IACA;AAAA,MACE,SAAS;AAAA,MACT,QAAQ;AAAA,QACN,UACE;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AAAA,EACA,SAAS,CAAC,EAAE,SAAS,MAAM;AACzB,UAAM,IAAI,4BAA4B,QAAQ;AAAA,EAChD;AACF,CAAC;AAQM,IAAM,WAAW,aAAa;AAAA,EACnC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,QAAQ,EAAE,OAAO;AAAA,IACf,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,gDAAgD;AAAA,IACxF,MAAM,EACH,KAAK,CAAC,QAAQ,WAAW,WAAW,OAAO,CAAC,EAC5C,QAAQ,MAAM,EACd,SAAS,gDAAgD;AAAA,EAC9D,CAAC;AAAA,EACD,UAAU;AAAA,IACR;AAAA,MACE,SAAS;AAAA,MACT,QAAQ;AAAA,QACN,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,IACF;AAAA,IACA;AAAA,MACE,SAAS;AAAA,MACT,QAAQ;AAAA,QACN,SACE;AAAA,QACF,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA,EACA,SAAS,CAAC,EAAE,SAAS,KAAK,MAAM;AAG9B,QAAI,CAAC,WAAW,QAAQ,KAAK,MAAM,IAAI;AACrC,aAAO;AAAA,IACT;AAIA,UAAM,WAAW;AAAA,MACf,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AACA,WAAO,SAAS,IAAI,IAAI;AAAA,EAC1B;AACF,CAAC;AAOM,IAAM,SAAS,aAAa;AAAA,EACjC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,QAAQ,EAAE,OAAO,CAAC,CAAC;AAAA,EACnB,UAAU;AAAA,IACR;AAAA,MACE,SAAS;AAAA,MACT,QAAQ,CAAC;AAAA,IACX;AAAA,EACF;AAAA,EACA,SAAS,MAAM;AACb,UAAM,IAAI,qBAAqB,gBAAgB;AAAA,EACjD;AACF,CAAC;AAKM,IAAM,iBAAiB,CAAC,SAAS,UAAU,MAAM;;;ACpGjD,IAAM,gBAAgB;AAuCtB,SAAS,sBACd,cACA,aACA,eACA,cACgB;AAChB,QAAM,WAA2B,CAAC;AAGlC,QAAM,qBAAqB,eAAe,eAAe;AACzD,QAAM,iBAAiB,sBAAsB,cAAc,YAAY;AACvE,QAAM,kBAAkB,gBAAgB,YAAY,KAAK,CAAC;AAG1D,QAAM,SAAS,EAAE,GAAG,gBAAgB,GAAG,gBAAgB;AAGvD,QAAM,cAAc,OAAO,SAAS,sBAAsB;AAG1D,WAAS,QAAQ,gBAAgB,gBAAgB,cAAc;AAG/D,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,QAAQ,SAAS;AACnB,eAAS,GAAG,IAAI;AAAA,IAClB;AAAA,EACF;AAEA,SAAO;AACT;AAUO,SAAS,uBACd,aACA,eACA,cACmB;AAEnB,QAAM,gBAAgB,oBAAI,IAAY;AAEtC,MAAI,cAAc;AAChB,eAAW,OAAO,OAAO,KAAK,YAAY,GAAG;AAC3C,UAAI,QAAQ,mBAAmB,OAAO,aAAa,GAAG,MAAM,UAAU;AACpE,sBAAc,IAAI,GAAG;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,eAAe;AACjB,eAAW,OAAO,OAAO,KAAK,aAAa,GAAG;AAC5C,oBAAc,IAAI,GAAG;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,SAA4B,CAAC;AACnC,aAAW,QAAQ,eAAe;AAChC,WAAO,IAAI,IAAI,sBAAsB,MAAM,aAAa,eAAe,YAAY;AAAA,EACrF;AAEA,SAAO;AACT;AAMA,SAAS,sBACP,cACA,cACgB;AAChB,MAAI,CAAC,cAAc;AACjB,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,QAAQ,aAAa,YAAY;AACvC,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AAEA,SAAO,CAAC;AACV;;;ACpIA;AAHA,SAAS,UAAU,YAAY;AAC/B,SAAS,eAAe;AAiBjB,IAAM,wBAAwB,KAAK,OAAO;AAiBjD,SAAS,eAAe,OAAuB;AAC7C,MAAI,QAAQ,KAAM,QAAO,GAAG,KAAK;AACjC,MAAI,QAAQ,OAAO,KAAM,QAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAC5D,MAAI,QAAQ,OAAO,OAAO,KAAM,QAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC5E,SAAO,IAAI,SAAS,OAAO,OAAO,OAAO,QAAQ,CAAC,CAAC;AACrD;AAKA,eAAe,cACb,cACA,UACA,SACe;AACf,QAAM,QAAQ,MAAM,KAAK,YAAY;AACrC,MAAI,MAAM,OAAO,SAAS;AACxB,UAAM,IAAI;AAAA,MACR,SAAS,QAAQ,mBAAmB,eAAe,MAAM,IAAI,CAAC,8BACjC,eAAe,OAAO,CAAC;AAAA,IAEtD;AAAA,EACF;AACF;AAgBA,eAAsB,cACpB,UACA,UAA2B,CAAC,GACD;AAC3B,QAAM,eAAe,QAAQ,QAAQ;AACrC,QAAM,cAAc,QAAQ,eAAe;AAE3C,MAAI;AACJ,MAAI;AACF,UAAM,cAAc,cAAc,UAAU,WAAW;AACvD,aAAS,MAAM,SAAS,YAAY;AAAA,EACtC,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,IAAI,MAAM,8BAA8B,QAAQ,MAAM,OAAO,EAAE;AAAA,EACvE;AAGA,QAAM,WAAW,oBAAoB,MAAM;AAC3C,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR,SAAS,QAAQ;AAAA,IAEnB;AAAA,EACF;AAEA,SAAO,gBAAgB,QAAQ,QAAQ;AACzC;AAgBA,eAAsB,cACpB,UACA,UAA2B,CAAC,GACD;AAC3B,QAAM,eAAe,QAAQ,QAAQ;AACrC,QAAM,cAAc,QAAQ,eAAe;AAE3C,MAAI;AACJ,MAAI;AACF,UAAM,cAAc,cAAc,UAAU,WAAW;AACvD,aAAS,MAAM,SAAS,YAAY;AAAA,EACtC,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,IAAI,MAAM,8BAA8B,QAAQ,MAAM,OAAO,EAAE;AAAA,EACvE;AAGA,QAAM,WAAW,oBAAoB,MAAM;AAC3C,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR,SAAS,QAAQ;AAAA,IAEnB;AAAA,EACF;AAEA,SAAO,gBAAgB,QAAQ,QAAQ;AACzC;AAWA,eAAsB,eACpB,UACA,UAA2B,CAAC,GACX;AACjB,QAAM,eAAe,QAAQ,QAAQ;AACrC,QAAM,cAAc,QAAQ,eAAe;AAE3C,MAAI;AACF,UAAM,cAAc,cAAc,UAAU,WAAW;AACvD,WAAO,MAAM,SAAS,YAAY;AAAA,EACpC,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,IAAI,MAAM,wBAAwB,QAAQ,MAAM,OAAO,EAAE;AAAA,EACjE;AACF;;;AC1KA;AAJA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,iBAAAC,sBAAqB;;;ACF9B,SAAS,KAAAC,UAAS;;;ACAlB,OAAO,QAAQ;AACf,OAAO,UAAU;AAMV,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC9C,YAAY,WAAmB,QAAgB;AAC7C,UAAM,uBAAuB,SAAS,KAAK,MAAM,EAAE;AACnD,SAAK,OAAO;AAAA,EACd;AACF;AAYO,SAAS,wBAAwB,WAA2B;AACjE,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,eAAe,KAAK,QAAQ,KAAK,SAAS;AAGhD,MAAI;AACJ,MAAI;AACF,gBAAY,GAAG,aAAa,YAAY;AAAA,EAC1C,SAAS,OAAO;AAEd,UAAM,YAAY;AAClB,QAAI,UAAU,SAAS,UAAU;AAC/B,kBAAY;AAAA,IACd,OAAO;AAEL,YAAM;AAAA,IACR;AAAA,EACF;AAIA,QAAM,aAAa,MAAM,KAAK;AAC9B,MAAI,CAAC,UAAU,WAAW,UAAU,KAAK,cAAc,KAAK;AAC1D,UAAM,IAAI,qBAAqB,WAAW,+CAA+C;AAAA,EAC3F;AAEA,SAAO;AACT;;;AD3CA,SAAS,wBAAwB,UAA0B;AACzD,SAAO,SACJ,MAAM,IAAI,EACV,OAAO,CAAC,SAAS,CAAC,KAAK,UAAU,EAAE,WAAW,GAAG,CAAC,EAClD,KAAK,IAAI;AACd;AAEO,IAAM,WAAW,aAAa;AAAA,EACnC,MAAM;AAAA,EACN,aACE;AAAA,EACF,QAAQC,GAAE,OAAO;AAAA,IACf,UAAUA,GAAE,OAAO,EAAE,SAAS,iDAAiD;AAAA,IAC/E,UAAUA,GAAE,OAAO,EAAE,SAAS,sCAAsC;AAAA,EACtE,CAAC;AAAA,EACD,UAAU;AAAA,IACR;AAAA,MACE,QAAQ;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA;AAAA,MAEZ;AAAA,MACA,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA;AAAA;AAAA,MAGZ;AAAA,MACA,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA;AAAA;AAAA,MAGZ;AAAA,MACA,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,QACN,UAAU;AAAA,QACV,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,MAKZ;AAAA,MACA,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,WAAW;AAAA,EACX,SAAS,OAAO,EAAE,UAAU,SAAS,MAAM;AACzC,UAAM,gBAAgB,wBAAwB,QAAQ;AACtD,UAAM,eAAe,wBAAwB,QAAQ;AAErD,QAAI;AACF,YAAM,OAAO,IAAI,MAAM,CAAC,MAAM,aAAa,GAAG;AAAA,QAC5C,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAGD,WAAK,MAAM,MAAM,GAAG,YAAY;AAAA,CAAI;AACpC,WAAK,MAAM,IAAI;AAGf,UAAI;AACJ,YAAM,iBAAiB,IAAI,QAAe,CAAC,GAAG,WAAW;AACvD,oBAAY,WAAW,MAAM;AAC3B,eAAK,KAAK;AACV,iBAAO,IAAI,MAAM,oCAAoC,CAAC;AAAA,QACxD,GAAG,GAAK;AAAA,MACV,CAAC;AAKD,YAAM,CAAC,UAAU,QAAQ,MAAM,IAAI,MAAM,QAAQ,KAAK;AAAA,QACpD,QAAQ,IAAI;AAAA,UACV,KAAK;AAAA,UACL,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,UAC/B,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,QACjC,CAAC;AAAA,QACD;AAAA,MACF,CAAC;AAGD,UAAI,WAAW;AACb,qBAAa,SAAS;AAAA,MACxB;AAEA,YAAM,SAAS,CAAC,QAAQ,MAAM,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK;AAEhE,UAAI,aAAa,GAAG;AAClB,eAAO,QAAQ,QAAQ;AAAA;AAAA,EAAO,UAAU,gCAAgC;AAAA,MAC1E;AAEA,aAAO,QAAQ,QAAQ;AAAA;AAAA,EAAO,UAAU,aAAa;AAAA,IACvD,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,aAAO,QAAQ,QAAQ;AAAA;AAAA,SAAc,OAAO;AAAA,IAC9C;AAAA,EACF;AACF,CAAC;;;AExHD,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,KAAAC,UAAS;AAyBlB,SAAS,UACP,SACA,WAAmB,SACnB,WAAmB,GACnB,eAAuB,GACV;AACb,QAAM,UAAuB,CAAC;AAE9B,MAAI;AACF,UAAM,QAAQC,IAAG,YAAY,OAAO;AAEpC,eAAW,QAAQ,OAAO;AACxB,YAAM,WAAWC,MAAK,KAAK,SAAS,IAAI;AACxC,YAAM,eAAeA,MAAK,SAAS,UAAU,QAAQ;AAErD,UAAI;AACF,cAAM,QAAQD,IAAG,UAAU,QAAQ;AACnC,YAAI;AACJ,YAAI;AAEJ,YAAI,MAAM,eAAe,GAAG;AAC1B,iBAAO;AACP,iBAAO;AAAA,QACT,WAAW,MAAM,YAAY,GAAG;AAC9B,iBAAO;AACP,iBAAO;AAAA,QACT,OAAO;AACL,iBAAO;AACP,iBAAO,MAAM;AAAA,QACf;AAEA,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,KAAK,MAAM,MAAM,MAAM,QAAQ,IAAI,GAAI;AAAA,QACnD,CAAC;AAGD,YAAI,SAAS,eAAe,eAAe,UAAU;AAEnD,cAAI;AACF,oCAAwB,QAAQ;AAChC,kBAAM,aAAa,UAAU,UAAU,UAAU,UAAU,eAAe,CAAC;AAC3E,oBAAQ,KAAK,GAAG,UAAU;AAAA,UAC5B,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,QAAQ;AAEN,WAAO,CAAC;AAAA,EACV;AAEA,SAAO;AACT;AASA,SAAS,UAAU,cAA8B;AAC/C,QAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACxC,QAAM,UAAU,MAAM;AAEtB,MAAI,UAAU,GAAI,QAAO,GAAG,OAAO;AACnC,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,MAAI,UAAU,GAAI,QAAO,GAAG,OAAO;AACnC,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,MAAI,QAAQ,GAAI,QAAO,GAAG,KAAK;AAC/B,QAAM,OAAO,KAAK,MAAM,QAAQ,EAAE;AAClC,MAAI,OAAO,EAAG,QAAO,GAAG,IAAI;AAC5B,QAAM,QAAQ,KAAK,MAAM,OAAO,CAAC;AACjC,MAAI,QAAQ,EAAG,QAAO,GAAG,KAAK;AAC9B,QAAM,SAAS,KAAK,MAAM,OAAO,EAAE;AACnC,MAAI,SAAS,GAAI,QAAO,GAAG,MAAM;AACjC,QAAM,QAAQ,KAAK,MAAM,OAAO,GAAG;AACnC,SAAO,GAAG,KAAK;AACjB;AAUA,SAAS,sBAAsB,SAA8B;AAC3D,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,EACT;AAGA,QAAM,gBAAgB,CAAC,GAAG,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM;AAChD,UAAM,YAAY,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,EAAE;AACtD,UAAM,cAAc,UAAU,EAAE,IAAI,IAAI,UAAU,EAAE,IAAI;AACxD,QAAI,gBAAgB,EAAG,QAAO;AAC9B,WAAO,EAAE,aAAa,cAAc,EAAE,YAAY;AAAA,EACpD,CAAC;AAGD,QAAM,WAA8C;AAAA,IAClD,WAAW;AAAA,IACX,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AAGA,QAAM,aAAa,CAAC,SAAiB,KAAK,QAAQ,OAAO,KAAK,EAAE,QAAQ,OAAO,KAAK;AAGpF,QAAM,SAAS;AACf,QAAM,OAAO,cAAc;AAAA,IACzB,CAAC,MAAM,GAAG,SAAS,EAAE,IAAI,CAAC,IAAI,WAAW,EAAE,YAAY,CAAC,IAAI,EAAE,IAAI,IAAI,UAAU,EAAE,QAAQ,CAAC;AAAA,EAC7F;AAEA,SAAO,CAAC,QAAQ,GAAG,IAAI,EAAE,KAAK,IAAI;AACpC;AAMO,IAAM,gBAAgB,aAAa;AAAA,EACxC,MAAM;AAAA,EACN,aACE;AAAA,EACF,QAAQE,GAAE,OAAO;AAAA,IACf,eAAeA,GAAE,OAAO,EAAE,QAAQ,GAAG,EAAE,SAAS,+BAA+B;AAAA,IAC/E,UAAUA,GACP,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,EAAE,EACN,QAAQ,CAAC,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU;AAAA,IACR;AAAA,MACE,QAAQ,EAAE,eAAe,KAAK,UAAU,EAAE;AAAA,MAC1C,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ,EAAE,eAAe,OAAO,UAAU,EAAE;AAAA,MAC5C,QACE;AAAA,MACF,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,SAAS,CAAC,EAAE,eAAe,SAAS,MAAM;AAExC,UAAM,gBAAgB,wBAAwB,aAAa;AAG3D,UAAM,QAAQF,IAAG,SAAS,aAAa;AACvC,QAAI,CAAC,MAAM,YAAY,GAAG;AACxB,YAAM,IAAI,MAAM,4BAA4B,aAAa,EAAE;AAAA,IAC7D;AAGA,UAAM,UAAU,UAAU,eAAe,eAAe,QAAQ;AAChE,UAAM,gBAAgB,sBAAsB,OAAO;AAGnD,WAAO,QAAQ,aAAa,aAAa,QAAQ;AAAA;AAAA,EAAO,aAAa;AAAA,EACvE;AACF,CAAC;;;AC7MD,OAAOG,SAAQ;AACf,SAAS,KAAAC,UAAS;AAQX,IAAMC,YAAW,aAAa;AAAA,EACnC,MAAM;AAAA,EACN,aACE;AAAA,EACF,QAAQC,GAAE,OAAO;AAAA,IACf,UAAUA,GAAE,OAAO,EAAE,SAAS,iDAAiD;AAAA,EACjF,CAAC;AAAA,EACD,UAAU;AAAA,IACR;AAAA,MACE,QAAQ,EAAE,UAAU,eAAe;AAAA,MACnC,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ,EAAE,UAAU,eAAe;AAAA,MACnC,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,SAAS,CAAC,EAAE,SAAS,MAAM;AAEzB,UAAM,gBAAgB,wBAAwB,QAAQ;AAGtD,UAAM,UAAUC,IAAG,aAAa,eAAe,OAAO;AAGtD,WAAO,QAAQ,QAAQ;AAAA;AAAA,EAAO,OAAO;AAAA,EACvC;AACF,CAAC;;;ACtCD,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,KAAAC,UAAS;AASX,IAAM,YAAY,aAAa;AAAA,EACpC,MAAM;AAAA,EACN,aACE;AAAA,EACF,QAAQC,GAAE,OAAO;AAAA,IACf,UAAUA,GAAE,OAAO,EAAE,SAAS,kDAAkD;AAAA,IAChF,SAASA,GAAE,OAAO,EAAE,SAAS,8BAA8B;AAAA,EAC7D,CAAC;AAAA,EACD,UAAU;AAAA,IACR;AAAA,MACE,QAAQ,EAAE,UAAU,cAAc,SAAS,gBAAgB;AAAA,MAC3D,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,QACN,UAAU;AAAA,QACV,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUX;AAAA,MACA,QAAQ;AAAA,MACR,SACE;AAAA,IACJ;AAAA,EACF;AAAA,EACA,SAAS,CAAC,EAAE,UAAU,QAAQ,MAAM;AAElC,UAAM,gBAAgB,wBAAwB,QAAQ;AAGtD,UAAM,YAAYC,MAAK,QAAQ,aAAa;AAC5C,QAAI,aAAa;AACjB,QAAI,CAACC,IAAG,WAAW,SAAS,GAAG;AAE7B,8BAAwB,SAAS;AACjC,MAAAA,IAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAC3C,mBAAa;AAAA,IACf;AAGA,IAAAA,IAAG,cAAc,eAAe,SAAS,OAAO;AAChD,UAAM,eAAe,OAAO,WAAW,SAAS,OAAO;AAGvD,UAAM,UAAU,aAAa,wBAAwBD,MAAK,QAAQ,QAAQ,CAAC,MAAM;AACjF,WAAO,QAAQ,QAAQ;AAAA;AAAA,QAAa,YAAY,SAAS,OAAO;AAAA,EAClE;AACF,CAAC;;;AClED,SAAS,KAAAE,UAAS;AAcX,IAAM,aAAa,aAAa;AAAA,EACrC,MAAM;AAAA,EACN,aACE;AAAA,EACF,QAAQC,GAAE,OAAO;AAAA,IACf,MAAMA,GACH,MAAMA,GAAE,OAAO,CAAC,EAChB,SAAS,2EAA2E;AAAA,IACvF,KAAKA,GACF,OAAO,EACP,SAAS,EACT,SAAS,gEAAgE;AAAA,IAC5E,SAASA,GAAE,OAAO,EAAE,QAAQ,GAAK,EAAE,SAAS,0CAA0C;AAAA,EACxF,CAAC;AAAA,EACD,UAAU;AAAA,IACR;AAAA,MACE,QAAQ,EAAE,MAAM,CAAC,MAAM,KAAK,GAAG,SAAS,IAAM;AAAA,MAC9C,QACE;AAAA,MACF,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ,EAAE,MAAM,CAAC,QAAQ,aAAa,GAAG,SAAS,IAAM;AAAA,MACxD,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ,EAAE,MAAM,CAAC,OAAO,iBAAiB,GAAG,SAAS,IAAM;AAAA,MAC3D,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ,EAAE,MAAM,CAAC,KAAK,GAAG,KAAK,QAAQ,SAAS,IAAM;AAAA,MACrD,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,MACA,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,MACA,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAAA,EACA,SAAS,OAAO,EAAE,MAAM,KAAK,QAAQ,MAAM;AACzC,UAAM,aAAa,OAAO,QAAQ,IAAI;AAEtC,QAAI,KAAK,WAAW,GAAG;AACrB,aAAO;AAAA,IACT;AAEA,QAAI;AAEJ,QAAI;AAEF,YAAM,OAAO,IAAI,MAAM,MAAM;AAAA,QAC3B,KAAK;AAAA,QACL,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC;AAGD,YAAM,iBAAiB,IAAI,QAAe,CAAC,GAAG,WAAW;AACvD,oBAAY,WAAW,MAAM;AAC3B,eAAK,KAAK;AACV,iBAAO,IAAI,MAAM,2BAA2B,OAAO,IAAI,CAAC;AAAA,QAC1D,GAAG,OAAO;AAAA,MACZ,CAAC;AAKD,YAAM,CAAC,UAAU,QAAQ,MAAM,IAAI,MAAM,QAAQ,KAAK;AAAA,QACpD,QAAQ,IAAI;AAAA,UACV,KAAK;AAAA,UACL,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,UAC/B,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAAA,QACjC,CAAC;AAAA,QACD;AAAA,MACF,CAAC;AAGD,UAAI,WAAW;AACb,qBAAa,SAAS;AAAA,MACxB;AAGA,YAAM,SAAS,CAAC,QAAQ,MAAM,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK;AAEhE,aAAO,UAAU,QAAQ;AAAA;AAAA,EAAO,UAAU,aAAa;AAAA,IACzD,SAAS,OAAO;AAEd,UAAI,WAAW;AACb,qBAAa,SAAS;AAAA,MACxB;AACA,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,aAAO;AAAA;AAAA,SAAsB,OAAO;AAAA,IACtC;AAAA,EACF;AACF,CAAC;;;ACzHM,IAAM,wBAAwD;AAAA,EACnE,eAAe;AAAA,EACf,UAAUC;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AACd;AAQO,SAAS,iBAAiB,MAA0C;AACzE,SAAO,sBAAsB,IAAI;AACnC;AAQO,SAAS,oBAAoB,MAAuB;AACzD,SAAO,QAAQ;AACjB;;;AChCA,SAAS,gBAA2B;AACpC,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAO,QAAQ;AACf,SAAS,qBAAqB;AAQ9B,IAAM,YAAYC,MAAK,KAAK,GAAG,QAAQ,GAAG,WAAW,cAAc;AAiD5D,SAAS,2BAA2B,WAA4B;AAErE,MAAI,0DAA0D,KAAK,SAAS,GAAG;AAC7E,WAAO;AAAA,EACT;AAEA,MAAI,UAAU,WAAW,MAAM,GAAG;AAChC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAcO,SAAS,qBAAqB,WAA2C;AAE9E,MAAI,UAAU,WAAW,MAAM,GAAG;AAChC,UAAM,MAAM,UAAU,MAAM,CAAC;AAC7B,UAAM,CAAC,SAAS,GAAG,IAAI,IAAI,MAAM,GAAG;AACpC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,IACX;AAAA,EACF;AAIA,QAAM,WAAW,UAAU;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,UAAU;AACZ,UAAM,CAAC,EAAE,KAAK,SAAS,QAAQ,UAAU,IAAI;AAC7C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,YAAY,MAA+B;AAClD,QAAM,gBAAgB,KAAK,UAAU,IAAI,KAAK,OAAO,KAAK;AAE1D,MAAI,KAAK,SAAS,OAAO;AACvB,WAAOA,MAAK,KAAK,WAAW,OAAO,GAAG,KAAK,OAAO,GAAG,aAAa,EAAE;AAAA,EACtE;AAEA,QAAM,eAAe,KAAK,QAAQ,QAAQ,SAAS,GAAG,EAAE,QAAQ,YAAY,EAAE;AAC9E,SAAOA,MAAK,KAAK,WAAW,OAAO,GAAG,YAAY,GAAG,aAAa,EAAE;AACtE;AAKA,SAAS,SAAS,UAA2B;AAC3C,QAAM,kBAAkBA,MAAK,KAAK,UAAU,cAAc;AAC1D,MAAI,CAACC,IAAG,WAAW,eAAe,GAAG;AACnC,WAAO;AAAA,EACT;AAGA,MAAI;AACF,UAAM,cAAc,KAAK,MAAMA,IAAG,aAAa,iBAAiB,OAAO,CAAC;AACxE,UAAM,aAAa,YAAY,QAAQ,WAAW;AAClD,UAAM,iBAAiBD,MAAK,KAAK,UAAU,UAAU;AACrD,QAAI,CAACC,IAAG,WAAW,cAAc,GAAG;AAClC,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAEN,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKA,eAAe,kBAAkB,MAAuB,UAAiC;AAEvF,EAAAA,IAAG,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;AAG1C,QAAM,cAAc;AAAA,IAClB,MAAM;AAAA,IACN,SAAS;AAAA,IACT,MAAM;AAAA,EACR;AACA,EAAAA,IAAG,cAAcD,MAAK,KAAK,UAAU,cAAc,GAAG,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;AAG1F,QAAM,cAAc,KAAK,UAAU,GAAG,KAAK,OAAO,IAAI,KAAK,OAAO,KAAK,KAAK;AAE5E,MAAI;AAEF,aAAS,YAAY,WAAW,KAAK;AAAA,MACnC,OAAO;AAAA,MACP,KAAK;AAAA,IACP,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,IAAI,MAAM,kCAAkC,WAAW,MAAM,OAAO,EAAE;AAAA,EAC9E;AACF;AAKA,eAAe,kBAAkB,MAAuB,UAAiC;AAEvF,EAAAC,IAAG,UAAUD,MAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAExD,MAAIC,IAAG,WAAW,QAAQ,GAAG;AAE3B,QAAI;AACF,eAAS,aAAa,EAAE,KAAK,UAAU,OAAO,OAAO,CAAC;AACtD,UAAI,KAAK,SAAS;AAChB,iBAAS,gBAAgB,KAAK,OAAO,IAAI,EAAE,KAAK,UAAU,OAAO,OAAO,CAAC;AAAA,MAC3E;AAAA,IACF,SAAS,OAAO;AAEd,MAAAA,IAAG,OAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,IACtD;AAAA,EACF;AAEA,MAAI,CAACA,IAAG,WAAW,QAAQ,GAAG;AAC5B,QAAI;AACF,YAAM,WAAW,KAAK,UAClB,sBAAsB,KAAK,OAAO,KAAK,KAAK,OAAO,MAAM,QAAQ,MACjE,cAAc,KAAK,OAAO,MAAM,QAAQ;AAC5C,eAAS,UAAU,EAAE,OAAO,OAAO,CAAC;AAAA,IACtC,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,YAAM,IAAI,MAAM,mCAAmC,KAAK,OAAO,MAAM,OAAO,EAAE;AAAA,IAChF;AAGA,QAAIA,IAAG,WAAWD,MAAK,KAAK,UAAU,cAAc,CAAC,GAAG;AACtD,UAAI;AACF,iBAAS,eAAe,EAAE,KAAK,UAAU,OAAO,UAAU,CAAC;AAAA,MAC7D,SAAS,OAAO;AACd,cAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,cAAM,IAAI,MAAM,uCAAuC,KAAK,OAAO,MAAM,OAAO,EAAE;AAAA,MACpF;AAGA,UAAI;AACF,cAAM,cAAc,KAAK,MAAMC,IAAG,aAAaD,MAAK,KAAK,UAAU,cAAc,GAAG,OAAO,CAAC;AAC5F,YAAI,YAAY,SAAS,OAAO;AAC9B,mBAAS,iBAAiB,EAAE,KAAK,UAAU,OAAO,UAAU,CAAC;AAAA,QAC/D;AAAA,MACF,SAAS,OAAO;AACd,cAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,cAAM,IAAI,MAAM,4BAA4B,KAAK,OAAO,MAAM,OAAO,EAAE;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,aAAa,YAA2C;AAC/D,QAAM,kBAAkBA,MAAK,KAAK,YAAY,cAAc;AAC5D,MAAI,CAACC,IAAG,WAAW,eAAe,GAAG;AACnC,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,cAAc,KAAK,MAAMA,IAAG,aAAa,iBAAiB,OAAO,CAAC;AACxE,WAAO,YAAY,UAAU;AAAA,EAC/B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,eAAe,UAAkB,aAA6B;AAErE,QAAM,kBAAkBD,MAAK,KAAK,UAAU,gBAAgB,WAAW;AACvE,MAAIC,IAAG,WAAW,eAAe,GAAG;AAClC,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AASA,eAAsB,oBACpB,WACA,eAAe,OACY;AAC3B,QAAM,OAAO,qBAAqB,SAAS;AAC3C,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,MAAM,uCAAuC,SAAS,EAAE;AAAA,EACpE;AAEA,QAAM,WAAW,YAAY,IAAI;AAGjC,MAAI,CAAC,SAAS,QAAQ,KAAK,cAAc;AACvC,QAAI,KAAK,SAAS,OAAO;AACvB,YAAM,kBAAkB,MAAM,QAAQ;AAAA,IACxC,OAAO;AACL,YAAM,kBAAkB,MAAM,QAAQ;AAAA,IACxC;AAAA,EACF;AAGA,QAAM,cAAc,eAAe,UAAU,KAAK,OAAO;AAGzD,QAAM,WAAW,aAAa,WAAW;AAGzC,MAAI;AACJ,MAAI,cAA+B;AAEnC,MAAI,KAAK,YAAY;AAEnB,kBAAc,CAAC,KAAK,UAAU;AAE9B,QAAI,UAAU,YAAY,KAAK,UAAU,GAAG;AAC1C,mBAAa,SAAS,UAAU,KAAK,UAAU,EAAE;AAAA,IACnD,OAAO;AACL,mBAAa,UAAU,WAAW;AAAA,IACpC;AAAA,EACF,WAAW,KAAK,QAAQ;AAEtB,QAAI,CAAC,UAAU,UAAU,KAAK,MAAM,GAAG;AACrC,YAAM,IAAI,MAAM,mBAAmB,KAAK,MAAM,iBAAiB,KAAK,OAAO,GAAG;AAAA,IAChF;AACA,UAAM,SAAS,SAAS,QAAQ,KAAK,MAAM;AAC3C,QAAI,WAAW,KAAK;AAElB,oBAAc;AAAA,IAChB,OAAO;AACL,oBAAc;AAAA,IAChB;AACA,iBAAa,UAAU,WAAW;AAAA,EACpC,OAAO;AAEL,iBAAa,UAAU,WAAW;AAAA,EACpC;AAGA,QAAM,qBAAqBD,MAAK,QAAQ,aAAa,UAAU;AAC/D,MAAI,CAACC,IAAG,WAAW,kBAAkB,GAAG;AACtC,UAAM,IAAI;AAAA,MACR,0BAA0B,kBAAkB;AAAA,IAE9C;AAAA,EACF;AAGA,QAAM,YAAY,cAAc,kBAAkB,EAAE;AACpD,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,OAAO;AAAA,EACzB,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,IAAI,MAAM,qBAAqB,SAAS,MAAM,OAAO,EAAE;AAAA,EAC/D;AAGA,MAAI,UAAU,yBAAyB,OAAO;AAG9C,MAAI,aAAa;AACf,UAAM,YAAY,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;AACjE,cAAU,QAAQ,OAAO,CAAC,MAAM;AAC9B,YAAM,OAAO,EAAE,MAAM,YAAY,KAAK;AACtC,aAAO,UAAU,IAAI,IAAI;AAAA,IAC3B,CAAC;AAGD,UAAM,aAAa,IAAI,IAAI,QAAQ,IAAI,CAAC,MAAM,EAAE,MAAM,YAAY,KAAK,EAAE,CAAC;AAC1E,eAAW,aAAa,aAAa;AACnC,UAAI,CAAC,WAAW,IAAI,UAAU,YAAY,CAAC,GAAG;AAC5C,cAAM,IAAI,MAAM,WAAW,SAAS,2BAA2B,KAAK,OAAO,GAAG;AAAA,MAChF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB,UAAM,IAAI,MAAM,gCAAgC,KAAK,OAAO,GAAG;AAAA,EACjE;AAEA,SAAO;AACT;;;ARxXA,IAAM,gBAAgB,CAAC,KAAK,KAAK,GAAG;AACpC,IAAM,iBAAiB;AAOvB,SAAS,aAAa,OAAyC;AAC7D,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,MAAM;AACZ,SACE,OAAO,IAAI,YAAY,cACvB,OAAO,IAAI,gBAAgB,aAC1B,qBAAqB,OAAO,YAAY;AAE7C;AAUA,SAAS,oBAAoB,OAAmD;AAC9E,MAAI,OAAO,UAAU,YAAY;AAC/B,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,MAAM;AACxB,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAGA,MAAI,qBAAqB,gBAAgB;AACvC,WAAO;AAAA,EACT;AAIA,QAAM,QAAQ;AACd,MAAI,OAAO,MAAM,YAAY,YAAY;AACvC,WAAO;AAAA,EACT;AAGA,SAAO,aAAa,SAAS;AAC/B;AAQA,SAAS,eAAe,OAAuB;AAC7C,MAAI,CAAC,MAAM,WAAW,GAAG,GAAG;AAC1B,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,QAAQ,IAAI;AACzB,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,SAAOC,MAAK,KAAK,MAAM,MAAM,MAAM,CAAC,CAAC;AACvC;AASA,SAAS,oBAAoB,WAA4B;AACvD,SACE,cAAc,KAAK,CAAC,WAAW,UAAU,WAAW,MAAM,CAAC,KAAK,UAAU,SAASA,MAAK,GAAG;AAE/F;AAUO,SAAS,kBAAkB,WAA0C;AAE1E,MAAI,UAAU,WAAW,cAAc,GAAG;AACxC,UAAM,OAAO,UAAU,MAAM,eAAe,MAAM;AAClD,UAAM,SAAS,iBAAiB,IAAI;AACpC,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR,2BAA2B,IAAI;AAAA,MACjC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,oBAAoB,SAAS,KAAK,oBAAoB,SAAS,GAAG;AACrE,WAAO,iBAAiB,SAAS;AAAA,EACnC;AAEA,SAAO;AACT;AAWO,SAAS,uBAAuB,WAAmB,KAAqB;AAC7E,MAAI,CAAC,oBAAoB,SAAS,GAAG;AACnC,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,eAAe,SAAS;AACzC,QAAM,eAAeA,MAAK,QAAQ,KAAK,QAAQ;AAC/C,MAAI,CAACC,IAAG,WAAW,YAAY,GAAG;AAChC,UAAM,IAAI,MAAM,8BAA8B,YAAY,EAAE;AAAA,EAC9D;AACA,SAAOC,eAAc,YAAY,EAAE;AACrC;AAUO,SAAS,yBAAyB,eAA0C;AACjF,QAAM,UAA4B,CAAC;AACnC,QAAM,UAAU,oBAAI,IAAa;AAEjC,QAAM,QAAQ,CAAC,UAAmB;AAChC,QAAI,UAAU,UAAa,UAAU,MAAM;AACzC;AAAA,IACF;AAEA,QAAI,QAAQ,IAAI,KAAK,GAAG;AACtB;AAAA,IACF;AACA,YAAQ,IAAI,KAAK;AAGjB,QAAI,iBAAiB,kBAAkB,aAAa,KAAK,GAAG;AAC1D,cAAQ,KAAK,KAAuB;AACpC;AAAA,IACF;AAEA,QAAI,oBAAoB,KAAK,GAAG;AAC9B,cAAQ,KAAK,IAAI,MAAM,CAAC;AACxB;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,iBAAW,SAAS,OAAO;AACzB,cAAM,KAAK;AAAA,MACb;AACA;AAAA,IACF;AAEA,QAAI,OAAO,UAAU,UAAU;AAC7B,iBAAW,SAAS,OAAO,OAAO,KAAgC,GAAG;AACnE,cAAM,KAAK;AAAA,MACb;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa;AACnB,SAAO;AACT;AAwBA,eAAsB,YACpB,YACA,KACA,WAAiC,CAAC,cAAc,OAAO,YAC5B;AAC3B,QAAM,UAA4B,CAAC;AAEnC,QAAM,uBAAuB,SAAS,SAAS,EAAE,SAAS,mBAAmB;AAE7E,aAAW,aAAa,YAAY;AAElC,UAAM,UAAU,kBAAkB,SAAS;AAC3C,QAAI,SAAS;AACX,cAAQ,KAAK,OAAO;AACpB;AAAA,IACF;AAIA,QAAI,wBAAwB,2BAA2B,SAAS,GAAG;AACjE,UAAI;AACF,cAAM,kBAAkB,MAAM,oBAAoB,SAAS;AAC3D,gBAAQ,KAAK,GAAG,eAAe;AAC/B;AAAA,MACF,SAAS,OAAO;AACd,cAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,cAAM,IAAI,MAAM,oCAAoC,SAAS,MAAM,OAAO,EAAE;AAAA,MAC9E;AAAA,IACF;AAGA,UAAM,WAAW,uBAAuB,WAAW,GAAG;AACtD,QAAI;AACJ,QAAI;AACF,gBAAU,MAAM,SAAS,QAAQ;AAAA,IACnC,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,YAAM,IAAI,MAAM,iCAAiC,SAAS,MAAM,OAAO,EAAE;AAAA,IAC3E;AAEA,QAAI;AACJ,QAAI;AACF,kBAAY,yBAAyB,OAAO;AAAA,IAC9C,SAAS,OAAO;AACd,YAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,YAAM,IAAI,MAAM,6CAA6C,SAAS,MAAM,OAAO,EAAE;AAAA,IACvF;AACA,QAAI,UAAU,WAAW,GAAG;AAC1B,YAAM,IAAI,MAAM,WAAW,SAAS,yCAAyC;AAAA,IAC/E;AACA,YAAQ,KAAK,GAAG,SAAS;AAAA,EAC3B;AAEA,SAAO;AACT;;;ASjRA;AAJA,SAAS,OAAO,aAAAC,kBAAiB;AACjC,SAAS,eAAe;AACxB,SAAS,YAAY;AAOd,IAAM,sBAAsB,KAAK,QAAQ,GAAG,WAAW,MAAM;AAQ7D,SAAS,cACd,QACA,QACoB;AACpB,MAAI,WAAW,MAAM;AACnB,WAAO,KAAK,qBAAqB,MAAM;AAAA,EACzC;AACA,MAAI,OAAO,WAAW,UAAU;AAC9B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAKO,SAAS,iBAAiB,UAAgC;AAC/D,QAAM,QAAkB,CAAC;AACzB,aAAW,OAAO,UAAU;AAC1B,UAAM,KAAK,OAAO,IAAI,KAAK,YAAY,CAAC,MAAM;AAE9C,UAAM,KAAK,IAAI,UAAU,mBAAmB,IAAI,OAAO,IAAI,EAAE;AAC7D,UAAM,KAAK,EAAE;AAAA,EACf;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAKA,eAAsB,aAAa,KAAa,UAAkB,SAAgC;AAChG,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,QAAMA,WAAU,KAAK,KAAK,QAAQ,GAAG,SAAS,OAAO;AACvD;AAMO,SAAS,uBAAuB,OAAa,oBAAI,KAAK,GAAW;AACtE,QAAM,MAAM,CAAC,MAAc,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AACvD,QAAM,OAAO,KAAK,YAAY;AAC9B,QAAM,QAAQ,IAAI,KAAK,SAAS,IAAI,CAAC;AACrC,QAAM,MAAM,IAAI,KAAK,QAAQ,CAAC;AAC9B,QAAM,QAAQ,IAAI,KAAK,SAAS,CAAC;AACjC,QAAM,UAAU,IAAI,KAAK,WAAW,CAAC;AACrC,QAAM,UAAU,IAAI,KAAK,WAAW,CAAC;AACrC,SAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG,IAAI,KAAK,IAAI,OAAO,IAAI,OAAO;AAC/D;AAMA,eAAsB,iBAAiB,SAA8C;AACnF,QAAM,YAAY,uBAAuB;AACzC,QAAM,aAAa,KAAK,SAAS,SAAS;AAC1C,MAAI;AACF,UAAM,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAC3C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,KAAK,oDAAoD,UAAU,IAAI,KAAK;AACpF,WAAO;AAAA,EACT;AACF;AAMO,SAAS,iBAAiB,GAAmB;AAClD,SAAO,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AACrC;;;ACpFA;AALA,OAAOC,YAAW;AAClB,SAAS,4BAA4B;;;ACcrC,OAAO,WAAW;AAClB,SAA+B,cAAc;AAC7C,SAAS,sBAAsB;AA+JxB,SAAS,aAAa,QAAwB;AACnD,SAAO,UAAU,MAAO,IAAI,SAAS,KAAM,QAAQ,CAAC,CAAC,MAAM,GAAG,MAAM;AACtE;AAsBO,SAAS,WAAW,MAAsB;AAC/C,MAAI,OAAO,MAAO;AAChB,WAAO,KAAK,QAAQ,CAAC;AAAA,EACvB;AACA,MAAI,OAAO,MAAM;AACf,WAAO,KAAK,QAAQ,CAAC;AAAA,EACvB;AACA,MAAI,OAAO,GAAG;AACZ,WAAO,KAAK,QAAQ,CAAC;AAAA,EACvB;AACA,SAAO,KAAK,QAAQ,CAAC;AACvB;AAmIO,SAAS,kBAAkB,MAAkC;AAClE,QAAM,QAAkB,CAAC;AAIzB,MAAI;AACJ,MAAI,KAAK,qBAAqB,UAAa,KAAK,oBAAoB;AAElE,iBAAa,IAAI,KAAK,gBAAgB,IAAI,KAAK,kBAAkB,IAAI,KAAK,SAAS;AAAA,EACrF,WAAW,KAAK,qBAAqB,QAAW;AAE9C,iBAAa,IAAI,KAAK,gBAAgB,IAAI,KAAK,SAAS;AAAA,EAC1D,OAAO;AAEL,iBAAa,IAAI,KAAK,SAAS;AAAA,EACjC;AACA,QAAM,KAAK,GAAG,MAAM,KAAK,UAAU,CAAC,IAAI,MAAM,QAAQ,KAAK,KAAK,CAAC,EAAE;AAGnE,MAAI,KAAK,mBAAmB,UAAa,KAAK,mBAAmB,MAAM;AACrE,UAAM,YAAY,GAAG,KAAK,MAAM,KAAK,cAAc,CAAC;AACpD,QAAI,KAAK,kBAAkB,IAAI;AAC7B,YAAM,KAAK,MAAM,IAAI,SAAS,CAAC;AAAA,IACjC,WAAW,KAAK,kBAAkB,IAAI;AACpC,YAAM,KAAK,MAAM,OAAO,SAAS,CAAC;AAAA,IACpC,OAAO;AACL,YAAM,KAAK,MAAM,MAAM,SAAS,CAAC;AAAA,IACnC;AAAA,EACF;AAGA,MAAI,KAAK,eAAe,KAAK,cAAc,GAAG;AAC5C,UAAM,SAAS,KAAK,WAAW,QAAQ,MAAM;AAC7C,UAAM,KAAK,MAAM,IAAI,QAAG,IAAI,MAAM,OAAO,IAAI,MAAM,GAAG,aAAa,KAAK,WAAW,CAAC,EAAE,CAAC;AAAA,EACzF;AAGA,MAAI,KAAK,qBAAqB,KAAK,oBAAoB,GAAG;AACxD,UAAM,KAAK,MAAM,IAAI,QAAG,IAAI,MAAM,KAAK,IAAI,aAAa,KAAK,iBAAiB,CAAC,EAAE,CAAC;AAAA,EACpF;AAGA,MAAI,KAAK,iBAAiB,UAAa,KAAK,eAAe,KAAK,KAAK,aAAa;AAChF,UAAM,SAAS,KAAK,WAAW,SAAS,MAAM;AAC9C,UAAM,KAAK,MAAM,IAAI,QAAG,IAAI,MAAM,MAAM,IAAI,MAAM,GAAG,aAAa,KAAK,gBAAgB,CAAC,CAAC,EAAE,CAAC;AAAA,EAC9F;AAGA,QAAM,KAAK,MAAM,IAAI,GAAG,KAAK,eAAe,QAAQ,CAAC,CAAC,GAAG,CAAC;AAG1D,MAAI,KAAK,SAAS,UAAa,KAAK,OAAO,GAAG;AAC5C,UAAM,KAAK,MAAM,KAAK,IAAI,WAAW,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,EACpD;AAIA,MAAI,CAAC,KAAK,eAAe,KAAK,iBAAiB,QAAW;AACxD,UAAM,SAAS,KAAK,gBAAgB;AAEpC,QAAI,WAAW,UAAU,WAAW,YAAY;AAC9C,YAAM,KAAK,MAAM,MAAM,OAAO,YAAY,CAAC,CAAC;AAAA,IAC9C,OAAO;AACL,YAAM,KAAK,MAAM,OAAO,OAAO,YAAY,CAAC,CAAC;AAAA,IAC/C;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC;AAGxC,MAAI,KAAK,eAAe,KAAK,SAAS;AACpC,WAAO,GAAG,MAAM,KAAK,KAAK,OAAO,CAAC,IAAI,IAAI;AAAA,EAC5C;AAGA,MAAI,CAAC,KAAK,aAAa;AACrB,WAAO,GAAG,MAAM,MAAM,QAAG,CAAC,IAAI,IAAI;AAAA,EACpC;AAEA,SAAO;AACT;AAgEO,SAAS,cAAc,UAA0C;AACtE,QAAM,QAAkB,CAAC;AAGzB,MAAI,SAAS,eAAe,QAAW;AACrC,UAAM,WAAW,MAAM,KAAK,IAAI,SAAS,UAAU,EAAE;AACrD,QAAI,SAAS,OAAO;AAClB,YAAM,KAAK,GAAG,QAAQ,IAAI,MAAM,QAAQ,SAAS,KAAK,CAAC,EAAE;AAAA,IAC3D,OAAO;AACL,YAAM,KAAK,QAAQ;AAAA,IACrB;AAAA,EACF,WAAW,SAAS,OAAO;AAEzB,UAAM,KAAK,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,EAC1C;AAGA,MAAI,SAAS,OAAO;AAClB,UAAM,EAAE,aAAa,cAAc,mBAAmB,yBAAyB,IAC7E,SAAS;AACX,UAAM,KAAK,MAAM,IAAI,QAAG,IAAI,MAAM,OAAO,IAAI,aAAa,WAAW,CAAC,EAAE,CAAC;AAEzE,QAAI,qBAAqB,oBAAoB,GAAG;AAC9C,YAAM,KAAK,MAAM,IAAI,QAAG,IAAI,MAAM,KAAK,IAAI,aAAa,iBAAiB,CAAC,EAAE,CAAC;AAAA,IAC/E;AAEA,QAAI,4BAA4B,2BAA2B,GAAG;AAC5D,YAAM,KAAK,MAAM,IAAI,QAAG,IAAI,MAAM,QAAQ,IAAI,aAAa,wBAAwB,CAAC,EAAE,CAAC;AAAA,IACzF;AACA,UAAM,KAAK,MAAM,IAAI,QAAG,IAAI,MAAM,MAAM,IAAI,aAAa,YAAY,CAAC,EAAE,CAAC;AAAA,EAC3E;AAGA,MAAI,SAAS,mBAAmB,UAAa,SAAS,iBAAiB,GAAG;AACxE,UAAM,KAAK,MAAM,IAAI,GAAG,SAAS,cAAc,GAAG,CAAC;AAAA,EACrD;AAGA,MAAI,SAAS,SAAS,UAAa,SAAS,OAAO,GAAG;AACpD,UAAM,KAAK,MAAM,KAAK,IAAI,WAAW,SAAS,IAAI,CAAC,EAAE,CAAC;AAAA,EACxD;AAGA,MAAI,SAAS,cAAc;AACzB,UAAM,KAAK,MAAM,IAAI,SAAS,YAAY,CAAC;AAAA,EAC7C;AAGA,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AAGA,SAAO,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC;AACpC;AAyKA,SAAS,YAAY,OAAwB;AAC3C,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,aAAa,OAAO,UAAU,UAAU;AAC3D,WAAO,OAAO,KAAK;AAAA,EACrB;AACA,SAAO,KAAK,UAAU,KAAK;AAC7B;AAOO,SAAS,cAAc,KAAa,QAAwB;AACjE,MAAI,UAAU,EAAG,QAAO;AACxB,MAAI,IAAI,UAAU,OAAQ,QAAO;AAEjC,SAAO,GAAG,IAAI,MAAM,GAAG,SAAS,CAAC,CAAC;AACpC;AAUO,SAAS,uBACd,QACA,UACQ;AACR,MAAI,CAAC,UAAU,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;AAC/C,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,OAAO,QAAQ,MAAM;AACrC,QAAM,eAAe;AAGrB,QAAM,YAAY,QAAQ,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,YAAY,KAAK,CAAC;AAG/D,QAAM,WAAW,QAAQ,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,MAAM;AACjD,WAAO,MAAM,IAAI,SAAS,KAAK,IAAI,IAAI,IAAI;AAAA,EAC7C,GAAG,CAAC;AAGJ,MAAI;AAEJ,MAAI,YAAY,WAAW,UAAU;AACnC,UAAM,qBAAqB,WAAW;AACtC,UAAM,iBAAiB,UAAU,OAAO,CAAC,KAAK,MAAM,MAAM,EAAE,QAAQ,CAAC;AAErE,QAAI,kBAAkB,oBAAoB;AAExC,eAAS,UAAU,IAAI,MAAM,QAAQ;AAAA,IACvC,OAAO;AAEL,YAAM,cAAc;AACpB,YAAM,WAAW,QAAQ,SAAS;AAElC,UAAI,sBAAsB,UAAU;AAElC,iBAAS,UAAU,IAAI,MAAM,KAAK,IAAI,GAAG,KAAK,MAAM,qBAAqB,QAAQ,MAAM,CAAC,CAAC;AAAA,MAC3F,OAAO;AAEL,iBAAS,UAAU,IAAI,CAAC,MAAM;AAC5B,gBAAM,aAAa,EAAE,SAAS;AAC9B,iBAAO,KAAK,IAAI,aAAa,KAAK,MAAM,aAAa,kBAAkB,CAAC;AAAA,QAC1E,CAAC;AAID,cAAM,cAAc,OAAO,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC;AACxD,YAAI,cAAc,oBAAoB;AAEpC,gBAAM,QAAQ,qBAAqB;AACnC,mBAAS,OAAO,IAAI,CAAC,MAAM,KAAK,IAAI,GAAG,KAAK,MAAM,IAAI,KAAK,CAAC,CAAC;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAAA,EACF,OAAO;AAEL,aAAS,UAAU,IAAI,MAAM,YAAY;AAAA,EAC3C;AAGA,SAAO,QACJ,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,MAAM;AACpB,UAAM,YAAY,cAAc,UAAU,CAAC,GAAG,OAAO,CAAC,CAAC;AACvD,WAAO,GAAG,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,KAAK,SAAS,CAAC;AAAA,EACnE,CAAC,EACA,KAAK,MAAM,IAAI,IAAI,CAAC;AACzB;AAwJO,SAAS,iBAAiB,MAAyB,UAA2B;AAEnF,QAAM,gBAAgB,YAAY,QAAQ,OAAO,WAAW;AAE5D,QAAM,cAAc,MAAM,QAAQ,KAAK,KAAK,IAAI;AAChD,QAAM,UAAU,GAAG,KAAK,eAAe,QAAQ,CAAC,CAAC;AACjD,QAAM,YAAY,MAAM,IAAI,OAAO;AAInC,QAAM,cAAc,IAAI,KAAK,KAAK,SAAS,IAAI,IAAI,QAAQ;AAC3D,QAAM,qBAAqB,KAAK,IAAI,IAAI,gBAAgB,cAAc,CAAC;AAGvE,QAAM,YAAY,uBAAuB,KAAK,YAAY,kBAAkB;AAC5E,QAAM,cAAc,YAAY,GAAG,MAAM,IAAI,GAAG,CAAC,GAAG,SAAS,GAAG,MAAM,IAAI,GAAG,CAAC,KAAK;AAGnF,MAAI,KAAK,OAAO;AACd,UAAM,WAAW,KAAK,MAAM,SAAS,KAAK,GAAG,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,WAAM,KAAK;AAC/E,WAAO,GAAG,MAAM,IAAI,QAAG,CAAC,IAAI,WAAW,GAAG,WAAW,IAAI,MAAM,IAAI,QAAQ,CAAC,IAAI,QAAQ,IAAI,SAAS;AAAA,EACvG;AAKA,MAAI,CAAC,KAAK,YAAY;AACpB,UAAM,QAAkB,CAAC;AAGzB,QAAI,KAAK,uBAAuB,KAAK,sBAAsB,GAAG;AAC5D,YAAM,KAAK,MAAM,IAAI,QAAG,IAAI,MAAM,OAAO,IAAI,aAAa,KAAK,mBAAmB,CAAC,EAAE,CAAC;AAAA,IACxF;AACA,QAAI,KAAK,wBAAwB,KAAK,uBAAuB,GAAG;AAC9D,YAAM,KAAK,MAAM,IAAI,QAAG,IAAI,MAAM,MAAM,IAAI,aAAa,KAAK,oBAAoB,CAAC,EAAE,CAAC;AAAA,IACxF;AACA,QAAI,KAAK,gBAAgB,KAAK,eAAe,GAAG;AAC9C,YAAM,KAAK,MAAM,KAAK,IAAI,WAAW,KAAK,YAAY,CAAC,EAAE,CAAC;AAAA,IAC5D;AAGA,UAAM,KAAK,MAAM,IAAI,GAAG,KAAK,eAAe,QAAQ,CAAC,CAAC,GAAG,CAAC;AAE1D,UAAM,aAAa,MAAM,SAAS,IAAI,IAAI,MAAM,KAAK,MAAM,IAAI,KAAK,CAAC,CAAC,KAAK;AAC3E,WAAO,GAAG,MAAM,KAAK,QAAG,CAAC,IAAI,WAAW,GAAG,UAAU;AAAA,EACvD;AAKA,MAAI;AACJ,MAAI,KAAK,eAAe,UAAa,KAAK,aAAa,GAAG;AAExD,kBAAc,MAAM,IAAI,QAAG,IAAI,MAAM,MAAM,IAAI,aAAa,KAAK,UAAU,CAAC,GAAG;AAAA,EACjF,WAAW,KAAK,gBAAgB,UAAa,KAAK,cAAc,GAAG;AACjE,kBAAc,MAAM,MAAM,YAAY,KAAK,WAAW,CAAC,IAAI;AAAA,EAC7D,OAAO;AACL,kBAAc;AAAA,EAChB;AAGA,QAAM,aAAa,KAAK,aAAa,MAAM,OAAO,QAAG,IAAI,MAAM,MAAM,QAAG;AACxE,QAAM,UAAU,MAAM,QAAQ,KAAK,IAAI;AAEvC,QAAM,QAAQ,GAAG,MAAM,IAAI,QAAG,CAAC,IAAI,WAAW,GAAG,WAAW;AAI5D,QAAM,cAAc,KAAK,UAAU,IAAI,OAAO,IAAI,WAAW;AAC7D,QAAM,QAAQ,GAAG,WAAW,GAAG,SAAS;AAExC,SAAO,GAAG,KAAK;AAAA,EAAK,KAAK;AAC3B;AAQA,SAAS,YAAY,OAAuB;AAC1C,MAAI,QAAQ,MAAM;AAChB,WAAO,GAAG,KAAK;AAAA,EACjB;AACA,MAAI,QAAQ,OAAO,MAAM;AACvB,WAAO,IAAI,QAAQ,MAAM,QAAQ,CAAC,CAAC;AAAA,EACrC;AACA,SAAO,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC9C;;;AD3/BO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AACF,GAAoD;AAClD,SAAO,CAAC,UAAkB;AACxB,UAAM,SAAS,OAAO,KAAK;AAC3B,QAAI,OAAO,MAAM,MAAM,GAAG;AACxB,YAAM,IAAI,qBAAqB,GAAG,KAAK,oBAAoB;AAAA,IAC7D;AAEA,QAAI,WAAW,CAAC,OAAO,UAAU,MAAM,GAAG;AACxC,YAAM,IAAI,qBAAqB,GAAG,KAAK,sBAAsB;AAAA,IAC/D;AAEA,QAAI,QAAQ,UAAa,SAAS,KAAK;AACrC,YAAM,IAAI,qBAAqB,GAAG,KAAK,qCAAqC,GAAG,GAAG;AAAA,IACpF;AAEA,QAAI,QAAQ,UAAa,SAAS,KAAK;AACrC,YAAM,IAAI,qBAAqB,GAAG,KAAK,kCAAkC,GAAG,GAAG;AAAA,IACjF;AAEA,WAAO;AAAA,EACT;AACF;AAMO,IAAM,gBAAN,MAAoB;AAAA,EAGzB,YAA6B,QAA+B;AAA/B;AAAA,EAAgC;AAAA,EAFrD,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAS3B,MAAMC,OAAoB;AACxB,QAAI,CAACA,OAAM;AACT;AAAA,IACF;AACA,SAAK,OAAO,MAAMA,KAAI;AACtB,SAAK,mBAAmBA,MAAK,SAAS,IAAI;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAsB;AACpB,QAAI,CAAC,KAAK,kBAAkB;AAC1B,WAAK,OAAO,MAAM,IAAI;AACtB,WAAK,mBAAmB;AAAA,IAC1B;AAAA,EACF;AACF;AAQO,SAAS,cAAc,QAAiC;AAC7D,SAAO,QAAQ,OAAO,KAAK;AAC7B;AA2KA,IAAM,iBAAiB,CAAC,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,QAAG;AACxE,IAAM,mBAAmB;AAelB,IAAM,iBAAN,MAAqB;AAAA,EAiF1B,YACmB,QACA,OACA,eACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA;AAAA,EAnFK,aAAa;AAAA,EACb,WAAkD;AAAA,EAClD,eAAqD;AAAA,EACrD,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,sBAAsB;AAAA;AAAA;AAAA,EAGtB,OAAqB;AAAA,EACrB,QAAQ;AAAA,EACR,gBAAgB,KAAK,IAAI;AAAA,EACzB,kBAAkB;AAAA,EAClB,2BAA2B;AAAA,EAC3B,mBAAmB;AAAA,EACnB,4BAA4B;AAAA,EAC5B,kBAAkB;AAAA,EAClB,cAAc;AAAA;AAAA,EAEd,wBAAwB;AAAA,EACxB,+BAA+B;AAAA;AAAA,EAG/B,iBAAiB,KAAK,IAAI;AAAA,EAC1B,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,mBAAmB;AAAA;AAAA,EAGnB,kBASJ,oBAAI,IAAI;AAAA;AAAA,EAGJ,eAsBJ,oBAAI,IAAI;AAAA;AAAA,EAGJ,gBAWJ,oBAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,EAYZ,UAAU,cAAsB,MAAc,QAAwC;AACpF,SAAK,gBAAgB,IAAI,cAAc,EAAE,MAAM,QAAQ,WAAW,KAAK,IAAI,EAAE,CAAC;AAE9E,QAAI,KAAK,aAAa,KAAK,OAAO;AAChC,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,cAA4B;AACvC,SAAK,gBAAgB,OAAO,YAAY;AAExC,QAAI,KAAK,aAAa,KAAK,OAAO;AAChC,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,qBAA8B;AAC5B,WAAO,KAAK,gBAAgB,OAAO;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,cAAsB;AAC9B,WAAO,KAAK,gBAAgB,IAAI,YAAY;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAe,cAA4B;AACzC,UAAM,SAAS,KAAK,gBAAgB,IAAI,YAAY;AACpD,QAAI,QAAQ;AACV,aAAO,YAAY;AACnB,aAAO,gBAAgB,KAAK,IAAI;AAChC,UAAI,KAAK,aAAa,KAAK,OAAO;AAChC,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,wBAA8B;AAC5B,eAAW,CAAC,IAAI,MAAM,KAAK,KAAK,iBAAiB;AAC/C,UAAI,OAAO,WAAW;AACpB,aAAK,gBAAgB,OAAO,EAAE;AAE9B,mBAAW,CAAC,UAAU,MAAM,KAAK,KAAK,cAAc;AAClD,cAAI,OAAO,uBAAuB,IAAI;AACpC,iBAAK,aAAa,OAAO,QAAQ;AAAA,UACnC;AAAA,QACF;AACA,mBAAW,CAAC,UAAU,MAAM,KAAK,KAAK,eAAe;AACnD,cAAI,OAAO,uBAAuB,IAAI;AACpC,iBAAK,cAAc,OAAO,QAAQ;AAAA,UACpC;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QAAI,KAAK,aAAa,KAAK,OAAO;AAChC,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,eACE,IACA,oBACA,OACA,OACA,WACA,MAIA,kBACA,oBACM;AACN,SAAK,aAAa,IAAI,IAAI;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,MACpB,aAAa,MAAM;AAAA,MACnB,mBAAmB,MAAM;AAAA,IAC3B,CAAC;AACD,QAAI,KAAK,aAAa,KAAK,OAAO;AAChC,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,kBACE,IACA,MAQM;AACN,UAAM,QAAQ,KAAK,aAAa,IAAI,EAAE;AACtC,QAAI,OAAO;AAET,UAAI,KAAK,gBAAgB,OAAW,OAAM,cAAc,KAAK;AAC7D,UAAI,KAAK,iBAAiB,OAAW,OAAM,eAAe,KAAK;AAC/D,UAAI,KAAK,sBAAsB,OAAW,OAAM,oBAAoB,KAAK;AACzE,UAAI,KAAK,6BAA6B;AACpC,cAAM,2BAA2B,KAAK;AACxC,UAAI,KAAK,iBAAiB,OAAW,OAAM,eAAe,KAAK;AAG/D,UAAI,KAAK,SAAS,QAAW;AAC3B,cAAM,OAAO,KAAK;AAAA,MACpB,WAAW,KAAK,iBAAiB,MAAM,SAAS,MAAM,cAAc;AAGlE,YAAI;AACF,gBAAM,YAAY,MAAM,MAAM,SAAS,GAAG,IAAI,MAAM,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,MAAM;AAChF,gBAAM,aAAa,KAAK,cAAc;AAAA,YACpC;AAAA,YACA,MAAM,eAAe;AAAA,YACrB,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,UACR;AACA,gBAAM,OAAO,YAAY;AAAA,QAC3B,QAAQ;AAAA,QAER;AAAA,MACF;AAEA,YAAM,YAAY;AAClB,YAAM,gBAAgB,KAAK,IAAI;AAC/B,UAAI,KAAK,aAAa,KAAK,OAAO;AAChC,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,kBAAkB,IAAkB;AAClC,SAAK,aAAa,OAAO,EAAE;AAC3B,QAAI,KAAK,aAAa,KAAK,OAAO;AAChC,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,IAAY;AACzB,WAAO,KAAK,aAAa,IAAI,EAAE;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,6BAA6B,oBAM3B;AACA,QAAI,cAAc;AAClB,QAAI,eAAe;AACnB,QAAI,oBAAoB;AACxB,QAAI,OAAO;AACX,QAAI,YAAY;AAEhB,eAAW,CAAC,EAAE,MAAM,KAAK,KAAK,cAAc;AAC1C,UAAI,OAAO,uBAAuB,oBAAoB;AACpD,uBAAe,OAAO,eAAe;AACrC,wBAAgB,OAAO,gBAAgB;AACvC,6BAAqB,OAAO,qBAAqB;AACjD,gBAAQ,OAAO,QAAQ;AACvB;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,aAAa,cAAc,mBAAmB,MAAM,UAAU;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,gBACE,IACA,OACA,oBACA,MACA,YACM;AACN,SAAK,cAAc,IAAI,IAAI;AAAA,MACzB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC;AACD,QAAI,KAAK,aAAa,KAAK,OAAO;AAChC,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmB,IAAkB;AACnC,SAAK,cAAc,OAAO,EAAE;AAC5B,QAAI,KAAK,aAAa,KAAK,OAAO;AAChC,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB,IAAY;AAC1B,WAAO,KAAK,cAAc,IAAI,EAAE;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAAqB,IAAkB;AACrC,UAAM,SAAS,KAAK,cAAc,IAAI,EAAE;AACxC,QAAI,QAAQ;AACV,aAAO,YAAY;AACnB,aAAO,gBAAgB,KAAK,IAAI;AAChC,UAAI,KAAK,aAAa,KAAK,OAAO;AAChC,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,UAAU,OAAe,sBAAqC;AAC5D,SAAK,OAAO;AACZ,SAAK,QAAQ;AACb,SAAK,gBAAgB,KAAK,IAAI;AAC9B,SAAK;AACL,SAAK,kBAAkB,wBAAwB;AAC/C,SAAK,2BAA2B;AAChC,SAAK,mBAAmB;AACxB,SAAK,4BAA4B;AACjC,SAAK,kBAAkB;AACvB,SAAK,cAAc;AAEnB,SAAK,wBAAwB;AAC7B,SAAK,+BAA+B;AACpC,SAAK,MAAM;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,OAA0B;AAChC,SAAK;AACL,QAAI,OAAO;AACT,WAAK,eAAe,MAAM;AAG1B,UAAI,KAAK,iBAAiB,KAAK,OAAO;AACpC,YAAI;AAEF,gBAAM,YAAY,KAAK,MAAM,SAAS,GAAG,IAAI,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,KAAK;AAE7E,gBAAM,OAAO,KAAK,cAAc;AAAA,YAC9B;AAAA,YACA,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM,qBAAqB;AAAA,YAC3B,MAAM,4BAA4B;AAAA,UACpC;AACA,cAAI,MAAM;AACR,iBAAK,aAAa,KAAK;AAAA,UACzB;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AACA,SAAK,MAAM;AACX,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,MAAoB;AAChC,QAAI,OAAO,GAAG;AACZ,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,eAAe,QAAgB,YAAY,OAAa;AAEtD,QAAI,aAAa,CAAC,KAAK,0BAA0B;AAC/C;AAAA,IACF;AACA,SAAK,kBAAkB;AACvB,SAAK,2BAA2B;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,gBAAgB,QAAgB,YAAY,OAAa;AAEvD,QAAI,aAAa,CAAC,KAAK,2BAA2B;AAChD;AAAA,IACF;AACA,SAAK,mBAAmB;AACxB,SAAK,4BAA4B;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB,mBAA2B,0BAAwC;AACjF,SAAK,wBAAwB;AAC7B,SAAK,+BAA+B;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,yBAAiC;AAC/B,QAAI,KAAK,mBAAmB,EAAG,QAAO;AACtC,WAAO,SAAS,KAAK,IAAI,IAAI,KAAK,kBAAkB,KAAM,QAAQ,CAAC,CAAC;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,wBAAgC;AAC9B,WAAO,SAAS,KAAK,IAAI,IAAI,KAAK,iBAAiB,KAAM,QAAQ,CAAC,CAAC;AAAA,EACrE;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,QAAI,CAAC,KAAK,SAAS,KAAK,UAAW;AACnC,SAAK,YAAY;AAGjB,SAAK,eAAe,WAAW,MAAM;AACnC,UAAI,KAAK,WAAW;AAClB,aAAK,WAAW,YAAY,MAAM,KAAK,OAAO,GAAG,EAAE;AACnD,aAAK,OAAO;AAAA,MACd;AAAA,IACF,GAAG,gBAAgB;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,YAA0B;AAC/B,SAAK,kBAAkB;AACvB,SAAK,cAAc;AAAA,EACrB;AAAA,EAEQ,SAAe;AAErB,SAAK,mBAAmB;AAExB,UAAM,UAAU,eAAe,KAAK,eAAe,eAAe,MAAM;AACxE,UAAM,QAAkB,CAAC;AAGzB,UAAM,sBAYD,CAAC;AAIN,QAAI,KAAK,OAAO;AACd,iBAAW,CAAC,UAAU,MAAM,KAAK,KAAK,iBAAiB;AAErD,YAAI,OAAO,WAAW;AACpB;AAAA,QACF;AACA,cAAM,kBAAkB,KAAK,IAAI,IAAI,OAAO,aAAa;AAGzD,cAAM,kBAAkB,KAAK,6BAA6B,QAAQ;AAIlE,cAAM,YAAY,QAAQ,OAAO,WAAW;AAC5C,cAAM,eAAe;AACrB,cAAM,OAAO;AAAA,UACX;AAAA,YACE,MAAM,OAAO;AAAA,YACb,YAAY,OAAO;AAAA,YACnB;AAAA,YACA,YAAY;AAAA;AAAA;AAAA,YAEZ,qBAAqB,gBAAgB;AAAA,YACrC,sBAAsB,gBAAgB;AAAA,YACtC,sBAAsB,gBAAgB;AAAA,YACtC,cAAc,gBAAgB;AAAA,UAChC;AAAA,UACA,YAAY,aAAa;AAAA,QAC3B;AAEA,cAAM,aAAa,KAChB,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,eAAe,CAAC,EAC3B,KAAK,IAAI;AACZ,cAAM,KAAK,UAAU;AAIrB,cAAM,YAoBD,CAAC;AAGN,mBAAW,CAAC,UAAU,MAAM,KAAK,KAAK,cAAc;AAClD,cAAI,OAAO,uBAAuB,UAAU;AAC1C,sBAAU,KAAK;AAAA,cACb,MAAM;AAAA,cACN,WAAW,OAAO;AAAA,cAClB,OAAO,OAAO;AAAA,cACd,WAAW,OAAO;AAAA,cAClB,kBAAkB,OAAO;AAAA,cACzB,oBAAoB,OAAO;AAAA,cAC3B,OAAO,OAAO;AAAA,cACd,aAAa,OAAO;AAAA,cACpB,mBAAmB,OAAO;AAAA,cAC1B,cAAc,OAAO;AAAA,cACrB,MAAM,OAAO;AAAA,cACb,cAAc,OAAO;AAAA,cACrB,WAAW,OAAO;AAAA,cAClB,eAAe,OAAO;AAAA,YACxB,CAAC;AAGD,gBAAI,CAAC,OAAO,WAAW;AACrB,kCAAoB,KAAK;AAAA,gBACvB,OAAO,OAAO;AAAA,gBACd,WAAW,OAAO;AAAA,gBAClB,kBAAkB,OAAO;AAAA,gBACzB,oBAAoB,OAAO;AAAA,gBAC3B,OAAO,OAAO;AAAA,gBACd,aAAa,OAAO;AAAA,gBACpB,mBAAmB,OAAO;AAAA,gBAC1B,cAAc,OAAO;AAAA,gBACrB,MAAM,OAAO;AAAA,gBACb,WAAW,OAAO;AAAA,gBAClB,kBAAkB,OAAO;AAAA;AAAA,cAC3B,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAGA,mBAAW,CAAC,UAAU,YAAY,KAAK,KAAK,eAAe;AACzD,cAAI,aAAa,uBAAuB,UAAU;AAChD,sBAAU,KAAK;AAAA,cACb,MAAM;AAAA,cACN,IAAI;AAAA;AAAA,cACJ,WAAW,aAAa;AAAA,cACxB,OAAO,aAAa;AAAA,cACpB,MAAM,aAAa;AAAA,cACnB,YAAY,aAAa;AAAA,cACzB,WAAW,aAAa;AAAA,cACxB,eAAe,aAAa;AAAA,YAC9B,CAAC;AAAA,UACH;AAAA,QACF;AAGA,kBAAU,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AAMlD,mBAAW,MAAM,WAAW;AAE1B,cAAI,GAAG,WAAW;AAChB;AAAA,UACF;AAGA,cAAI,GAAG,SAAS,SAAS;AACvB;AAAA,UACF;AAGA,gBAAM,SAAS,KAAK,OAAO,GAAG,QAAQ,CAAC;AACvC,gBAAMC,mBAAkB,KAAK,IAAI,IAAI,GAAG,aAAa;AAGrD,gBAAM,gBAAgB,GAAG,KAAK,KAAK,6BAA6B,GAAG,EAAE,IAAI,EAAE,aAAa,GAAG,cAAc,GAAG,mBAAmB,GAAG,MAAM,GAAG,WAAW,EAAE;AAIxJ,gBAAMC,aAAY,QAAQ,OAAO,WAAW;AAE5C,gBAAM,eAAe,GAAGC,OAAM,IAAI,GAAG,OAAO,IAAI,GAAG,CAAC;AACpD,gBAAMC,QAAO;AAAA,YACX;AAAA,cACE,MAAM,GAAG,QAAQ;AAAA,cACjB,YAAY,GAAG;AAAA,cACf,gBAAAH;AAAA,cACA,YAAY;AAAA;AAAA;AAAA,cAEZ,qBAAqB,cAAc;AAAA,cACnC,sBAAsB,cAAc;AAAA,cACpC,sBAAsB,cAAc;AAAA,cACpC,cAAc,cAAc;AAAA,YAC9B;AAAA,YACAC,aAAY,OAAO,SAAS,aAAa;AAAA,UAC3C;AAEA,gBAAM,eAAeE,MAClB,MAAM,IAAI,EACV,IAAI,CAAC,MAAM,SAAS,eAAe,CAAC,EACpC,KAAK,IAAI;AACZ,gBAAM,KAAK,YAAY;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AAOA,eAAW,UAAU,qBAAqB;AAExC,YAAM,SAAS,KAAK,OAAO,OAAO,QAAQ,CAAC;AAE3C,YAAM,eAAe,GAAGD,OAAM,IAAI,GAAG,OAAO,gBAAgB,GAAG,CAAC;AAChE,YAAM,kBAAkB,KAAK,IAAI,IAAI,OAAO,aAAa;AACzD,YAAM,OAAO,kBAAkB;AAAA,QAC7B,WAAW,OAAO;AAAA,QAClB,kBAAkB,OAAO;AAAA,QACzB,oBAAoB,OAAO;AAAA,QAC3B,OAAO,OAAO;AAAA,QACd,aAAa,OAAO;AAAA,QACpB,mBAAmB,OAAO;AAAA,QAC1B,cAAc,OAAO;AAAA,QACrB;AAAA,QACA,MAAM,OAAO;AAAA,QACb,aAAa;AAAA,QACb;AAAA,MACF,CAAC;AACD,YAAM,KAAK,GAAG,MAAM,GAAG,YAAY,GAAG,IAAI,EAAE;AAAA,IAC9C;AAGA,QAAI,KAAK,SAAS,aAAa;AAC7B,YAAM,KAAK,KAAK,oBAAoB,OAAO,CAAC;AAAA,IAC9C,OAAO;AACL,YAAM,KAAK,KAAK,qBAAqB,OAAO,CAAC;AAAA,IAC/C;AAGA,UAAM,SAAS,MAAM,KAAK,IAAI;AAE9B,SAAK,uBAAuB,OAAO,MAAM,KAAK,KAAK,CAAC,GAAG,SAAS;AAGhE,SAAK,OAAO,MAAM,OAAO,MAAM;AAC/B,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAA2B;AACjC,QAAI,CAAC,KAAK,eAAe,KAAK,wBAAwB,EAAG;AAGzD,SAAK,OAAO,MAAM,UAAU;AAG5B,aAAS,IAAI,GAAG,IAAI,KAAK,qBAAqB,KAAK;AAEjD,WAAK,OAAO,MAAM,eAAe;AAAA,IACnC;AAGA,SAAK,OAAO,MAAM,IAAI;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAsB;AACpB,QAAI,KAAK,OAAO;AACd,WAAK,mBAAmB;AAAA,IAC1B;AACA,SAAK,sBAAsB;AAC3B,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,oBAAoB,SAAyB;AAEnD,UAAM,YAAY,KAAK,4BACnB,KAAK,MAAM,KAAK,kBAAkB,wBAAwB,IAC1D,KAAK;AAGT,WAAO,kBAAkB;AAAA,MACvB,WAAW,KAAK;AAAA,MAChB,OAAO,KAAK,SAAS;AAAA,MACrB,aAAa,KAAK;AAAA,MAClB,mBAAmB,KAAK;AAAA,MACxB,cAAc;AAAA,MACd,iBAAiB,KAAK,IAAI,IAAI,KAAK,iBAAiB;AAAA,MACpD,MAAM,KAAK,yBAAyB,SAAS;AAAA,MAC7C,aAAa;AAAA,MACb;AAAA,MACA,gBAAgB,KAAK,uBAAuB;AAAA,MAC5C,WAAW;AAAA,QACT,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,MACf;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,yBAAyB,cAA8B;AAC7D,QAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,MAAO,QAAO;AAE/C,QAAI;AAEF,YAAM,YAAY,KAAK,MAAM,SAAS,GAAG,IAAI,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,KAAK;AAE7E,YAAM,OAAO,KAAK,cAAc;AAAA,QAC9B;AAAA,QACA,KAAK;AAAA,QACL;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,MACP;AAEA,aAAO,MAAM,aAAa;AAAA,IAC5B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,yBAAwC;AAC9C,QAAI,CAAC,KAAK,iBAAiB,CAAC,KAAK,SAAS,KAAK,oBAAoB,GAAG;AACpE,aAAO;AAAA,IACT;AAGA,UAAM,YAAY,KAAK,MAAM,SAAS,GAAG,IAAI,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI,KAAK;AAE7E,UAAM,SAAS,KAAK,cAAc,eAAe,SAAS;AAC1D,QAAI,CAAC,QAAQ,eAAe;AAC1B,aAAO;AAAA,IACT;AAEA,WAAQ,KAAK,kBAAkB,OAAO,gBAAiB;AAAA,EACzD;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,SAAyB;AACpD,UAAM,YAAY,KAAK,IAAI,IAAI,KAAK,kBAAkB,KAAM,QAAQ,CAAC;AAGrE,UAAM,QAAkB,CAAC;AACzB,QAAI,KAAK,OAAO;AACd,YAAM,KAAKA,OAAM,KAAK,KAAK,KAAK,CAAC;AAAA,IACnC;AACA,QAAI,KAAK,cAAc,GAAG;AACxB,YAAM,KAAKA,OAAM,IAAI,QAAQ,IAAIA,OAAM,QAAQ,IAAI,KAAK,WAAW,EAAE,CAAC;AAAA,IACxE;AACA,QAAI,KAAK,aAAa,GAAG;AACvB,YAAM,KAAKA,OAAM,IAAI,OAAO,IAAIA,OAAM,KAAK,IAAI,KAAK,UAAU,EAAE,CAAC;AAAA,IACnE;AACA,QAAI,KAAK,YAAY,GAAG;AACtB,YAAM,KAAKA,OAAM,IAAI,OAAO,IAAIA,OAAM,KAAK,KAAK,WAAW,KAAK,SAAS,CAAC,EAAE,CAAC;AAAA,IAC/E;AACA,UAAM,KAAKA,OAAM,IAAI,GAAG,OAAO,GAAG,CAAC;AAEnC,WAAO,GAAG,MAAM,KAAKA,OAAM,IAAI,KAAK,CAAC,CAAC,IAAIA,OAAM,KAAK,OAAO,CAAC;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAc;AACZ,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,UAAW;AAEpC,QAAI,KAAK,cAAc;AACrB,mBAAa,KAAK,YAAY;AAC9B,WAAK,eAAe;AAAA,IACtB;AACA,QAAI,KAAK,UAAU;AACjB,oBAAc,KAAK,QAAQ;AAC3B,WAAK,WAAW;AAAA,IAClB;AACA,SAAK,YAAY;AAGjB,SAAK,mBAAmB;AACxB,SAAK,cAAc;AACnB,SAAK,sBAAsB;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,WAAiB;AACf,SAAK,MAAM;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,eAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAsB;AACpB,UAAM,QAAkB,CAAC;AACzB,UAAM,YAAY,KAAK,IAAI,IAAI,KAAK,iBAAiB,KAAM,QAAQ,CAAC;AAGpE,UAAM,YAAY,KAAK,4BACnB,KAAK,MAAM,KAAK,kBAAkB,wBAAwB,IAC1D,KAAK;AAET,QAAI,KAAK,kBAAkB,GAAG;AAC5B,YAAM,SAAS,KAAK,2BAA2B,MAAM;AACrD,YAAM,KAAK,UAAK,MAAM,GAAG,aAAa,KAAK,eAAe,CAAC,EAAE;AAAA,IAC/D;AAEA,QAAI,YAAY,GAAG;AACjB,YAAM,SAAS,KAAK,4BAA4B,MAAM;AACtD,YAAM,KAAK,UAAK,MAAM,GAAG,aAAa,SAAS,CAAC,EAAE;AAAA,IACpD;AAEA,UAAM,KAAK,GAAG,OAAO,GAAG;AAExB,WAAO,MAAM,KAAK,KAAK;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,eAAuB;AACrB,UAAM,QAAkB,CAAC;AAEzB,QAAI,KAAK,SAAS,aAAa;AAE7B,YAAM,UAAU,KAAK,OAAO,KAAK,IAAI,IAAI,KAAK,iBAAiB,GAAI;AAGnE,YAAM,YAAY,KAAK,4BACnB,KAAK,MAAM,KAAK,kBAAkB,wBAAwB,IAC1D,KAAK;AACT,YAAM,eAAe,KAAK;AAE1B,UAAI,KAAK,kBAAkB,GAAG;AAC5B,cAAM,SAAS,KAAK,2BAA2B,MAAM;AACrD,cAAM;AAAA,UACJA,OAAM,IAAI,QAAG,IAAIA,OAAM,OAAO,IAAI,MAAM,GAAG,aAAa,KAAK,eAAe,CAAC,EAAE;AAAA,QACjF;AAAA,MACF;AACA,UAAI,YAAY,GAAG;AACjB,cAAM,SAAS,eAAe,MAAM;AACpC,cAAM,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,MAAM,IAAI,MAAM,GAAG,aAAa,SAAS,CAAC,EAAE,CAAC;AAAA,MACjF;AACA,YAAM,KAAKA,OAAM,IAAI,GAAG,OAAO,GAAG,CAAC;AAAA,IACrC,OAAO;AAEL,YAAM,UAAU,KAAK,OAAO,KAAK,IAAI,IAAI,KAAK,kBAAkB,GAAI;AAEpE,UAAI,KAAK,cAAc,GAAG;AACxB,cAAM,KAAKA,OAAM,QAAQ,aAAa,KAAK,WAAW,CAAC,CAAC;AAAA,MAC1D;AACA,UAAI,KAAK,aAAa,GAAG;AACvB,cAAM,KAAKA,OAAM,KAAK,IAAI,KAAK,UAAU,EAAE,CAAC;AAAA,MAC9C;AACA,UAAI,KAAK,YAAY,GAAG;AACtB,cAAM,KAAKA,OAAM,KAAK,IAAI,WAAW,KAAK,SAAS,CAAC,EAAE,CAAC;AAAA,MACzD;AACA,YAAM,KAAKA,OAAM,IAAI,GAAG,OAAO,GAAG,CAAC;AAAA,IACrC;AAEA,WAAO,GAAG,MAAM,KAAKA,OAAM,IAAI,KAAK,CAAC,CAAC,IAAIA,OAAM,MAAM,GAAG,CAAC;AAAA,EAC5D;AACF;AAQA,eAAe,WAAW,QAAgD;AACxE,QAAM,SAAmB,CAAC;AAC1B,mBAAiB,SAAS,QAAQ;AAChC,QAAI,OAAO,UAAU,UAAU;AAC7B,aAAO,KAAK,KAAK;AAAA,IACnB,OAAO;AACL,aAAO,KAAK,MAAM,SAAS,MAAM,CAAC;AAAA,IACpC;AAAA,EACF;AACA,SAAO,OAAO,KAAK,EAAE;AACvB;AAQA,SAAS,gBAAgB,OAAuB;AAC9C,SAAO,MAAM,KAAK;AACpB;AAWA,eAAsB,cACpB,WACA,KACiB;AACjB,MAAI,WAAW,KAAK,GAAG;AACrB,WAAO,gBAAgB,SAAS;AAAA,EAClC;AAEA,MAAI,cAAc,IAAI,KAAK,GAAG;AAC5B,UAAM,IAAI,MAAM,oEAAoE;AAAA,EACtF;AAEA,QAAM,aAAa,gBAAgB,MAAM,WAAW,IAAI,KAAK,CAAC;AAC9D,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,6DAA6D;AAAA,EAC/E;AAEA,SAAO;AACT;AAaA,eAAsB,cACpB,QACA,KACe;AACf,MAAI;AACF,UAAM,OAAO;AAAA,EACf,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,QAAI,OAAO,MAAM,GAAGA,OAAM,IAAI,KAAK,QAAQ,CAAC,IAAI,OAAO;AAAA,CAAI;AAC3D,QAAI,YAAY,CAAC;AAAA,EACnB;AACF;;;AE9wCO,SAAS,mBAAmB,KAAc,UAAoC;AACnF,SAAO,IACJ,OAAO,aAAa,OAAO,oBAAoB,OAAO,UAAU,SAAS,aAAa,EACtF,OAAO,aAAa,cAAc,oBAAoB,cAAc,UAAU,MAAM,EACpF;AAAA,IACC,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,oBAAoB,EAAE,OAAO,eAAe,KAAK,GAAG,KAAK,EAAE,CAAC;AAAA,IAC5D,UAAU;AAAA,EACZ,EACC;AAAA,IACC,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,oBAAoB,EAAE,OAAO,cAAc,SAAS,MAAM,KAAK,EAAE,CAAC;AAAA,IAClE,WAAW,YAAY;AAAA,EACzB,EACC,OAAO,aAAa,OAAO,oBAAoB,OAAO,UAAU,KAAK,EACrE;AAAA,IACC,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,WAAW,kBAAkB;AAAA,EAC/B,EACC,OAAO,aAAa,YAAY,oBAAoB,UAAU,EAC9D,OAAO,aAAa,YAAY,oBAAoB,UAAU;AACnE;AASO,SAAS,gBAAgB,KAAc,UAAiC;AAE7E,QAAM,oBAAoB,CAAC,OAAe,WAAqB,CAAC,MAAgB;AAAA,IAC9E,GAAG;AAAA,IACH;AAAA,EACF;AACA,QAAM,iBAAiB,UAAU,WAAW,UAAU,UAAU,CAAC;AAEjE,SAAO,IACJ,OAAO,aAAa,OAAO,oBAAoB,OAAO,UAAU,SAAS,aAAa,EACtF,OAAO,aAAa,cAAc,oBAAoB,cAAc,UAAU,MAAM,EACpF;AAAA,IACC,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,oBAAoB,EAAE,OAAO,eAAe,KAAK,GAAG,KAAK,EAAE,CAAC;AAAA,IAC5D,UAAU;AAAA,EACZ,EACC;AAAA,IACC,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,oBAAoB,EAAE,OAAO,kBAAkB,SAAS,MAAM,KAAK,EAAE,CAAC;AAAA,IACtE,WAAW,gBAAgB;AAAA,EAC7B,EACC,OAAO,aAAa,cAAc,oBAAoB,cAAc,mBAAmB;AAAA,IACtF,GAAG;AAAA,EACL,CAAC,EACA,OAAO,aAAa,YAAY,oBAAoB,YAAY,UAAU,aAAa,KAAK,EAC5F;AAAA,IACC,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,WAAW,qBAAqB,MAAM;AAAA,EACxC,EACC,OAAO,aAAa,OAAO,oBAAoB,OAAO,UAAU,KAAK,EACrE;AAAA,IACC,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,WAAW,kBAAkB;AAAA,EAC/B,EACC,OAAO,aAAa,YAAY,oBAAoB,UAAU,EAC9D,OAAO,aAAa,YAAY,oBAAoB,UAAU;AACnE;AAKO,SAAS,wBACd,QAC6B;AAC7B,QAAM,SAAsC,CAAC;AAC7C,MAAI,OAAO,UAAU,OAAW,QAAO,QAAQ,OAAO;AACtD,MAAI,OAAO,WAAW,OAAW,QAAO,SAAS,OAAO;AACxD,MAAI,OAAO,gBAAgB,OAAW,QAAO,cAAc,OAAO;AAClE,MAAI,OAAO,YAAY,MAAM,OAAW,QAAO,YAAY,OAAO,YAAY;AAC9E,MAAI,OAAO,UAAU,OAAW,QAAO,QAAQ,OAAO;AACtD,MAAI,OAAO,kBAAkB,MAAM,OAAW,QAAO,iBAAiB,OAAO,kBAAkB;AAC/F,SAAO;AACT;AAKO,SAAS,qBAAqB,QAAuD;AAC1F,QAAM,SAAmC,CAAC;AAC1C,MAAI,OAAO,UAAU,OAAW,QAAO,QAAQ,OAAO;AACtD,MAAI,OAAO,WAAW,OAAW,QAAO,SAAS,OAAO;AACxD,MAAI,OAAO,gBAAgB,OAAW,QAAO,cAAc,OAAO;AAClE,MAAI,OAAO,gBAAgB,MAAM,OAAW,QAAO,gBAAgB,OAAO,gBAAgB;AAE1F,QAAM,UAAU,OAAO,WAAW,OAAO;AACzC,MAAI,YAAY,OAAW,QAAO,SAAS;AAC3C,MAAI,OAAO,aAAa,OAAW,QAAO,WAAW,OAAO;AAC5D,MAAI,OAAO,qBAAqB,MAAM;AACpC,WAAO,qBAAqB,OAAO,qBAAqB;AAC1D,MAAI,OAAO,qBAAqB,MAAM;AACpC,WAAO,oBAAoB,OAAO,qBAAqB;AACzD,MAAI,OAAO,mBAAmB,MAAM;AAClC,WAAO,kBAAkB,OAAO,mBAAmB;AACrD,MAAI,OAAO,mBAAmB,MAAM;AAClC,WAAO,kBAAkB,OAAO,mBAAmB;AACrD,MAAI,OAAO,iBAAiB,MAAM,OAAW,QAAO,iBAAiB,OAAO,iBAAiB;AAC7F,MAAI,OAAO,UAAU,OAAW,QAAO,QAAQ,OAAO;AACtD,MAAI,OAAO,kBAAkB,MAAM,OAAW,QAAO,iBAAiB,OAAO,kBAAkB;AAC/F,MAAI,OAAO,cAAc,OAAW,QAAO,YAAY,OAAO;AAC9D,SAAO;AACT;;;AC5KA,SAAS,QAAQ,YAAY,mBAAmB;AAIhD,IAAI,qBAAqB;AAEzB,SAAS,2BAAiC;AACxC,MAAI,CAAC,oBAAoB;AACvB,eAAW,IAAI,YAAY,CAAC;AAC5B,yBAAqB;AAAA,EACvB;AACF;AAGA,IAAM,qBAAqB;AAQpB,SAAS,aAAa,SAIR;AAEnB,2BAAyB;AAEzB,QAAM,SAAS,IAAI,OAAO;AAAA,IACxB,UAAU;AAAA;AAAA,IACV,aAAa;AAAA;AAAA,IACb,OAAO,SAAS,SAAS;AAAA,IACzB,OAAO,SAAS;AAAA,IAChB,QAAQ,SAAS;AAAA;AAAA,IAEjB,UAAU;AAAA;AAAA,IAEV,QAAQ;AAAA,EACV,CAAC;AAED,MAAI,cAAc;AAClB,MAAI,gBAAgB;AACpB,MAAI,gBAAsD;AAI1D,QAAM,gBAAgB,MAAM;AAC1B,QAAI,YAAa;AAIjB,QAAI,cAAe;AAEnB,oBAAgB;AAChB,oBAAgB,WAAW,MAAM;AAC/B,sBAAgB;AAChB,UAAI,CAAC,aAAa;AAChB,eAAO,OAAO;AAAA,MAChB;AAAA,IACF,GAAG,kBAAkB;AAAA,EACvB;AAGA,QAAM,YAAY,MAAM;AACtB,QAAI,YAAa;AAGjB,QAAI,eAAe;AACjB,mBAAa,aAAa;AAC1B,sBAAgB;AAChB,sBAAgB;AAAA,IAClB;AAEA,WAAO,OAAO;AAAA,EAChB;AAGA,QAAM,UAAU,MAAM;AACpB,QAAI,YAAa;AACjB,kBAAc;AAGd,QAAI,eAAe;AACjB,mBAAa,aAAa;AAC1B,sBAAgB;AAAA,IAClB;AAGA,WAAO,QAAQ;AAGf,YAAQ,OAAO,MAAM,WAAW;AAAA,EAClC;AAGA,QAAM,gBAAgB,MAAM;AAC1B,YAAQ;AACR,YAAQ,KAAK,GAAG;AAAA,EAClB;AAEA,QAAM,iBAAiB,MAAM;AAC3B,YAAQ;AACR,YAAQ,KAAK,GAAG;AAAA,EAClB;AAEA,UAAQ,KAAK,UAAU,aAAa;AACpC,UAAQ,KAAK,WAAW,cAAc;AAGtC,UAAQ,KAAK,qBAAqB,CAAC,QAAQ;AACzC,YAAQ;AACR,YAAQ,MAAM,uBAAuB,GAAG;AACxC,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACzHA,SAAS,KAAK,eAAe,eAA4B;AAclD,SAAS,kBAAkB,QAAgC;AAGhE,QAAM,OAAO,IAAI,cAAc;AAAA,IAC7B,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA;AAAA,IAER,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,OAAO;AAAA,IACP,MAAM;AAAA;AAAA,IACN,WAAW;AAAA,MACT,IAAI;AAAA,MACJ,OAAO;AAAA,QACL,IAAI;AAAA,MACN;AAAA,IACF;AAAA;AAAA,IAEA,MAAM;AAAA;AAAA,IAEN,OAAO;AAAA,MACL,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF,CAAC;AAID,QAAM,WAAW,IAAI,QAAQ;AAAA,IAC3B,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,MACL,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF,CAAC;AAGD,WAAS,SAAS,IAAI;AAItB,QAAM,YAAY,IAAI,IAAI;AAAA,IACxB,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,OAAO;AAAA,MACL,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF,CAAC;AAED,SAAO,EAAE,MAAM,UAAU,UAAU;AACrC;AAeO,SAAS,yBACd,QACA,WAUA,cACM;AAEN,SAAO,IAAI,CAAC,MAAM,GAAG,GAAG,MAAM;AAC5B,QAAI,aAAa,MAAM,SAAU;AACjC,cAAU,iBAAiB;AAC3B,WAAO,OAAO;AAAA,EAChB,CAAC;AAED,SAAO,IAAI,CAAC,QAAQ,GAAG,GAAG,MAAM;AAC9B,QAAI,aAAa,MAAM,SAAU;AACjC,cAAU,aAAa;AACvB,WAAO,OAAO;AAAA,EAChB,CAAC;AAGD,SAAO,IAAI,CAAC,SAAS,OAAO,GAAG,MAAM;AACnC,QAAI,aAAa,MAAM,SAAU;AACjC,cAAU,eAAe;AACzB,WAAO,OAAO;AAAA,EAChB,CAAC;AAGD,SAAO,IAAI,CAAC,UAAU,GAAG,GAAG,MAAM;AAChC,QAAI,aAAa,MAAM,SAAU;AACjC,cAAU,WAAW;AACrB,WAAO,OAAO;AAAA,EAChB,CAAC;AAGD,SAAO,IAAI,CAAC,QAAQ,GAAG,GAAG,MAAM;AAC9B,QAAI,aAAa,MAAM,SAAU;AACjC,cAAU,cAAc;AACxB,WAAO,OAAO;AAAA,EAChB,CAAC;AAED,SAAO,IAAI,CAAC,OAAO,GAAG,GAAG,MAAM;AAC7B,QAAI,aAAa,MAAM,SAAU;AACjC,cAAU,aAAa;AACvB,WAAO,OAAO;AAAA,EAChB,CAAC;AAGD,SAAO,IAAI,CAAC,GAAG,GAAG,MAAM;AACtB,QAAI,aAAa,MAAM,SAAU;AACjC,cAAU,mBAAmB;AAAA,EAC/B,CAAC;AAED,SAAO,IAAI,CAAC,KAAK,GAAG,MAAM;AACxB,QAAI,aAAa,MAAM,SAAU;AACjC,cAAU,oBAAoB;AAAA,EAChC,CAAC;AACH;;;ACzJA,IAAM,kBAAkB;AAGxB,IAAME,kBAAiB,CAAC,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,QAAG;AAGxE,IAAM,sBAAsB;AAKrB,IAAM,YAAN,MAAgB;AAAA,EACb;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA,uBAAuB;AAAA;AAAA,EAEvB,wBAAwB;AAAA;AAAA,EAExB,cAAc;AAAA;AAAA,EAGd,iBAAiB,oBAAI,IAAoB;AAAA;AAAA,EAGzC,gBAAgB,oBAAI,IAAY;AAAA;AAAA,EAGhC,eAAe;AAAA;AAAA,EAGf,kBAAyD;AAAA;AAAA,EAGzD,YAAuB;AAAA;AAAA,EAGvB,gBAAgB,oBAAI,IAAoB;AAAA;AAAA,EAGxC,qBAAqB,oBAAI,IAAoB;AAAA;AAAA,EAG7C,kBAAuC;AAAA,EAE/C,YACE,WACA,OACA,gBACA,mBACA;AACA,SAAK,YAAY;AACjB,SAAK,iBAAiB;AACtB,SAAK,oBAAoB,qBAAqB;AAC9C,SAAK,UAAU;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,cAAc;AAAA,MACd,MAAM;AAAA,MACN,WAAW,KAAK,IAAI;AAAA,MACpB,WAAW;AAAA,MACX;AAAA,IACF;AAGA,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,OAAe,sBAAoC;AAC3D,SAAK,QAAQ,QAAQ;AACrB,SAAK,QAAQ;AAEb,SAAK,uBAAuB;AAC5B,SAAK,wBAAwB;AAC7B,SAAK,cAAc;AACnB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB,uBAAqC;AACnD,SAAK,wBAAwB;AAC7B,SAAK,OAAO,IAAI;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QACE,aACA,cACA,cACA,MACM;AAEN,SAAK,QAAQ,eAAe;AAC5B,SAAK,QAAQ,gBAAgB;AAC7B,SAAK,QAAQ,gBAAgB;AAC7B,SAAK,QAAQ,QAAQ;AAErB,SAAK,uBAAuB;AAC5B,SAAK,wBAAwB;AAC7B,SAAK,cAAc;AACnB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,MAAoB;AAChC,QAAI,OAAO,GAAG;AACZ,WAAK,QAAQ,QAAQ;AACrB,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,aAAa,OAAe,OAAqB;AAC/C,SAAK,eAAe,IAAI,OAAO,KAAK;AACpC,SAAK,aAAa;AAClB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,WAAW,OAAqB;AAC9B,SAAK,eAAe,OAAO,KAAK;AAChC,SAAK,iBAAiB;AACtB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,YAAY,MAAoB;AAC9B,SAAK,cAAc,IAAI,IAAI;AAC3B,SAAK,aAAa;AAClB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU,MAAoB;AAC5B,SAAK,cAAc,OAAO,IAAI;AAC9B,SAAK,iBAAiB;AACtB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,QAAI,KAAK,gBAAiB;AAC1B,SAAK,kBAAkB,YAAY,MAAM;AACvC,WAAK,gBAAgB,KAAK,eAAe,KAAKA,gBAAe;AAC7D,WAAK,OAAO,IAAI;AAAA,IAClB,GAAG,mBAAmB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAyB;AAC/B,QAAI,KAAK,eAAe,SAAS,KAAK,KAAK,cAAc,SAAS,GAAG;AACnE,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAoB;AAC1B,QAAI,KAAK,iBAAiB;AACxB,oBAAc,KAAK,eAAe;AAClC,WAAK,kBAAkB;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAsB;AACpB,SAAK,eAAe,MAAM;AAC1B,SAAK,cAAc,MAAM;AACzB,SAAK,cAAc,MAAM;AACzB,SAAK,mBAAmB,MAAM;AAC9B,SAAK,YAAY;AACjB,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,gBAAgB,MAAiC;AAE/C,QAAI,KAAK,iBAAiB;AACxB,WAAK,gBAAgB;AAAA,IACvB;AAGA,SAAK,cAAc,MAAM;AACzB,SAAK,mBAAmB,MAAM;AAE9B,SAAK,kBAAkB,KAAK,MAAM,CAAC,UAA0B;AAC3D,WAAK,gBAAgB,KAAK;AAAA,IAC5B,CAAC;AAED,WAAO,MAAM;AACX,UAAI,KAAK,iBAAiB;AACxB,aAAK,gBAAgB;AACrB,aAAK,kBAAkB;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,OAA6B;AACnD,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK,kBAAkB;AAErB,cAAM,QAAQ,MAAM,UAAU,IAC1B,IAAI,MAAM,YAAY,CAAC,KACvB,IAAI,MAAM,YAAY,CAAC,IAAI,MAAM,KAAK;AAC1C,aAAK,cAAc,IAAI,MAAM,QAAQ,KAAK;AAC1C,aAAK,aAAa,OAAO,MAAM,KAAK;AACpC;AAAA,MACF;AAAA,MAEA,KAAK,qBAAqB;AACxB,cAAM,QAAQ,KAAK,cAAc,IAAI,MAAM,MAAM;AACjD,YAAI,OAAO;AACT,eAAK,WAAW,KAAK;AAErB,cAAI,MAAM,SAAS,MAAM,MAAM;AAC7B,iBAAK;AAAA,cACH,MAAM,OAAO,eAAe;AAAA,cAC5B,MAAM,OAAO,gBAAgB;AAAA,cAC7B,MAAM,OAAO,qBAAqB;AAAA,cAClC,MAAM,QAAQ;AAAA,YAChB;AAAA,UACF;AACA,eAAK,cAAc,OAAO,MAAM,MAAM;AAAA,QACxC;AACA;AAAA,MACF;AAAA,MAEA,KAAK,kBAAkB;AACrB,cAAM,QAAQ,KAAK,cAAc,IAAI,MAAM,MAAM;AACjD,YAAI,OAAO;AACT,eAAK,WAAW,KAAK;AACrB,eAAK,cAAc,OAAO,MAAM,MAAM;AAAA,QACxC;AACA;AAAA,MACF;AAAA,MAEA,KAAK,eAAe;AAClB,aAAK,mBAAmB,IAAI,MAAM,QAAQ,MAAM,IAAI;AACpD,aAAK,YAAY,MAAM,IAAI;AAC3B;AAAA,MACF;AAAA,MAEA,KAAK,mBAAmB;AACtB,cAAM,OAAO,KAAK,mBAAmB,IAAI,MAAM,MAAM;AACrD,YAAI,MAAM;AACR,eAAK,UAAU,IAAI;AACnB,cAAI,MAAM,MAAM;AACd,iBAAK,cAAc,MAAM,IAAI;AAAA,UAC/B;AACA,eAAK,mBAAmB,OAAO,MAAM,MAAM;AAAA,QAC7C;AACA;AAAA,MACF;AAAA,MAEA,KAAK;AAAA,MACL,KAAK,kBAAkB;AACrB,cAAM,OAAO,KAAK,mBAAmB,IAAI,MAAM,MAAM;AACrD,YAAI,MAAM;AACR,eAAK,UAAU,IAAI;AACnB,eAAK,mBAAmB,OAAO,MAAM,MAAM;AAAA,QAC7C;AACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,aAAa,MAAuB;AAClC,SAAK,YAAY;AACjB,SAAK,OAAO,IAAI;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,eAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,iBAAiB,OAAuB;AAE9C,UAAM,kBAAkB,MAAM,SAAS,GAAG,IAAI,MAAM,MAAM,GAAG,EAAE,CAAC,IAAI;AAEpE,WAAO,gBACJ,QAAQ,WAAW,EAAE,EACrB,QAAQ,WAAW,EAAE,EACrB,QAAQ,QAAQ,EAAE,EAClB,QAAQ,WAAW,EAAE;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmC;AACjC,WAAO,EAAE,GAAG,KAAK,QAAQ;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKA,oBAA4B;AAC1B,YAAQ,KAAK,IAAI,IAAI,KAAK,QAAQ,aAAa;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,OAAO,YAAY,OAAa;AACtC,UAAM,UAAU,KAAK,kBAAkB,EAAE,QAAQ,CAAC;AAGlD,UAAMC,UAAS;AACf,UAAMC,SAAQ;AACd,UAAM,OAAO;AACb,UAAMC,QAAO;AACb,UAAMC,WAAU;AAChB,UAAM,OAAO;AACb,UAAMC,SAAQ;AACd,UAAM,UAAU;AAChB,UAAM,WAAW;AACjB,UAAMC,SAAQ;AACd,UAAM,QAAQ;AAGd,UAAM,qBAAqB,KAAK,QAAQ,cAAc,KAAK;AAC3D,UAAM,sBAAsB,KAAK,QAAQ,eAAe,KAAK;AAI7D,UAAM,QAAkB,CAAC;AAGzB,QAAI,KAAK,cAAc,UAAU;AAC/B,YAAM,KAAK,GAAG,OAAO,GAAGA,MAAK,WAAWD,MAAK,EAAE;AAAA,IACjD,OAAO;AACL,YAAM,KAAK,GAAG,QAAQ,GAAG,KAAK,UAAUA,MAAK,EAAE;AAAA,IACjD;AAGA,UAAM,cAAc,KAAK,eAAe,KAAK,uBAAuB,IAAI,MAAM;AAC9E,UAAM,KAAK,GAAGJ,OAAM,UAAK,WAAW,GAAG,aAAa,kBAAkB,CAAC,GAAGI,MAAK,EAAE;AAGjF,QAAI,KAAK,QAAQ,eAAe,GAAG;AACjC,YAAM,KAAK,GAAG,IAAI,UAAK,aAAa,KAAK,QAAQ,YAAY,CAAC,GAAGA,MAAK,EAAE;AAAA,IAC1E;AAGA,UAAM,eAAe,KAAK,cAAc,MAAM;AAC9C,UAAM,KAAK,GAAGH,MAAK,UAAK,YAAY,GAAG,aAAa,mBAAmB,CAAC,GAAGG,MAAK,EAAE;AAGlF,UAAM,KAAK,GAAG,IAAI,GAAG,OAAO,IAAIA,MAAK,EAAE;AAGvC,UAAM,KAAK,GAAGF,KAAI,IAAI,WAAW,KAAK,QAAQ,IAAI,CAAC,GAAGE,MAAK,EAAE;AAG7D,QAAI,KAAK,eAAe,OAAO,KAAK,KAAK,cAAc,OAAO,GAAG;AAC/D,YAAM,UAAUL,gBAAe,KAAK,YAAY;AAGhD,UAAI,KAAK,eAAe,OAAO,GAAG;AAChC,cAAM,UAAU,oBAAI,IAAsB;AAC1C,mBAAW,CAAC,OAAO,KAAK,KAAK,KAAK,gBAAgB;AAChD,gBAAM,aAAa,KAAK,iBAAiB,KAAK;AAC9C,cAAI,CAAC,QAAQ,IAAI,UAAU,EAAG,SAAQ,IAAI,YAAY,CAAC,CAAC;AACxD,kBAAQ,IAAI,UAAU,GAAG,KAAK,KAAK;AAAA,QACrC;AAEA,cAAM,WAAqB,CAAC;AAC5B,mBAAW,CAAC,OAAO,MAAM,KAAK,SAAS;AACrC,mBAAS,KAAK,GAAG,KAAK,IAAI,OAAO,KAAK,IAAI,CAAC,EAAE;AAAA,QAC/C;AACA,cAAM,KAAK,GAAG,OAAO,IAAII,QAAO,GAAG,SAAS,KAAK,KAAK,CAAC,GAAGC,MAAK,EAAE;AAAA,MACnE;AAGA,UAAI,KAAK,cAAc,OAAO,GAAG;AAC/B,cAAM,aAAa,CAAC,GAAG,KAAK,aAAa,EAAE,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI;AAChE,cAAM,OAAO,KAAK,cAAc,OAAO,IAAI,KAAK,KAAK,cAAc,OAAO,CAAC,KAAK;AAChF,cAAM,KAAK,GAAGF,KAAI,UAAK,UAAU,GAAG,IAAI,GAAGE,MAAK,EAAE;AAAA,MACpD;AAAA,IACF;AAEA,SAAK,UAAU,WAAW,MAAM,KAAK,IAAI,IAAI,IAAIA,MAAK,GAAG,CAAC;AAG1D,QAAI,WAAW;AACb,WAAK,kBAAkB;AAAA,IACzB,OAAO;AACL,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,eAAeE,OAAsB;AAC1C,WAAO,KAAK,KAAKA,MAAK,SAAS,eAAe;AAAA,EAChD;AACF;;;AC3dA,IAAM,cAAc;AAGpB,IAAM,gBAAgB;AAGtB,IAAM,iBAAiB;AAKhB,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA,eAAoC;AAAA;AAAA,EAGpC,sBAAsB;AAAA;AAAA,EAGtB,gBAAsC;AAAA;AAAA,EAGtC,gBAAqC;AAAA,EAE7C,YACE,UACA,MACA,QACA,gBACA,mBACA;AACA,SAAK,WAAW;AAChB,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,iBAAiB;AACtB,SAAK,oBAAoB,qBAAqB;AAG9C,SAAK,SAAS,GAAG,UAAU,CAAC,UAAkB;AAC5C,WAAK,aAAa,KAAK;AAAA,IACzB,CAAC;AAGD,SAAK,SAAS,GAAG,UAAU,MAAM;AAC/B,WAAK,aAAa;AAAA,IACpB,CAAC;AAID,SAAK,SAAS,IAAI,CAAC,KAAK,GAAG,MAAM;AAC/B,UAAI,KAAK,eAAe;AACtB,aAAK,cAAc;AAAA,MACrB;AAAA,IACF,CAAC;AAID,SAAK,SAAS,IAAI,CAAC,KAAK,GAAG,MAAM;AAC/B,UAAI,KAAK,eAAe;AACtB,aAAK,cAAc;AAAA,MACrB;AAAA,IACF,CAAC;AAID,SAAK,OAAO,IAAI,CAAC,OAAO,GAAG,MAAM;AAC/B,UAAI,KAAK,qBAAqB;AAC5B,aAAK,sBAAsB;AAAA,MAC7B;AAAA,IACF,CAAC;AAGD,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,UAA+B;AACrC,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,UAA4B;AAClC,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,aAAa,UAAkB,YAAqC;AACxE,WAAO,IAAI,QAAQ,CAACC,UAAS,WAAW;AACtC,WAAK,eAAe;AAAA,QAClB;AAAA,QACA;AAAA,QACA,SAAAA;AAAA,QACA;AAAA,MACF;AAGA,WAAK,qBAAqB,QAAQ;AAGlC,WAAK,UAAU;AAAA,IACjB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,gBAAiC;AACrC,WAAO,IAAI,QAAQ,CAACA,UAAS,WAAW;AACtC,WAAK,eAAe;AAAA,QAClB,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,SAAAA;AAAA,QACA;AAAA,MACF;AAIA,WAAK,iBAAiB;AAAA,IACxB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,wBAA8B;AAC5B,QAAI,KAAK,uBAAuB,KAAK,cAAc;AACjD,WAAK,sBAAsB;AAC3B,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,kBAA2B;AACzB,WAAO,KAAK,iBAAiB;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAsB;AACpB,QAAI,KAAK,cAAc;AACrB,WAAK,aAAa,OAAO,IAAI,MAAM,iBAAiB,CAAC;AACrD,WAAK,eAAe;AACpB,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,WAAiB;AACf,SAAK,sBAAsB;AAC3B,SAAK,SAAS,KAAK;AACnB,SAAK,SAAS,SAAS,aAAa;AAEpC,SAAK,kBAAkB;AAEvB,SAAK,SAAS,MAAM;AACpB,SAAK,SAAS,UAAU;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAmB;AACjB,SAAK,SAAS,KAAK;AACnB,SAAK,sBAAsB;AAC3B,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAyB;AACvB,WAAO,KAAK,SAAS,YAAY;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,UAAwB;AAE3C,UAAM,QAAQ,SAAS,WAAW,aAAa,IAC3C,SAAS,MAAM,cAAc,MAAM,EAAE,KAAK,IAC1C,SAAS,WAAW,WAAW,IAC7B,SAAS,MAAM,YAAY,MAAM,EAAE,KAAK,IACxC,SAAS,KAAK;AAEpB,QAAI,CAAC,OAAO;AAEV,WAAK,SAAS,MAAM;AACpB,WAAK,SAAS,UAAU;AACxB;AAAA,IACF;AAEA,QAAI,KAAK,cAAc;AAErB,YAAM,EAAE,SAAAA,SAAQ,IAAI,KAAK;AACzB,WAAK,eAAe;AAGpB,WAAK,QAAQ;AAGb,MAAAA,SAAQ,KAAK;AAAA,IACf,OAAO;AAEL,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,QAAI,KAAK,cAAc;AAGrB,WAAK,SAAS,MAAM;AACpB,WAAK,SAAS,UAAU;AAAA,IAC1B,OAAO;AACL,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAgB;AACtB,SAAK,sBAAsB;AAC3B,SAAK,SAAS,SAAS,WAAW;AAElC,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAyB;AAC/B,SAAK,sBAAsB;AAC3B,SAAK,SAAS,SAAS,cAAc;AAGrC,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAkB;AACxB,SAAK,sBAAsB;AAC3B,SAAK,SAAS,SAAS,aAAa;AACpC,SAAK,SAAS,MAAM;AACpB,SAAK,SAAS,UAAU;AACxB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAAqB,UAAwB;AACnD,UAAM,iBAAiB,KAAK,KAAK,WAAW;AAC5C,UAAM,YAAY,OAAO,SAAI,OAAO,EAAE,IAAI;AAC1C,UAAM,YAAY,GAAG,SAAS,KAAK,QAAQ,GAAG,SAAS;AAEvD,SAAK,KAAK,WAAW,iBAAiB,SAAS;AAC/C,SAAK,KAAK,gBAAgB,GAAG;AAC7B,SAAK,eAAe;AAAA,EACtB;AACF;;;AC1SA,SAAS,OAAAC,YAA+B;;;ACHxC,OAAOC,YAAW;AAQlB,IAAM,MAAM;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,eAAe;AAAA,EACf,cAAc;AAChB;AAWO,IAAM,qBAAqB;AAE3B,IAAM,qBAAqB;AAE3B,IAAM,kBAAkB;AAWxB,SAAS,uBAAuB,MAAmB,UAA2B;AACnF,QAAM,YAAY,KAAK,aAAa,qBAAqB;AACzD,QAAM,iBAAiB,KAAK,aAAaC,OAAM,QAAQA,OAAM;AAE7D,QAAM,QAAkB,CAAC;AAGzB,QAAM,aAAaA,OAAM,KAAK,IAAI,KAAK,SAAS,EAAE;AAClD,QAAM,QAAQA,OAAM,QAAQ,KAAK,KAAK;AACtC,QAAM,KAAK,GAAG,UAAU,IAAI,KAAK,EAAE;AAEnC,MAAI,KAAK,SAAS;AAChB,UAAM,IAAI,KAAK;AAGf,QAAI,EAAE,eAAe,EAAE,cAAc,GAAG;AACtC,YAAM,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,OAAO,IAAI,aAAa,EAAE,WAAW,CAAC,EAAE,CAAC;AAAA,IAC7E;AAGA,QAAI,EAAE,qBAAqB,EAAE,oBAAoB,GAAG;AAClD,YAAM,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,KAAK,IAAI,aAAa,EAAE,iBAAiB,CAAC,EAAE,CAAC;AAAA,IACjF;AAGA,QAAI,EAAE,gBAAgB,EAAE,eAAe,GAAG;AACxC,YAAM,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,MAAM,IAAI,aAAa,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,IAC7E;AAGA,QAAI,EAAE,mBAAmB,QAAW;AAClC,YAAM,KAAKA,OAAM,IAAI,GAAG,EAAE,eAAe,QAAQ,CAAC,CAAC,GAAG,CAAC;AAAA,IACzD;AAGA,QAAI,EAAE,SAAS,UAAa,EAAE,OAAO,GAAG;AACtC,YAAM,KAAKA,OAAM,KAAK,IAAI,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC;AAAA,IACjD;AAGA,QAAI,KAAK,cAAc,EAAE,cAAc;AACrC,YAAM,SAAS,EAAE,aAAa,YAAY;AAC1C,UAAI,WAAW,UAAU,WAAW,YAAY;AAC9C,cAAM,KAAKA,OAAM,MAAM,MAAM,CAAC;AAAA,MAChC,OAAO;AACL,cAAM,KAAKA,OAAM,OAAO,MAAM,CAAC;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,MAAM,KAAKA,OAAM,IAAI,KAAK,CAAC;AACxC,QAAM,SAAS,eAAe,SAAS;AAGvC,MAAI,UAAU;AACZ,WAAOA,OAAM,OAAO,MAAM,GAAG,MAAM,IAAI,IAAI,EAAE;AAAA,EAC/C;AAEA,SAAO,GAAG,MAAM,IAAI,IAAI;AAC1B;AAOO,SAAS,sBAAsB,MAA6B;AACjE,QAAM,QAAkB,CAAC;AACzB,QAAM,SAAS;AACf,QAAM,IAAI,KAAK;AAEf,MAAI,CAAC,GAAG;AACN,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,sBAAsB,CAAC,EAAE;AAC1D,WAAO;AAAA,EACT;AAGA,QAAM,QAAQ,KAAK,IAAI,KAAK,QAAQ,OAAO,WAAW,MAAM,CAAC;AAC7D,QAAM,aAAa,GAAG,IAAI,OAAO,GAAG,IAAI,UAAU,YAAY,IAAI,WAAW,OAAO,QAAQ,EAAE,CAAC;AAE/F,QAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,UAAU,CAAC,EAAE;AAG9C,QAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,aAAaA,OAAM,QAAQ,KAAK,KAAK,CAAC,EAAE;AAGtF,MAAI,EAAE,gBAAgB,QAAW;AAC/B,QAAI,YAAY,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,aAAaA,OAAM,OAAO,aAAa,EAAE,WAAW,CAAC,CAAC;AACzG,QAAI,EAAE,qBAAqB,EAAE,oBAAoB,GAAG;AAClD,YAAM,gBAAiB,EAAE,oBAAoB,EAAE,cAAe,KAAK,QAAQ,CAAC;AAC5E,mBAAaA,OAAM,KAAK,KAAK,aAAa,EAAE,iBAAiB,CAAC,YAAY,YAAY,IAAI;AAAA,IAC5F;AACA,UAAM,KAAK,SAAS;AAAA,EACtB;AAGA,MAAI,EAAE,iBAAiB,QAAW;AAChC,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,aAAaA,OAAM,MAAM,aAAa,EAAE,YAAY,CAAC,CAAC,SAAS;AAAA,EAC/G;AAGA,MAAI,EAAE,mBAAmB,QAAW;AAClC,QAAI,eAAeA,OAAM;AACzB,QAAI,EAAE,kBAAkB,GAAI,gBAAeA,OAAM;AAAA,aACxC,EAAE,kBAAkB,GAAI,gBAAeA,OAAM;AACtD,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,aAAa,aAAa,GAAG,KAAK,MAAM,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE;AAAA,EAC/G;AAGA,MAAI,EAAE,mBAAmB,QAAW;AAClC,QAAI,WAAW,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,aAAaA,OAAM,IAAI,GAAG,EAAE,eAAe,QAAQ,CAAC,CAAC,GAAG,CAAC;AAC3G,QAAI,EAAE,gBAAgB,EAAE,iBAAiB,GAAG;AAC1C,YAAM,eAAe,KAAK,MAAM,EAAE,eAAe,EAAE,cAAc;AACjE,kBAAYA,OAAM,IAAI,KAAK,YAAY,SAAS;AAAA,IAClD;AACA,UAAM,KAAK,QAAQ;AAAA,EACrB;AAGA,MAAI,EAAE,SAAS,UAAa,EAAE,OAAO,GAAG;AACtC,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,aAAaA,OAAM,KAAK,IAAI,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE;AAAA,EACnG;AAGA,MAAI,EAAE,cAAc;AAClB,UAAM,SAAS,EAAE,aAAa,YAAY;AAC1C,UAAM,cAAc,WAAW,UAAU,WAAW,aAAaA,OAAM,QAAQA,OAAM;AACrF,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,aAAa,YAAY,MAAM,CAAC,EAAE;AAAA,EAClF;AAGA,QAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,aAAa,IAAI,WAAW,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE;AAErF,SAAO;AACT;AAWO,SAAS,sBAAsB,MAAkB,UAA2B;AACjF,MAAI;AACJ,MAAI;AAEJ,MAAI,KAAK,OAAO;AACd,gBAAY;AACZ,qBAAiBA,OAAM;AAAA,EACzB,WAAW,KAAK,YAAY;AAC1B,gBAAY;AACZ,qBAAiBA,OAAM;AAAA,EACzB,OAAO;AACL,gBAAY;AACZ,qBAAiBA,OAAM;AAAA,EACzB;AAEA,QAAM,cAAcA,OAAM,QAAQ,KAAK,KAAK,IAAI;AAGhD,MAAI,YAAY;AAChB,MAAI,KAAK,cAAc,OAAO,KAAK,KAAK,UAAU,EAAE,SAAS,GAAG;AAC9D,UAAM,YAAY,QAAQ,OAAO,WAAW;AAC5C,UAAM,cAAc,KAAK,IAAI,IAAI,YAAY,EAAE;AAC/C,UAAM,UAAU,OAAO,QAAQ,KAAK,UAAU,EAAE,MAAM,GAAG,CAAC;AAC1D,UAAM,YAAY,QAAQ,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AAC9C,YAAM,WAAW,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK;AACzE,YAAM,YAAY,SAAS,SAAS,cAAc,SAAS,MAAM,GAAG,cAAc,CAAC,IAAI,QAAQ;AAC/F,aAAO,GAAGA,OAAM,IAAI,GAAG,CAAC,IAAIA,OAAM,KAAK,SAAS,CAAC;AAAA,IACnD,CAAC;AACD,gBAAY,GAAGA,OAAM,IAAI,GAAG,CAAC,GAAG,UAAU,KAAKA,OAAM,IAAI,IAAI,CAAC,CAAC,GAAGA,OAAM,IAAI,GAAG,CAAC;AAAA,EAClF;AAGA,MAAI,WAAW;AACf,MAAI,KAAK,OAAO;AACd,UAAM,YAAY,KAAK,MAAM,SAAS,KAAK,KAAK,MAAM,MAAM,GAAG,EAAE,IAAI,QAAQ,KAAK;AAClF,eAAW,IAAIA,OAAM,IAAI,QAAQ,CAAC,IAAI,SAAS;AAAA,EACjD;AAGA,QAAM,UAAoB,CAAC;AAG3B,MAAI,KAAK,oBAAoB,QAAW;AACtC,UAAM,OAAO,KAAK,mBAAmB,MACjC,IAAI,KAAK,kBAAkB,KAAM,QAAQ,CAAC,CAAC,MAC3C,GAAG,KAAK,MAAM,KAAK,eAAe,CAAC;AACvC,YAAQ,KAAK,IAAI;AAAA,EACnB;AAGA,MAAI,KAAK,iBAAiB,KAAK,cAAc,eAAe,GAAG;AAC7D,UAAM,EAAE,aAAa,cAAc,aAAa,IAAI,KAAK;AACzD,UAAM,aAAuB,CAAC;AAC9B,eAAW,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,OAAO,IAAI,aAAa,WAAW,CAAC,EAAE,CAAC;AAC9E,QAAI,eAAe,GAAG;AACpB,iBAAW,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,KAAK,IAAI,aAAa,YAAY,CAAC,EAAE,CAAC;AAAA,IAC/E;AACA,eAAW,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,MAAM,IAAI,aAAa,YAAY,CAAC,EAAE,CAAC;AAC9E,YAAQ,KAAK,WAAW,KAAK,GAAG,CAAC;AAAA,EACnC,WAAW,KAAK,gBAAgB,KAAK,eAAe,GAAG;AAErD,YAAQ,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,MAAM,IAAI,aAAa,KAAK,YAAY,CAAC,EAAE,CAAC;AAAA,EAClF;AAGA,MAAI,KAAK,QAAQ,KAAK,OAAO,GAAG;AAC9B,YAAQ,KAAKA,OAAM,KAAK,IAAI,WAAW,KAAK,IAAI,CAAC,EAAE,CAAC;AAAA,EACtD;AAGA,QAAM,aAAa,QAAQ,SAAS,IAAI,IAAIA,OAAM,IAAI,QAAQ,KAAK,KAAK,CAAC,CAAC,KAAK;AAE/E,QAAM,OAAO,GAAG,eAAe,SAAS,CAAC,IAAI,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU;AAG5F,MAAI,UAAU;AACZ,WAAOA,OAAM,OAAO,MAAM,IAAI;AAAA,EAChC;AAEA,SAAO;AACT;AAOO,SAAS,qBAAqB,MAA4B;AAC/D,QAAM,QAAkB,CAAC;AACzB,QAAM,SAAS;AACf,QAAM,YAAY,QAAQ,OAAO,WAAW;AAC5C,QAAM,QAAQ,KAAK,IAAI,IAAI,YAAY,CAAC;AAGxC,MAAI,KAAK,cAAc,OAAO,KAAK,KAAK,UAAU,EAAE,SAAS,GAAG;AAC9D,UAAM,aAAa,GAAG,IAAI,OAAO,GAAG,IAAI,UAAU,eAAe,IAAI,WAAW,OAAO,QAAQ,EAAE,CAAC;AAClG,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,UAAU,CAAC,EAAE;AAE9C,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,KAAK,UAAU,GAAG;AAC1D,YAAM,WAAW,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,OAAO,MAAM,CAAC;AAElF,YAAM,aAAa,SAAS,MAAM,IAAI;AACtC,YAAM,cAAc,QAAQ;AAC5B,UAAI,WAAW,WAAW,GAAG;AAC3B,cAAM,YAAY,SAAS,SAAS,cAAc,SAAS,MAAM,GAAG,cAAc,CAAC,IAAI,QAAQ;AAC/F,cAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,IAAIA,OAAM,IAAI,GAAG,CAAC,KAAKA,OAAM,KAAK,SAAS,CAAC,EAAE;AAAA,MAC9F,OAAO;AACL,cAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,IAAIA,OAAM,IAAI,GAAG,CAAC,GAAG;AACnE,mBAAW,QAAQ,WAAW,MAAM,GAAG,CAAC,GAAG;AACzC,gBAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,MAAMA,OAAM,KAAK,IAAI,CAAC,EAAE;AAAA,QACxE;AACA,YAAI,WAAW,SAAS,GAAG;AACzB,gBAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,MAAMA,OAAM,IAAI,QAAQ,WAAW,SAAS,CAAC,cAAc,CAAC,EAAE;AAAA,QAC9G;AAAA,MACF;AAAA,IACF;AACA,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,aAAa,IAAI,WAAW,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE;AAAA,EACvF;AAGA,MAAI,KAAK,UAAU,KAAK,OAAO;AAC7B,UAAM,aAAa,KAAK,QAAQ,YAAY;AAC5C,UAAM,aAAa,GAAG,IAAI,OAAO,GAAG,IAAI,UAAU,GAAG,UAAU,GAAG,IAAI,WAAW,OAAO,QAAQ,WAAW,SAAS,CAAC,CAAC;AACtH,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,UAAU,CAAC,EAAE;AAE9C,UAAM,UAAU,KAAK,SAAS,KAAK,UAAU;AAC7C,UAAM,eAAe,QAAQ,MAAM,IAAI;AACvC,UAAM,WAAW;AACjB,UAAM,eAAe,aAAa,MAAM,GAAG,QAAQ;AAEnD,eAAW,QAAQ,cAAc;AAC/B,YAAM,YAAY,KAAK,SAAS,QAAQ,IAAI,KAAK,MAAM,GAAG,QAAQ,CAAC,IAAI,QAAQ;AAC/E,YAAM,QAAQ,KAAK,QAAQA,OAAM,MAAMA,OAAM;AAC7C,YAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,IAAI,MAAM,SAAS,CAAC,EAAE;AAAA,IACtE;AAEA,QAAI,aAAa,SAAS,UAAU;AAClC,YAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,IAAIA,OAAM,IAAI,QAAQ,aAAa,SAAS,QAAQ,cAAc,CAAC,EAAE;AAAA,IACrH;AAGA,QAAI,KAAK,oBAAoB,QAAW;AACtC,YAAM,OAAO,KAAK,mBAAmB,MACjC,IAAI,KAAK,kBAAkB,KAAM,QAAQ,CAAC,CAAC,MAC3C,GAAG,KAAK,MAAM,KAAK,eAAe,CAAC;AACvC,YAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,UAAUA,OAAM,IAAI,IAAI,CAAC,EAAE;AAAA,IAC3E;AAEA,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,aAAa,IAAI,WAAW,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE;AAAA,EACvF;AAGA,MAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,UAAM,aAAa,GAAG,IAAI,OAAO,GAAG,IAAI,UAAU,sBAAsB,IAAI,WAAW,OAAO,QAAQ,EAAE,CAAC;AACzG,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,UAAU,CAAC,EAAE;AAC9C,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,IAAIA,OAAM,IAAI,GAAG,KAAK,SAAS,MAAM,gDAAgD,CAAC,EAAE;AACtI,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,aAAa,IAAI,WAAW,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE;AAAA,EACvF;AAGA,MAAI,KAAK,oBAAoB,UAAa,KAAK,QAAQ,KAAK,gBAAgB,KAAK,eAAe;AAC9F,UAAM,oBAAoB,GAAG,IAAI,OAAO,GAAG,IAAI,UAAU,YAAY,IAAI,WAAW,OAAO,QAAQ,EAAE,CAAC;AACtG,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,iBAAiB,CAAC,EAAE;AAGrD,QAAI,KAAK,oBAAoB,QAAW;AACtC,YAAM,OAAO,KAAK,mBAAmB,MACjC,IAAI,KAAK,kBAAkB,KAAM,QAAQ,CAAC,CAAC,MAC3C,GAAG,KAAK,MAAM,KAAK,eAAe,CAAC;AACvC,YAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,cAAcA,OAAM,IAAI,IAAI,CAAC,EAAE;AAAA,IAC/E;AAGA,QAAI,KAAK,gBAAgB,KAAK,eAAe,GAAG;AAC9C,YAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,cAAcA,OAAM,MAAM,IAAI,aAAa,KAAK,YAAY,CAAC,EAAE,CAAC,SAAS;AAAA,IACzH;AAGA,QAAI,KAAK,QAAQ,KAAK,OAAO,GAAG;AAC9B,YAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,cAAcA,OAAM,KAAK,IAAI,WAAW,KAAK,IAAI,CAAC,EAAE,CAAC,EAAE;AAAA,IACvG;AAGA,QAAI,KAAK,iBAAiB,KAAK,cAAc,eAAe,GAAG;AAC7D,YAAM,IAAI,KAAK;AACf,YAAM,aAAuB,CAAC;AAC9B,iBAAW,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,OAAO,IAAI,aAAa,EAAE,WAAW,CAAC,EAAE,CAAC;AAChF,UAAI,EAAE,eAAe,GAAG;AACtB,mBAAW,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,KAAK,IAAI,aAAa,EAAE,YAAY,CAAC,EAAE,CAAC;AAAA,MACjF;AACA,iBAAW,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,MAAM,IAAI,aAAa,EAAE,YAAY,CAAC,EAAE,CAAC;AAChF,YAAM,WAAW,WAAW,KAAK,GAAG;AACpC,YAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,QAAQ,CAAC,eAAe,EAAE,YAAY,KAAK,QAAQ,GAAG;AAAA,IAC7F;AAEA,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,IAAI,aAAa,IAAI,WAAW,OAAO,QAAQ,CAAC,CAAC,CAAC,EAAE;AAAA,EACvF;AAEA,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,KAAK,GAAG,MAAM,GAAGA,OAAM,IAAI,sBAAsB,CAAC,EAAE;AAAA,EAC5D;AAEA,SAAO;AACT;AAUO,SAAS,UAAU,OAAe,SAAS,OAAe;AAC/D,MAAI,UAAU,EAAG,QAAO;AAExB,QAAM,aAAa,KAAK,OAAO,QAAQ,CAAC;AACxC,QAAM,YAAY,SAAS,kBAAQ;AACnC,SAAO,aAAa;AACtB;AAKO,SAAS,sBAAsB,OAAuB;AAC3D,MAAI,UAAU,EAAG,QAAO;AACxB,SAAO,KAAK,OAAO,KAAK,IAAI;AAC9B;;;AD1XO,IAAM,gBAAN,MAAM,eAAc;AAAA,EACjB;AAAA,EACA;AAAA;AAAA,EAGA,QAAQ,oBAAI,IAAuB;AAAA;AAAA,EAGnC,UAAoB,CAAC;AAAA;AAAA,EAGrB,SAAS,oBAAI,IAA6B;AAAA;AAAA,EAG1C,gBAA0B,CAAC;AAAA;AAAA,EAG3B,gBAAgB;AAAA;AAAA,EAGhB,gBAAgB;AAAA;AAAA,EAGhB,mBAAkC;AAAA;AAAA,EAGlC,iBAAiB,oBAAI,IAAqB;AAAA;AAAA,EAG1C,aAAsB;AAAA;AAAA,EAG9B,OAAwB,sBAAsB;AAAA;AAAA,EAGtC,qBAAqB,oBAAI,IAAoB;AAAA;AAAA,EAG7C,uBAAuB,oBAAI,IAAoB;AAAA;AAAA,EAG/C,qBAAqB,oBAAI,IAAoB;AAAA,EAErD,YAAY,WAA0B,gBAA4B;AAChE,SAAK,YAAY;AACjB,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBA,WACE,WACA,OACA,gBACA,UACQ;AAGR,QAAI,CAAC,kBAAkB,CAAC,UAAU;AAChC,YAAM,aAAa,KAAK,mBAAmB,IAAI,SAAS;AACxD,UAAI,YAAY;AAEd,aAAK,mBAAmB;AACxB,eAAO;AAAA,MACT;AAAA,IACF,WAAW,gBAAgB;AAEzB,YAAM,YAAY,GAAG,cAAc,IAAI,SAAS;AAChD,YAAM,aAAa,KAAK,mBAAmB,IAAI,SAAS;AACxD,UAAI,YAAY;AAEd,aAAK,mBAAmB;AACxB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,KAAK,KAAK,WAAW,KAAK;AAChC,UAAM,aAAa,iBAAiB,KAAK,QAAQ,cAAc,IAAI;AACnE,UAAM,QAAQ,aAAa,WAAW,QAAQ,IAAI;AAElD,UAAM,OAAoB;AAAA,MACxB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,UAAU,kBAAkB;AAAA,MAC5B;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ,UAAU,CAAC;AAAA,IACb;AAEA,SAAK,MAAM,IAAI,IAAI,IAAI;AAEvB,QAAI,gBAAgB;AAElB,YAAM,SAAS,KAAK,QAAQ,cAAc;AAC1C,aAAO,SAAS,KAAK,EAAE;AAEvB,YAAM,YAAY,GAAG,cAAc,IAAI,SAAS;AAChD,WAAK,mBAAmB,IAAI,WAAW,EAAE;AAAA,IAC3C,OAAO;AAEL,WAAK,QAAQ,KAAK,EAAE;AACpB,WAAK,mBAAmB,IAAI,WAAW,EAAE;AAAA,IAC3C;AAEA,SAAK,mBAAmB;AACxB,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,gBACE,IACA,SACA,aACM;AACN,UAAM,OAAO,KAAK,QAAQ,EAAE;AAC5B,QAAI,CAAC,QAAQ,KAAK,SAAS,WAAY;AAEvC,SAAK,aAAa;AAClB,SAAK,UAAU;AACf,QAAI,gBAAgB,QAAW;AAC7B,WAAK,cAAc;AAAA,IACrB;AACA,SAAK,YAAY,EAAE;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBACE,IACA,UACM;AACN,UAAM,OAAO,KAAK,QAAQ,EAAE;AAC5B,QAAI,CAAC,QAAQ,KAAK,SAAS,WAAY;AACvC,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,UACE,cACA,MACA,YACQ;AAER,UAAM,aAAa,KAAK,qBAAqB,IAAI,YAAY;AAC7D,QAAI,YAAY;AAEd,aAAO;AAAA,IACT;AAEA,UAAM,KAAK,KAAK,WAAW,QAAQ;AACnC,UAAM,kBAAkB,KAAK;AAG7B,QAAI,QAAQ;AACZ,QAAI,iBAAiB;AACnB,YAAM,SAAS,KAAK,QAAQ,eAAe;AAC3C,UAAI,QAAQ;AACV,gBAAQ,OAAO,QAAQ;AAAA,MACzB;AAAA,IACF;AAEA,UAAM,OAAmB;AAAA,MACvB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ;AAAA,MACA,UAAU,CAAC;AAAA;AAAA,IACb;AAEA,SAAK,MAAM,IAAI,IAAI,IAAI;AAEvB,QAAI,iBAAiB;AAEnB,YAAM,SAAS,KAAK,QAAQ,eAAe;AAC3C,aAAO,SAAS,KAAK,EAAE;AAAA,IACzB,OAAO;AAEL,WAAK,QAAQ,KAAK,EAAE;AAAA,IACtB;AAGA,SAAK,qBAAqB,IAAI,cAAc,EAAE;AAE9C,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,eACE,cACA,QACA,OACA,iBACA,MACM;AAEN,UAAM,OAAO,KAAK,yBAAyB,YAAY;AACvD,QAAI,CAAC,KAAM;AAEX,SAAK,aAAa;AAClB,SAAK,SAAS;AACd,SAAK,QAAQ;AACb,SAAK,kBAAkB;AACvB,SAAK,OAAO;AAGZ,QAAI,QAAQ;AACV,WAAK,eAAe,KAAK,KAAK,OAAO,SAAS,CAAC;AAAA,IACjD;AAGA,QAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,WAAK,gBAAgB,KAAK,uBAAuB,KAAK,QAAQ;AAAA,IAChE;AAEA,SAAK,YAAY,KAAK,EAAE;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKQ,uBACN,UAC6B;AAC7B,QAAI,cAAc;AAClB,QAAI,eAAe;AACnB,QAAI,eAAe;AACnB,QAAI,OAAO;AACX,QAAI,eAAe;AAEnB,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,KAAK,MAAM,IAAI,OAAO;AACpC,UAAI,OAAO,SAAS,cAAc,MAAM,SAAS;AAC/C,uBAAe,MAAM,QAAQ,eAAe;AAC5C,wBAAgB,MAAM,QAAQ,gBAAgB;AAC9C,wBAAgB,MAAM,QAAQ,qBAAqB;AACnD,gBAAQ,MAAM,QAAQ,QAAQ;AAC9B;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,aAAa,cAAc,cAAc,MAAM,aAAa;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,SAAyB;AAC/B,UAAM,KAAK,KAAK,WAAW,MAAM;AAEjC,UAAM,OAAiB;AAAA,MACrB;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,MACP,UAAU;AAAA,MACV;AAAA,MACA,UAAU,CAAC;AAAA,IACb;AAEA,SAAK,MAAM,IAAI,IAAI,IAAI;AACvB,SAAK,QAAQ,KAAK,EAAE;AACpB,SAAK,cAAc;AACnB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,yBAAyB,cAA8C;AACrE,UAAM,UAAU,KAAK,qBAAqB,IAAI,YAAY;AAC1D,QAAI,CAAC,QAAS,QAAO;AACrB,UAAM,OAAO,KAAK,MAAM,IAAI,OAAO;AACnC,WAAO,MAAM,SAAS,WAAY,OAAsB;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,kBAAkB,WAAgC;AAChD,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,sBAAqC;AACnC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAA4B;AAC1B,WAAO,KAAK,oBAAoB;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAmB,IAAY,aAA2B;AACxD,UAAM,OAAO,KAAK,QAAQ,EAAE;AAC5B,QAAI,CAAC,QAAQ,KAAK,SAAS,WAAY;AACvC,SAAK,cAAc;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,MAAM,MAAM;AACjB,SAAK,OAAO,MAAM;AAClB,SAAK,eAAe,MAAM;AAC1B,SAAK,mBAAmB,MAAM;AAC9B,SAAK,qBAAqB,MAAM;AAChC,SAAK,mBAAmB,MAAM;AAC9B,SAAK,UAAU,CAAC;AAChB,SAAK,gBAAgB,CAAC;AACtB,SAAK,gBAAgB;AACrB,SAAK,mBAAmB;AAGxB,eAAW,SAAS,CAAC,GAAG,KAAK,UAAU,QAAQ,GAAG;AAChD,YAAM,OAAO;AAAA,IACf;AACA,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,aAAmB;AACjB,QAAI,KAAK,cAAc,WAAW,EAAG;AAErC,QAAI,KAAK,gBAAgB,KAAK,cAAc,SAAS,GAAG;AACtD,WAAK;AACL,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAAuB;AACrB,QAAI,KAAK,cAAc,WAAW,EAAG;AAErC,QAAI,KAAK,gBAAgB,GAAG;AAC1B,WAAK;AACL,WAAK,gBAAgB;AAAA,IACvB,WAAW,KAAK,kBAAkB,MAAM,KAAK,cAAc,SAAS,GAAG;AAErE,WAAK,gBAAgB,KAAK,cAAc,SAAS;AACjD,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,cAAoB;AAClB,QAAI,KAAK,cAAc,SAAS,GAAG;AACjC,WAAK,gBAAgB;AACrB,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,aAAmB;AACjB,QAAI,KAAK,cAAc,SAAS,GAAG;AACjC,WAAK,gBAAgB,KAAK,cAAc,SAAS;AACjD,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAgD;AAC9C,QAAI,KAAK,gBAAgB,KAAK,KAAK,iBAAiB,KAAK,cAAc,QAAQ;AAC7E,aAAO;AAAA,IACT;AACA,WAAO,KAAK,OAAO,IAAI,KAAK,cAAc,KAAK,aAAa,CAAC;AAAA,EAC/D;AAAA;AAAA;AAAA;AAAA,EAKA,eAAqB;AACnB,UAAM,QAAQ,KAAK,iBAAiB;AACpC,QAAI,CAAC,MAAO;AAEZ,UAAM,WAAW,CAAC,MAAM;AAExB,SAAK,eAAe,IAAI,MAAM,KAAK,IAAI,MAAM,QAAQ;AACrD,SAAK,YAAY,MAAM,KAAK,EAAE;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,qBAA2B;AACzB,UAAM,QAAQ,KAAK,iBAAiB;AACpC,QAAI,CAAC,MAAO;AAEZ,QAAI,MAAM,UAAU;AAClB,YAAM,WAAW;AAEjB,WAAK,eAAe,IAAI,MAAM,KAAK,IAAI,KAAK;AAC5C,WAAK,YAAY,MAAM,KAAK,EAAE;AAAA,IAChC,OAAO;AACL,WAAK,gBAAgB;AACrB,WAAK,gBAAgB;AAAA,IACvB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,WAAW,QAAwB;AACzC,WAAO,GAAG,MAAM,IAAI,EAAE,KAAK,aAAa;AAAA,EAC1C;AAAA,EAEQ,QAAQ,IAAmC;AACjD,WAAO,KAAK,MAAM,IAAI,EAAE;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAsB;AAE5B,eAAW,SAAS,CAAC,GAAG,KAAK,UAAU,QAAQ,GAAG;AAChD,YAAM,OAAO;AAAA,IACf;AACA,SAAK,OAAO,MAAM;AAClB,SAAK,gBAAgB,CAAC;AAGtB,QAAI,MAAM;AAGV,eAAW,UAAU,KAAK,SAAS;AACjC,YAAM,KAAK,eAAe,QAAQ,GAAG;AAAA,IACvC;AAGA,QAAI,KAAK,iBAAiB,KAAK,cAAc,QAAQ;AACnD,WAAK,gBAAgB,KAAK,cAAc,SAAS;AAAA,IACnD;AAGA,SAAK,8BAA8B;AAEnC,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,eAAe,QAAgB,KAAqB;AAC1D,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,QAAI,CAAC,KAAM,QAAO;AAGlB,UAAM,QAAQ,KAAK,YAAY,MAAM,GAAG;AACxC,SAAK,OAAO,IAAI,QAAQ,KAAK;AAG7B,QAAI,MAAM,YAAY;AACpB,WAAK,cAAc,KAAK,MAAM;AAAA,IAChC;AAGA,UAAM,SAAS,KAAK,eAAe,KAAK;AACxC,WAAO;AAIP,QAAI,cAAc,QAAQ,KAAK,SAAS,SAAS,GAAG;AAClD,iBAAW,WAAW,KAAK,UAAU;AACnC,cAAM,KAAK,eAAe,SAAS,GAAG;AAAA,MACxC;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,MAAiB,KAA8B;AACjE,UAAM,aAAa,KAAK,cAAc,WAAW,KAAK;AACtD,UAAM,aAAa,KAAK,SAAS;AAGjC,UAAM,WAAW,KAAK,eAAe,IAAI,KAAK,EAAE,KAAK;AAGrD,UAAM,UAAU,KAAK,mBAAmB,MAAM,YAAY,QAAQ;AAGlE,UAAM,MAAM,IAAIC,KAAI;AAAA,MAClB,QAAQ,KAAK;AAAA,MACb;AAAA,MACA,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ,QAAQ,MAAM,IAAI,EAAE;AAAA,MAC5B;AAAA,MACA,MAAM;AAAA;AAAA,IACR,CAAC;AAED,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,mBACN,MACA,UACA,UACQ;AACR,UAAM,SAAS,UAAU,KAAK,KAAK;AAEnC,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK,YAAY;AACf,cAAM,YAAY,uBAAuB,MAAM,QAAQ;AACvD,YAAI,CAAC,UAAU;AACb,iBAAO,SAAS;AAAA,QAClB;AACA,cAAM,gBAAgB,sBAAsB,IAAI;AAChD,cAAM,aAAa,sBAAsB,KAAK,KAAK;AACnD,eAAO;AAAA,UACL,SAAS;AAAA,UACT,GAAG,cAAc,IAAI,CAAC,SAAS,aAAa,IAAI;AAAA,QAClD,EAAE,KAAK,IAAI;AAAA,MACb;AAAA,MAEA,KAAK,UAAU;AACb,cAAM,YAAY,sBAAsB,MAAM,QAAQ;AACtD,YAAI,CAAC,UAAU;AACb,iBAAO,SAAS;AAAA,QAClB;AACA,cAAM,gBAAgB,qBAAqB,IAAI;AAC/C,cAAM,aAAa,sBAAsB,KAAK,KAAK;AACnD,eAAO;AAAA,UACL,SAAS;AAAA,UACT,GAAG,cAAc,IAAI,CAAC,SAAS,aAAa,IAAI;AAAA,QAClD,EAAE,KAAK,IAAI;AAAA,MACb;AAAA,MAEA,KAAK;AACH,eAAO,KAAK;AAAA,IAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,OAAgC;AACrD,UAAM,UAAU,MAAM,IAAI,WAAW;AACrC,WAAO,QAAQ,MAAM,IAAI,EAAE;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKQ,YAAY,QAAsB;AACxC,UAAM,QAAQ,KAAK,OAAO,IAAI,MAAM;AACpC,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,QAAI,CAAC,SAAS,CAAC,KAAM;AAErB,UAAM,aAAa,KAAK,cAAc,KAAK,aAAa,MAAM;AAC9D,UAAM,UAAU,KAAK,mBAAmB,MAAM,YAAY,MAAM,QAAQ;AAExE,UAAM,YAAY,KAAK,eAAe,KAAK;AAC3C,UAAM,IAAI,WAAW,OAAO;AAC5B,UAAM,YAAY,QAAQ,MAAM,IAAI,EAAE;AACtC,UAAM,IAAI,SAAS;AAGnB,QAAI,cAAc,WAAW;AAC3B,WAAK,iBAAiB;AAAA,IACxB;AAEA,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAwB;AAE9B,eAAW,MAAM,KAAK,eAAe;AACnC,YAAM,QAAQ,KAAK,OAAO,IAAI,EAAE;AAChC,UAAI,OAAO;AACT,cAAM,aAAa,KAAK,cAAc,KAAK,aAAa,MAAM;AAC9D,cAAM,UAAU,KAAK,mBAAmB,MAAM,MAAM,YAAY,MAAM,QAAQ;AAC9E,cAAM,IAAI,WAAW,OAAO;AAAA,MAC9B;AAAA,IACF;AAGA,SAAK,kBAAkB;AACvB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAyB;AAC/B,QAAI,MAAM;AACV,eAAW,UAAU,KAAK,SAAS;AACjC,YAAM,KAAK,mBAAmB,QAAQ,GAAG;AAAA,IAC3C;AAGA,SAAK,8BAA8B;AAAA,EACrC;AAAA,EAEQ,mBAAmB,QAAgB,KAAqB;AAC9D,UAAM,QAAQ,KAAK,OAAO,IAAI,MAAM;AACpC,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,QAAI,CAAC,SAAS,CAAC,KAAM,QAAO;AAE5B,UAAM,IAAI,MAAM;AAChB,UAAM,SAAS,KAAK,eAAe,KAAK;AACxC,WAAO;AAGP,QAAI,cAAc,MAAM;AACtB,iBAAW,WAAW,KAAK,UAAU;AACnC,cAAM,KAAK,mBAAmB,SAAS,GAAG;AAAA,MAC5C;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAA0B;AAChC,UAAM,QAAQ,KAAK,iBAAiB;AACpC,QAAI,CAAC,MAAO;AAGZ,QAAI,CAAC,KAAK,UAAU,aAAa,CAAC,KAAK,UAAU,SAAU;AAE3D,UAAM,WAAW,MAAM,IAAI;AAC3B,UAAM,cAAc,KAAK,eAAe,KAAK;AAC7C,UAAM,kBAAkB,KAAK,UAAU;AACvC,UAAM,YAAY,KAAK,UAAU,UAAU;AAG3C,QAAI,WAAW,WAAW;AACxB,WAAK,UAAU,SAAS,QAAQ;AAEhC,WAAK,aAAa;AAAA,IACpB,WAES,WAAW,cAAc,YAAY,iBAAiB;AAC7D,WAAK,UAAU,SAAS,WAAW,cAAc,eAAe;AAEhE,UAAI,KAAK,WAAW,GAAG;AACrB,aAAK,aAAa;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,wBAAgC;AACtC,QAAI,cAAc;AAClB,eAAW,UAAU,KAAK,SAAS;AACjC,oBAAc,KAAK,kBAAkB,QAAQ,WAAW;AAAA,IAC1D;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB,QAAgB,eAA+B;AACvE,UAAM,QAAQ,KAAK,OAAO,IAAI,MAAM;AACpC,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,QAAI,CAAC,SAAS,CAAC,KAAM,QAAO;AAE5B,qBAAiB,KAAK,eAAe,KAAK;AAE1C,QAAI,cAAc,MAAM;AACtB,iBAAW,WAAW,KAAK,UAAU;AACnC,wBAAgB,KAAK,kBAAkB,SAAS,aAAa;AAAA,MAC/D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,2BAAmC;AACzC,UAAM,kBAAkB,KAAK,UAAU;AACvC,UAAM,gBAAgB,KAAK,sBAAsB;AAEjD,QAAI,iBAAiB,iBAAiB;AACpC,aAAO;AAAA,IACT;AAEA,WAAO,kBAAkB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAsB;AAC5B,QAAI,CAAC,KAAK,UAAU,UAAW,QAAO;AAEtC,UAAM,YAAY,KAAK,UAAU,UAAU;AAC3C,UAAM,kBAAkB,KAAK,UAAU;AACvC,UAAM,gBAAgB,KAAK,sBAAsB;AAGjD,UAAM,YAAY,KAAK,IAAI,GAAG,gBAAgB,eAAe;AAC7D,WAAO,aAAa,YAAY,eAAc;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAuB;AAC7B,QAAI,CAAC,KAAK,UAAU,cAAe;AACnC,SAAK,UAAU,cAAc,GAAG;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,gCAAsC;AAC5C,UAAM,SAAS,KAAK,yBAAyB;AAG7C,QAAI,SAAS,GAAG;AACd,iBAAW,UAAU,KAAK,SAAS;AACjC,aAAK,sBAAsB,QAAQ,MAAM;AAAA,MAC3C;AAAA,IACF;AAGA,QAAI,KAAK,YAAY;AACnB,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,sBAAsB,QAAgB,QAAsB;AAClE,UAAM,QAAQ,KAAK,OAAO,IAAI,MAAM;AACpC,UAAM,OAAO,KAAK,QAAQ,MAAM;AAChC,QAAI,CAAC,SAAS,CAAC,KAAM;AAErB,UAAM,IAAI,MAAO,MAAM,IAAI,MAAiB;AAE5C,QAAI,cAAc,MAAM;AACtB,iBAAW,WAAW,KAAK,UAAU;AACnC,aAAK,sBAAsB,SAAS,MAAM;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAyB;AACvB,QAAI,CAAC,KAAK,WAAW,GAAG;AACtB,WAAK,aAAa;AAAA,IACpB,OAAO;AAEL,WAAK,aAAa;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAAyB;AACvB,SAAK,aAAa;AAClB,SAAK,eAAe;AACpB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,eAAqB;AACnB,SAAK,iBAAiB;AACtB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,kBAAuC;AAAA;AAAA,EAGvC,oBAAoB,oBAAI,IAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBpD,gBAAgB,MAAiC;AAE/C,QAAI,KAAK,iBAAiB;AACxB,WAAK,gBAAgB;AAAA,IACvB;AAEA,SAAK,kBAAkB,MAAM;AAG7B,SAAK,kBAAkB,KAAK,MAAM,CAAC,UAA0B;AAC3D,WAAK,gBAAgB,OAAO,IAAI;AAAA,IAClC,CAAC;AAED,WAAO,MAAM;AACX,UAAI,KAAK,iBAAiB;AACxB,aAAK,gBAAgB;AACrB,aAAK,kBAAkB;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,OAAuB,MAA2B;AACxE,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK,kBAAkB;AAErB,YAAI;AACJ,YAAI,MAAM,UAAU;AAClB,0BAAgB,KAAK,kBAAkB,IAAI,MAAM,QAAQ;AAAA,QAC3D;AAOA,cAAM,UAAU,KAAK;AAAA,UACnB,MAAM,YAAY;AAAA,UAClB,MAAM;AAAA,UACN;AAAA,UACA,MAAM,QAAQ;AAAA,QAChB;AACA,aAAK,kBAAkB,IAAI,MAAM,QAAQ,OAAO;AAGhD,cAAM,YAAY,KAAK,QAAQ,MAAM,MAAM;AAC3C,YAAI,WAAW,SAAS,cAAc,UAAU,SAAS;AACvD,eAAK,kBAAkB,SAAS,UAAU,OAAO;AAAA,QACnD;AACA;AAAA,MACF;AAAA,MAEA,KAAK,qBAAqB;AACxB,cAAM,UAAU,KAAK,kBAAkB,IAAI,MAAM,MAAM;AACvD,YAAI,SAAS;AACX,eAAK,gBAAgB,SAAS;AAAA,YAC5B,aAAa,MAAM,OAAO;AAAA,YAC1B,mBAAmB,MAAM,OAAO;AAAA,YAChC,cAAc,MAAM,OAAO;AAAA,YAC3B,MAAM,MAAM;AAAA,YACZ,cAAc,MAAM,gBAAgB;AAAA,UACtC,CAAC;AAGD,gBAAM,eAAe,KAAK,QAAQ,MAAM,MAAM;AAC9C,cAAI,cAAc,SAAS,cAAc,aAAa,UAAU;AAC9D,iBAAK,mBAAmB,SAAS,aAAa,QAAQ;AAAA,UACxD;AAAA,QACF;AACA;AAAA,MACF;AAAA,MAEA,KAAK,eAAe;AAElB,YAAI;AACJ,YAAI,MAAM,UAAU;AAClB,0BAAgB,KAAK,kBAAkB,IAAI,MAAM,QAAQ;AAAA,QAC3D;AAGA,cAAM,oBAAoB,KAAK;AAC/B,YAAI,eAAe;AACjB,eAAK,kBAAkB,aAAa;AAAA,QACtC;AAEA,cAAM,UAAU,KAAK;AAAA,UACnB,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AACA,aAAK,kBAAkB,IAAI,MAAM,QAAQ,OAAO;AAGhD,aAAK,mBAAmB;AACxB;AAAA,MACF;AAAA,MAEA,KAAK,mBAAmB;AACtB,aAAK;AAAA,UACH,MAAM;AAAA,UACN,MAAM;AAAA,UACN;AAAA,UACA,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AACA;AAAA,MACF;AAAA,MAEA,KAAK,gBAAgB;AACnB,aAAK;AAAA,UACH,MAAM;AAAA,UACN;AAAA,UACA,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AACA;AAAA,MACF;AAAA,MAEA,KAAK,kBAAkB;AAErB,cAAM,OAAO,KAAK,yBAAyB,MAAM,YAAY;AAC7D,YAAI,MAAM;AACR,eAAK,aAAa;AAClB,eAAK,QAAQ,YAAY,MAAM,qBAAqB;AACpD,eAAK,YAAY,KAAK,EAAE;AAAA,QAC1B;AACA;AAAA,MACF;AAAA,IAIF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB,YAAwC;AAC5D,WAAO,KAAK,kBAAkB,IAAI,UAAU;AAAA,EAC9C;AACF;;;AEljCA,SAAS,OAAAC,YAAwB;AAIjC,IAAM,oBAAoB;AAG1B,IAAM,yBAAyB;AASxB,SAAS,mBACd,QACA,SAC2B;AAC3B,SAAO,IAAI,QAAQ,CAACC,aAAY;AAE9B,UAAM,UAAU,mBAAmB,OAAO;AAG1C,UAAM,SAAS,IAAID,KAAI;AAAA,MACrB,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA;AAAA,MAER;AAAA,MACA,MAAM;AAAA;AAAA,MAEN,QAAQ;AAAA,QACN,MAAM;AAAA,MACR;AAAA,MACA,OAAO;AAAA,QACL,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,QAAQ;AAAA,UACN,IAAI;AAAA,QACN;AAAA,MACF;AAAA;AAAA,MAEA,SAAS;AAAA,QACP,MAAM;AAAA,QACN,OAAO;AAAA,QACP,KAAK;AAAA,QACL,QAAQ;AAAA,MACV;AAAA;AAAA;AAAA,IAGF,CAAC;AAGD,WAAO,MAAM;AAGb,UAAM,YAAY,CAAC,IAAY,QAA0B;AACvD,UAAI,WAAoC;AAExC,cAAQ,IAAI,MAAM;AAAA,QAChB,KAAK;AACH,qBAAW;AACX;AAAA,QACF,KAAK;AACH,qBAAW;AACX;AAAA,QACF,KAAK;AACH,qBAAW;AACX;AAAA,QACF,KAAK;AACH,qBAAW;AACX;AAAA,QACF,KAAK;AACH,qBAAW;AACX;AAAA,MACJ;AAEA,UAAI,UAAU;AAEZ,eAAO,QAAQ;AACf,eAAO,OAAO;AAGd,QAAAC,SAAQ,QAAQ;AAAA,MAClB;AAAA,IACF;AAEA,WAAO,GAAG,YAAY,SAAS;AAC/B,WAAO,OAAO;AAAA,EAChB,CAAC;AACH;AAKA,SAAS,mBAAmB,SAAkC;AAC5D,QAAM,QAAkB,CAAC;AAGzB,QAAM,KAAK,4BAA4B,QAAQ,UAAU,MAAM;AAC/D,QAAM,KAAK,EAAE;AAGb,MAAI,OAAO,KAAK,QAAQ,UAAU,EAAE,SAAS,GAAG;AAC9C,UAAM,KAAK,sBAAsB;AACjC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,QAAQ,UAAU,GAAG;AAC7D,YAAM,WAAW,iBAAiB,KAAK;AACvC,YAAM,KAAK,cAAc,GAAG,QAAQ,QAAQ,EAAE;AAAA,IAChD;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,MAAI,QAAQ,SAAS;AACnB,UAAM,KAAK,mBAAmB;AAC9B,UAAM,eAAe,QAAQ,QAAQ,MAAM,IAAI,EAAE,MAAM,GAAG,iBAAiB;AAC3E,eAAW,QAAQ,cAAc;AAC/B,YAAM,KAAK,cAAc,cAAc,IAAI,CAAC,KAAK;AAAA,IACnD;AACA,QAAI,QAAQ,QAAQ,MAAM,IAAI,EAAE,SAAS,mBAAmB;AAC1D,YAAM,KAAK,mBAAmB;AAAA,IAChC;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,QAAM,KAAK,mBAAmB;AAC9B,QAAM,KAAK,8CAA8C;AACzD,QAAM,KAAK,yCAAyC;AACpD,QAAM,KAAK,oDAAoD;AAC/D,QAAM,KAAK,sDAAsD;AACjE,QAAM,KAAK,iCAAiC;AAE5C,SAAO,MAAM,KAAK,IAAI;AACxB;AAKA,SAAS,iBAAiB,OAAwB;AAChD,MAAI;AAEJ,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM;AAAA,EACR,WAAW,UAAU,QAAQ,UAAU,QAAW;AAChD,UAAM,OAAO,KAAK;AAAA,EACpB,OAAO;AACL,UAAM,KAAK,UAAU,KAAK;AAAA,EAC5B;AAGA,MAAI,IAAI,SAAS,wBAAwB;AACvC,UAAM,IAAI,MAAM,GAAG,yBAAyB,CAAC,IAAI;AAAA,EACnD;AAGA,SAAO,cAAc,GAAG;AAC1B;AAKA,SAAS,cAAc,KAAqB;AAE1C,SAAO,IAAI,QAAQ,OAAO,IAAI,EAAE,QAAQ,OAAO,IAAI;AACrD;;;ACtKA,SAAS,OAAAC,YAAwB;AAqBjC,IAAM,QAAQ;AACd,IAAM,OAAO;AACb,IAAM,MAAM;AACZ,IAAM,MAAM;AACZ,IAAM,UAAU;AAChB,IAAM,QAAQ;AACd,IAAM,OAAO;AACb,IAAM,SAAS;AACf,IAAM,QAAQ;AAeP,SAAS,cAAc,SAA4C;AACxE,MAAI,gBAA4B,MAAM;AAAA,EAAC;AAEvC,QAAM,SAAS,IAAI,QAAc,CAACC,aAAY;AAC5C,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI;AAGJ,QAAI;AACJ,QAAI;AAGJ,UAAM,WAAW,eAAe;AAEhC,QAAI,UAAU;AAEZ,UAAI,SAAS,WAAW;AACtB,gBAAQ,qBAAqB,UAAU;AACvC,YAAI,CAAC,cAAc,OAAO,KAAK,UAAU,EAAE,WAAW,GAAG;AACvD,oBAAU,GAAG,GAAG,gBAAgB,KAAK;AAAA,QACvC,OAAO;AACL,oBAAU,uBAAuB,UAAU;AAAA,QAC7C;AAAA,MACF,OAAO;AACL,gBAAQ,iBAAiB,UAAU;AACnC,YAAI,OAAO;AACT,oBAAU,GAAG,GAAG,GAAG,IAAI,SAAS,KAAK;AAAA,EAAK,KAAK;AAAA,QACjD,WAAW,CAAC,QAAQ;AAClB,oBAAU,GAAG,GAAG,2BAA2B,KAAK;AAAA,QAClD,OAAO;AACL,oBAAU,mBAAmB,MAAM;AAAA,QACrC;AAAA,MACF;AAAA,IACF,OAAO;AAEL,UAAI,SAAS,WAAW;AACtB,gBAAQ,mBAAmB,SAAS,IAAI,KAAK;AAC7C,YAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AACpC,oBAAU,GAAG,GAAG,4BAA4B,KAAK;AAAA,QACnD,OAAO;AACL,oBAAU,eAAe,OAAO;AAAA,QAClC;AAAA,MACF,OAAO;AACL,gBAAQ,oBAAoB,SAAS,IAAI,KAAK;AAC9C,YAAI,CAAC,UAAU;AACb,oBAAU,GAAG,GAAG,6BAA6B,KAAK;AAAA,QACpD,OAAO;AACL,oBAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAGA,UAAM,SAAS,IAAIC,KAAI;AAAA,MACrB,QAAQ;AAAA,MACR,KAAK;AAAA,MACL,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA;AAAA,MACR,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,WAAW;AAAA,QACT,IAAI;AAAA,QACJ,OAAO,EAAE,IAAI,OAAO;AAAA,MACtB;AAAA,MACA,QAAQ,EAAE,MAAM,OAAO;AAAA,MACvB,OAAO;AAAA,MACP,OAAO;AAAA,QACL,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,QAAQ,EAAE,IAAI,OAAO;AAAA,QACrB,OAAO,EAAE,IAAI,QAAQ,MAAM,KAAK;AAAA,MAClC;AAAA,MACA,SAAS,EAAE,MAAM,GAAG,OAAO,EAAE;AAAA,MAC7B;AAAA,MACA,MAAM;AAAA;AAAA,IACR,CAAC;AAGD,UAAM,UAAU,IAAIA,KAAI;AAAA,MACtB,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS,GAAG,GAAG,KAAK,KAAK,0BAAgB,GAAG,cAAc,KAAK,WAAW,GAAG,YAAY,KAAK,WAAW,GAAG,UAAU,KAAK;AAAA,MAC3H,MAAM;AAAA,MACN,OAAO,EAAE,IAAI,SAAS,IAAI,QAAQ;AAAA,IACpC,CAAC;AAED,WAAO,MAAM;AAGb,UAAM,QAAQ,MAAM;AAClB,cAAQ,QAAQ;AAChB,aAAO,QAAQ;AACf,aAAO,OAAO;AACd,MAAAD,SAAQ;AAAA,IACV;AAGA,oBAAgB;AAEhB,WAAO,IAAI,CAAC,UAAU,GAAG,GAAG,KAAK;AAGjC,WAAO,IAAI,CAAC,QAAQ,GAAG,GAAG,MAAM;AAC9B,aAAO,gBAAgB,CAAC;AACxB,aAAO,OAAO;AAAA,IAChB,CAAC;AAED,WAAO,IAAI,CAAC,OAAO,KAAK,GAAG,MAAM;AAC/B,aAAO,gBAAgB,GAAG;AAC1B,aAAO,OAAO;AAAA,IAChB,CAAC;AAED,WAAO,OAAO;AAAA,EAChB,CAAC;AAED,SAAO,EAAE,QAAQ,OAAO,cAAc;AACxC;AAMA,SAAS,eAAe,UAAgC;AACtD,QAAM,QAAkB,CAAC;AACzB,QAAM,YAAY,SAAI,OAAO,EAAE;AAE/B,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,MAAM,SAAS,CAAC;AACtB,UAAM,YAAY,aAAa,IAAI,IAAI;AACvC,UAAM,WAAW,IAAI,KAAK,YAAY;AAGtC,UAAM,KAAK,GAAG,GAAG,GAAG,SAAS,GAAG,KAAK,EAAE;AACvC,UAAM;AAAA,MACJ,GAAG,SAAS,GAAG,IAAI,IAAI,QAAQ,IAAI,KAAK,IAAI,GAAG,WAAW,IAAI,CAAC,OAAO,SAAS,MAAM,GAAG,KAAK;AAAA,IAC/F;AACA,UAAM,KAAK,GAAG,GAAG,GAAG,SAAS,GAAG,KAAK,EAAE;AACvC,UAAM,KAAK,EAAE;AAGb,UAAM,eAAe,qBAAqB,IAAI,OAAO;AACrD,UAAM,KAAK,GAAG,YAAY;AAC1B,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAKA,SAAS,qBAAqB,SAAuC;AACnE,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO,QAAQ,MAAM,IAAI;AAAA,EAC3B;AAEA,MAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B,WAAO,CAAC,KAAK,UAAU,SAAS,MAAM,CAAC,CAAC;AAAA,EAC1C;AAEA,QAAM,QAAkB,CAAC;AAEzB,aAAW,QAAQ,SAAS;AAC1B,QAAI,OAAO,SAAS,UAAU;AAC5B,YAAM,KAAK,GAAG,KAAK,MAAM,IAAI,CAAC;AAAA,IAChC,WAAW,WAAW,IAAI,GAAG;AAC3B,YAAM,KAAK,GAAG,KAAK,KAAK,MAAM,IAAI,CAAC;AAAA,IACrC,WAAW,YAAY,IAAI,GAAG;AAC5B,YAAM,YAAY,KAAK,QAAQ,cAAc;AAC7C,YAAM,KAAK,GAAG,GAAG,WAAW,SAAS,IAAI,KAAK,EAAE;AAAA,IAClD,WAAW,YAAY,IAAI,GAAG;AAC5B,YAAM,YAAY,KAAK,QAAQ,cAAc;AAC7C,YAAM,KAAK,GAAG,GAAG,WAAW,SAAS,IAAI,KAAK,EAAE;AAAA,IAClD,WAAW,cAAc,IAAI,GAAG;AAC9B,YAAM,KAAK,GAAG,MAAM,GAAG,IAAI,cAAc,KAAK,IAAI,IAAI,KAAK,EAAE;AAC7D,YAAM,KAAK,GAAG,GAAG,OAAO,KAAK,EAAE,GAAG,KAAK,EAAE;AACzC,YAAM,KAAK,GAAG,GAAG,SAAS,KAAK,EAAE;AACjC,YAAM,WAAW,KAAK,UAAU,KAAK,OAAO,MAAM,CAAC;AACnD,YAAM,KAAK,GAAG,SAAS,MAAM,IAAI,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,IACzD,WAAW,iBAAiB,IAAI,GAAG;AACjC,YAAM,KAAK,GAAG,IAAI,GAAG,IAAI,gBAAgB,KAAK,EAAE;AAChD,YAAM,KAAK,GAAG,GAAG,gBAAgB,KAAK,WAAW,GAAG,KAAK,EAAE;AAC3D,UAAI,OAAO,KAAK,YAAY,UAAU;AACpC,cAAM,KAAK,GAAG,KAAK,QAAQ,MAAM,IAAI,CAAC;AAAA,MACxC,OAAO;AACL,cAAM,KAAK,KAAK,UAAU,KAAK,SAAS,MAAM,CAAC,CAAC;AAAA,MAClD;AAAA,IACF,OAAO;AAEL,YAAM,WAAY,KAA2B,QAAQ;AACrD,YAAM,KAAK,GAAG,GAAG,IAAI,QAAQ,IAAI,KAAK,EAAE;AACxC,YAAM,KAAK,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAAA,IAC1C;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,aAAa,MAAsB;AAC1C,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAGA,SAAS,WAAW,MAAuD;AACzE,SACE,OAAO,SAAS,YAChB,SAAS,QACR,KAA2B,SAAS,UACrC,OAAQ,KAA4B,SAAS;AAEjD;AAEA,SAAS,YACP,MAC6D;AAC7D,SACE,OAAO,SAAS,YAChB,SAAS,QACR,KAA2B,SAAS;AAEzC;AAEA,SAAS,YACP,MAC6D;AAC7D,SACE,OAAO,SAAS,YAChB,SAAS,QACR,KAA2B,SAAS;AAEzC;AAEA,SAAS,cACP,MACwE;AACxE,SACE,OAAO,SAAS,YAChB,SAAS,QACR,KAA2B,SAAS;AAEzC;AAEA,SAAS,iBACP,MACwE;AACxE,SACE,OAAO,SAAS,YAChB,SAAS,QACR,KAA2B,SAAS;AAEzC;AASA,SAAS,uBAAuB,QAAyC;AACvE,QAAM,QAAkB,CAAC;AACzB,QAAM,YAAY,SAAI,OAAO,EAAE;AAE/B,QAAM,KAAK,GAAG,GAAG,GAAG,SAAS,GAAG,KAAK,EAAE;AACvC,QAAM,KAAK,GAAG,IAAI,GAAG,IAAI,aAAa,KAAK,EAAE;AAC7C,QAAM,KAAK,GAAG,GAAG,GAAG,SAAS,GAAG,KAAK,EAAE;AACvC,QAAM,KAAK,EAAE;AAGb,QAAM,OAAO,KAAK,UAAU,QAAQ,MAAM,CAAC;AAC3C,QAAM,cAAc,cAAc,IAAI;AACtC,QAAM,KAAK,WAAW;AAEtB,SAAO,MAAM,KAAK,IAAI;AACxB;AAMA,SAAS,mBAAmB,QAAwB;AAClD,QAAM,QAAkB,CAAC;AACzB,QAAM,YAAY,SAAI,OAAO,EAAE;AAE/B,QAAM,KAAK,GAAG,GAAG,GAAG,SAAS,GAAG,KAAK,EAAE;AACvC,QAAM,KAAK,GAAG,KAAK,GAAG,IAAI,SAAS,KAAK,EAAE;AAC1C,QAAM,KAAK,GAAG,GAAG,GAAG,SAAS,GAAG,KAAK,EAAE;AACvC,QAAM,KAAK,EAAE;AAGb,QAAM,UAAU,OAAO,KAAK;AAC5B,MACG,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,KAC/C,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GAChD;AACA,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,OAAO;AACjC,YAAM,OAAO,KAAK,UAAU,QAAQ,MAAM,CAAC;AAC3C,YAAM,KAAK,cAAc,IAAI,CAAC;AAC9B,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,QAAM,KAAK,MAAM;AACjB,SAAO,MAAM,KAAK,IAAI;AACxB;AAKA,SAAS,cAAc,MAAsB;AAE3C,MAAI,SAAS,KAAK,QAAQ,eAAe,GAAG,IAAI,OAAO,KAAK,GAAG;AAE/D,WAAS,OAAO,QAAQ,gBAAgB,KAAK,KAAK,OAAO,KAAK,EAAE;AAEhE,WAAS,OAAO,QAAQ,oBAAoB,KAAK,MAAM,KAAK,KAAK,EAAE;AAEnE,WAAS,OAAO,QAAQ,wBAAwB,KAAK,OAAO,KAAK,KAAK,EAAE;AACxE,SAAO;AACT;;;ACxWA,IAAM,mBAAmB;AAQlB,IAAM,SAAN,MAAM,QAAO;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA,kBAA0C;AAAA;AAAA,EAG1C,YAAY;AAAA;AAAA,EAGZ,iBAAsC;AAAA;AAAA,EAGtC,mBAAwC;AAAA;AAAA,EAGxC,mBAAkC;AAAA;AAAA,EAGlC,mBAAmB;AAAA;AAAA,EAGnB,cAAc,oBAAI,IAAoB;AAAA;AAAA,EAGtC,qBAAqB,oBAAI,IAAoB;AAAA;AAAA,EAG7C,YAAuB;AAAA;AAAA,EAGvB,iBAAsC;AAAA,EAEtC,YACN,WACA,QACA,WACA,cACA,eACA;AACA,SAAK,YAAY;AACjB,SAAK,SAAS;AACd,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,gBAAgB;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,OAAO,SAAsC;AACxD,UAAM,YAAY,aAAa;AAAA,MAC7B,OAAO,QAAQ;AAAA,MACf,QAAQ,QAAQ;AAAA,MAChB,OAAO;AAAA,IACT,CAAC;AAED,UAAM,EAAE,OAAO,IAAI;AAGnB,UAAM,SAAS,kBAAkB,MAAM;AAGvC,UAAM,YAAY,IAAI;AAAA,MACpB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,MAAM,UAAU,cAAc;AAAA,MAC9B,MAAM,UAAU,UAAU;AAAA,IAC5B;AAIA,UAAM,eAAe,IAAI;AAAA,MACvB,OAAO;AAAA,MACP,OAAO;AAAA,MACP;AAAA,MACA,MAAM,UAAU,cAAc;AAAA,MAC9B,MAAM,UAAU,UAAU;AAAA,IAC5B;AAGA,UAAM,gBAAgB,IAAI;AAAA,MACxB,OAAO;AAAA,MACP,MAAM,UAAU,cAAc;AAAA,IAChC;AAEA,UAAM,MAAM,IAAI,QAAO,WAAW,QAAQ,WAAW,cAAc,aAAa;AAGhF,QAAI,iBAAiB,MAAM;AAG3B,iBAAa,QAAQ,MAAM,IAAI,YAAY,CAAC;AAG5C,iBAAa,QAAQ,MAAM,IAAI,gBAAgB,CAAC;AAGhD;AAAA,MACE;AAAA,MACA;AAAA,QACE,cAAc,MAAM,cAAc,WAAW;AAAA,QAC7C,kBAAkB,MAAM,cAAc,eAAe;AAAA,QACrD,gBAAgB,MAAM,cAAc,aAAa;AAAA,QACjD,YAAY,MAAM,cAAc,mBAAmB;AAAA,QACnD,eAAe,MAAM,cAAc,YAAY;AAAA,QAC/C,cAAc,MAAM;AAClB,wBAAc,WAAW;AACzB,wBAAc,iBAAiB;AAAA,QACjC;AAAA,QACA,kBAAkB,MAAM,IAAI,cAAc,SAAS;AAAA,QACnD,mBAAmB,MAAM,IAAI,cAAc,UAAU;AAAA,MACvD;AAAA,MACA,MAAM,IAAI;AAAA,IACZ;AAGA,WAAO,KAAK,GAAG,UAAU,MAAM;AAC7B,oBAAc,iBAAiB;AAAA,IACjC,CAAC;AAGD,WAAO,GAAG,UAAU,MAAM;AACxB,oBAAc,aAAa;AAAA,IAC7B,CAAC;AAGD,QAAI,eAAe;AAGnB,cAAU,cAAc;AAExB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,QAAsB;AAE7C,WAAO,IAAI,CAAC,QAAQ,GAAG,MAAM;AAC3B,UAAI,KAAK,aAAa,gBAAgB,GAAG;AAEvC;AAAA,MACF;AAGA,YAAM,WAAW,KAAK,cAAc,iBAAiB;AACrD,UAAI,UAAU,UAAU;AAEtB;AAAA,MACF;AAGA,UAAI,KAAK,kBAAkB;AACzB,aAAK,iBAAiB;AAAA,MACxB;AAGA,UAAI,KAAK,mBAAmB,CAAC,KAAK,gBAAgB,OAAO,SAAS;AAChE,aAAK,gBAAgB,MAAM;AAAA,MAC7B;AAAA,IACF,CAAC;AAGD,WAAO,IAAI,CAAC,KAAK,GAAG,MAAM;AACxB,WAAK,YAAY;AAAA,IACnB,CAAC;AAGD,WAAO,IAAI,CAAC,KAAK,GAAG,MAAM;AACxB,WAAK,gBAAgB;AAAA,IACvB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAoB;AAClB,UAAM,MAAM,KAAK,IAAI;AAErB,QAAI,MAAM,KAAK,YAAY,kBAAkB;AAE3C,UAAI,KAAK,gBAAgB;AACvB,aAAK,eAAe;AAAA,MACtB;AACA,WAAK,QAAQ;AACb,cAAQ,KAAK,GAAG;AAAA,IAClB,OAAO;AAEL,WAAK,YAAY;AACjB,WAAK,SAAS,4BAA4B;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,kBAAwB;AACtB,SAAK,YAAY,KAAK,cAAc,WAAW,UAAU;AACzD,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,MAAuB;AAClC,QAAI,KAAK,cAAc,MAAM;AAC3B,WAAK,YAAY;AACjB,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,iBAAuB;AAE7B,SAAK,UAAU,aAAa,KAAK,SAAS;AAG1C,QAAI,KAAK,cAAc,SAAS;AAE9B,WAAK,OAAO,KAAK,SAAS;AAAA,IAC5B,OAAO;AAEL,WAAK,OAAO,KAAK,SAAS;AAAA,IAC5B;AAGA,SAAK,UAAU,UAAU;AAGzB,QAAI,KAAK,cAAc,SAAS;AAC9B,WAAK,aAAa,SAAS;AAAA,IAC7B,OAAO;AACL,WAAK,aAAa,WAAW;AAAA,IAC/B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,YAAY,OAA0B;AACpC,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AAEH,aAAK,cAAc,QAAQ,MAAM,OAAO;AACxC;AAAA,MAEF,KAAK,eAAe;AAElB,YAAI,KAAK,cAAc,iBAAiB,EAAG;AAG3C,cAAM,WAAW,KAAK,cAAc;AAAA,UAClC,MAAM,KAAK;AAAA,UACX,MAAM,KAAK;AAAA,UACX,MAAM,KAAK;AAAA,QACb;AACA,aAAK,YAAY,IAAI,MAAM,KAAK,cAAc,QAAQ;AAEtD,aAAK,UAAU,YAAY,MAAM,KAAK,UAAU;AAChD;AAAA,MACF;AAAA,MAEA,KAAK;AAEH,YAAI,KAAK,cAAc,iBAAiB,EAAG;AAG3C,aAAK,cAAc;AAAA,UACjB,MAAM,OAAO;AAAA,UACb,MAAM,OAAO;AAAA,UACb,MAAM,OAAO;AAAA,UACb,MAAM,OAAO;AAAA,UACb,MAAM,OAAO;AAAA,QACf;AAEA,aAAK,UAAU,UAAU,MAAM,OAAO,UAAU;AAChD;AAAA,MAEF,KAAK;AAEH,YAAI,KAAK,cAAc,iBAAiB,EAAG;AAG3C,aAAK,oBAAoB,MAAM,aAAa;AAC5C;AAAA,MAEF,KAAK;AAEH;AAAA,MAEF,KAAK;AAEH;AAAA,MAEF;AAEE;AAAA,IACJ;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,UAA+B;AAEzD,UAAM,iBAAiB,KAAK,YAAY,IAAI,SAAS,kBAAkB;AACvE,QAAI,CAAC,eAAgB;AAErB,YAAQ,SAAS,MAAM;AAAA,MACrB,KAAK,kBAAkB;AAErB,cAAM,OAAO,SAAS;AAEtB,cAAM,MAAM,GAAG,SAAS,kBAAkB,IAAI,KAAK,SAAS;AAG5D,YAAI,KAAK,mBAAmB,IAAI,GAAG,GAAG;AACpC;AAAA,QACF;AAEA,cAAM,YAAY,KAAK,cAAc;AAAA,UACnC,KAAK,YAAY;AAAA;AAAA,UACjB,KAAK;AAAA,UACL;AAAA;AAAA,QACF;AACA,aAAK,mBAAmB,IAAI,KAAK,SAAS;AAE1C,cAAM,WAAW,IAAI,KAAK,gBAAgB,IAAI,KAAK,YAAY,CAAC;AAChE,aAAK,UAAU,aAAa,UAAU,KAAK,KAAK;AAChD;AAAA,MACF;AAAA,MAEA,KAAK,gBAAgB;AACnB,cAAM,OAAO,SAAS;AACtB,cAAM,MAAM,GAAG,SAAS,kBAAkB,IAAI,KAAK,SAAS;AAC5D,cAAM,YAAY,KAAK,mBAAmB,IAAI,GAAG;AACjD,YAAI,WAAW;AACb,eAAK,cAAc,gBAAgB,WAAW;AAAA,YAC5C,aAAa,KAAK,OAAO,eAAe,KAAK;AAAA,YAC7C,mBAAmB,KAAK,OAAO;AAAA,YAC/B,cAAc,KAAK,OAAO,gBAAgB,KAAK;AAAA,YAC/C,gBAAgB,KAAK,YAAY,KAAK,YAAY,MAAO;AAAA,YACzD,MAAM,KAAK;AAAA,YACX,cAAc,KAAK,gBAAgB;AAAA,UACrC,CAAC;AAED,gBAAM,WAAW,IAAI,KAAK,gBAAgB,IAAI,KAAK,YAAY,CAAC;AAChE,eAAK,UAAU,WAAW,QAAQ;AAElC,cAAI,KAAK,QAAQ,KAAK,OAAO,GAAG;AAC9B,iBAAK,UAAU,cAAc,KAAK,IAAI;AAAA,UACxC;AAAA,QACF;AACA;AAAA,MACF;AAAA,MAEA,KAAK,eAAe;AAElB,cAAM,cAAc,SAAS;AAC7B,YAAI,YAAY,MAAM;AAEpB,cAAI,KAAK,YAAY,IAAI,YAAY,KAAK,YAAY,GAAG;AACvD;AAAA,UACF;AAIA,cAAI,SAAS,cAAc,QAAW;AACpC,kBAAM,MAAM,GAAG,SAAS,kBAAkB,IAAI,SAAS,SAAS;AAChE,kBAAM,oBAAoB,KAAK,mBAAmB,IAAI,GAAG;AACzD,gBAAI,mBAAmB;AACrB,mBAAK,cAAc,kBAAkB,iBAAiB;AAAA,YACxD;AAAA,UACF;AAEA,gBAAM,WAAW,KAAK,cAAc;AAAA,YAClC,YAAY,KAAK;AAAA,YACjB,YAAY,KAAK;AAAA,YACjB,YAAY,KAAK;AAAA,UACnB;AACA,eAAK,YAAY,IAAI,YAAY,KAAK,cAAc,QAAQ;AAE5D,eAAK,UAAU,YAAY,YAAY,KAAK,UAAU;AAAA,QACxD;AACA;AAAA,MACF;AAAA,MAEA,KAAK,iBAAiB;AACpB,cAAM,cAAc,SAAS;AAC7B,YAAI,YAAY,QAAQ;AACtB,eAAK,cAAc;AAAA,YACjB,YAAY,OAAO;AAAA,YACnB,YAAY,OAAO;AAAA,YACnB,YAAY,OAAO;AAAA,YACnB,YAAY,OAAO;AAAA,YACnB,YAAY,OAAO;AAAA,UACrB;AAEA,cAAI,YAAY,OAAO,YAAY;AACjC,iBAAK,UAAU,UAAU,YAAY,OAAO,UAAU;AAAA,UACxD;AAEA,cAAI,YAAY,OAAO,QAAQ,YAAY,OAAO,OAAO,GAAG;AAC1D,iBAAK,UAAU,cAAc,YAAY,OAAO,IAAI;AAAA,UACtD;AAAA,QACF;AACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,iBAAiB,WAAmB,QAAgB,wBAAwB,GAAS;AAGnF,SAAK,mBAAmB;AACxB,SAAK,mBAAmB,KAAK,cAAc,oBAAoB;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB,uBAAqC;AACzD,SAAK,UAAU,gBAAgB,qBAAqB;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,MAA2D;AAG7E,QAAI,KAAK,cAAc,iBAAiB,EAAG;AAE3C,QAAI,KAAK,oBAAoB,KAAK,aAAa;AAC7C,WAAK,cAAc,mBAAmB,KAAK,kBAAkB,KAAK,WAAW;AAAA,IAC/E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,kBAAkB,UAA8B;AAG9C,QAAI,KAAK,cAAc,iBAAiB,EAAG;AAE3C,QAAI,KAAK,kBAAkB;AACzB,WAAK,cAAc,kBAAkB,KAAK,kBAAkB,QAAQ;AAAA,IACtE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,cAAc,MAAoC;AACtD,QAAI,KAAK,cAAc,SAAU;AAEjC,UAAM,WAAW,KAAK,cAAc,iBAAiB;AACrD,QAAI,CAAC,SAAU;AAGf,QAAI,KAAK,gBAAgB;AACvB,WAAK,eAAe;AACpB,WAAK,iBAAiB;AAAA,IACxB;AAEA,QAAI;AAEJ,QAAI,SAAS,KAAK,SAAS,YAAY;AAErC,YAAM,OAAO,SAAS;AACtB,eAAS,cAAc;AAAA,QACrB,QAAQ,KAAK,UAAU;AAAA,QACvB;AAAA,QACA,SAAS,KAAK;AAAA,QACd,UAAU,KAAK;AAAA,QACf,WAAW,KAAK;AAAA,QAChB,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH,WAAW,SAAS,KAAK,SAAS,UAAU;AAE1C,YAAM,OAAO,SAAS;AACtB,eAAS,cAAc;AAAA,QACrB,QAAQ,KAAK,UAAU;AAAA,QACvB;AAAA,QACA,YAAY,KAAK;AAAA,QACjB,YAAY,KAAK;AAAA,QACjB,QAAQ,KAAK;AAAA,QACb,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH,OAAO;AAEL;AAAA,IACF;AAGA,SAAK,iBAAiB,OAAO;AAG7B,UAAM,OAAO;AACb,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAAa,UAAkB,YAAqC;AAExE,UAAM,eAAe,KAAK;AAC1B,SAAK,aAAa,OAAO;AAEzB,QAAI;AACF,YAAM,SAAS,MAAM,KAAK,aAAa,aAAa,UAAU,UAAU;AACxE,aAAO;AAAA,IACT,UAAE;AAEA,WAAK,aAAa,YAAY;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,gBAAiC;AAGrC,UAAM,SAAS,MAAM,KAAK,aAAa,cAAc;AAErD,SAAK,aAAa,QAAQ;AAC1B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,SAAqD;AACtE,WAAO,mBAAmB,KAAK,UAAU,QAAQ,OAAO;AAAA,EAC1D;AAAA;AAAA;AAAA;AAAA,EAKA,cAAc,MAAoB;AAChC,SAAK,UAAU,cAAc,IAAI;AAAA,EACnC;AAAA;AAAA,EAGQ,kBAAuC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4B/C,gBAAgB,MAAiC;AAE/C,QAAI,KAAK,iBAAiB;AACxB,WAAK,gBAAgB;AAAA,IACvB;AAGA,UAAM,aAAa,KAAK,cAAc,gBAAgB,IAAI;AAG1D,UAAM,cAAc,KAAK,UAAU,gBAAgB,IAAI;AAGvD,SAAK,kBAAkB,MAAM;AAC3B,iBAAW;AACX,kBAAY;AAAA,IACd;AAEA,WAAO,MAAM;AACX,UAAI,KAAK,iBAAiB;AACxB,aAAK,gBAAgB;AACrB,aAAK,kBAAkB;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,iBAA8B;AAC5B,QAAI,CAAC,KAAK,iBAAiB;AACzB,WAAK,kBAAkB,IAAI,gBAAgB;AAAA,IAC7C;AACA,WAAO,KAAK,gBAAgB;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAmB;AACjB,SAAK,kBAAkB,IAAI,gBAAgB;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK,iBAAiB,OAAO,WAAW;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,UAA4B;AACjC,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,UAA4B;AACnC,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKQ,SAAS,SAAuB;AACtC,SAAK,cAAc,QAAQ;AAAA,GAAM,OAAO;AAAA,CAAK;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa;AACX,WAAO,KAAK,UAAU,WAAW;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA,EAKA,oBAA4B;AAC1B,WAAO,KAAK,UAAU,kBAAkB;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,YAAkB;AAGhB,SAAK,UAAU,cAAc;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AAEd,QAAI,KAAK,iBAAiB;AACxB,WAAK,gBAAgB;AACrB,WAAK,kBAAkB;AAAA,IACzB;AAGA,SAAK,aAAa,cAAc;AAGhC,SAAK,UAAU,QAAQ;AAAA,EACzB;AACF;;;A1BvtBA,eAAsB,aACpB,WACA,SACA,KACe;AACf,QAAM,SAAS,IAAI,aAAa;AAGhC,QAAM,qBAAqB,cAAc,IAAI,KAAK;AAClD,QAAM,YAAa,IAAI,OAA8B,UAAU;AAC/D,QAAM,SAAS,sBAAsB,aAAa,CAAC,QAAQ;AAG3D,MAAI;AACJ,MAAI,QAAQ;AAEV,aAAS,aAAa;AAAA,EACxB,OAAO;AAEL,aAAS,MAAM,cAAc,WAAW,GAAG;AAAA,EAC7C;AAGA,QAAM,WAAW,IAAI,eAAe;AAIpC,MAAI,QAAQ,aAAa,OAAO;AAC9B,eAAW,UAAU,gBAAgB;AAInC,UACE,OAAO,SAAS,cACf,QAAQ,uBAAuB,SAAS,CAAC,qBAC1C;AACA;AAAA,MACF;AACA,eAAS,gBAAgB,MAAM;AAAA,IACjC;AAAA,EACF;AAGA,QAAM,mBAAmB,QAAQ,UAAU,CAAC;AAC5C,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAME,WAAU,MAAM,YAAY,kBAAkB,QAAQ,IAAI,CAAC;AACjE,eAAW,UAAUA,UAAS;AAC5B,eAAS,gBAAgB,MAAM;AAAA,IACjC;AAAA,EACF;AAGA,MAAI,MAAqB;AACzB,MAAI,QAAQ;AACV,UAAM,MAAM,OAAO,OAAO;AAAA,MACxB,OAAO,QAAQ;AAAA,MACf,OAAO,IAAI;AAAA,MACX,QAAQ,IAAI;AAAA,IACd,CAAC;AAAA,EACH;AAGA,QAAM,kBAAkB,IAAI,gBAAgB;AAC5C,MAAI,eAAe;AAGnB,QAAM,aAAa,MAAM;AACvB,QAAI,KAAK;AACP,UAAI,QAAQ;AAAA,IACd;AACA,YAAQ,KAAK,GAAG;AAAA,EAClB;AAGA,MAAI,KAAK;AACP,QAAI,OAAO,UAAU;AACrB,QAAI,SAAS,MAAM;AACjB,qBAAe;AACf,sBAAgB,MAAM;AAAA,IACxB,CAAC;AAAA,EACH;AAGA,MAAI,CAAC,QAAQ;AACX,YAAQ,KAAK,UAAU,MAAM,QAAQ,KAAK,GAAG,CAAC;AAAA,EAChD;AAIA,QAAM,4BAA4B,CAAC,cAAc,aAAa,UAAU;AACxE,QAAM,gBAAgB,QAAQ,kBAAkB,CAAC;AAGjD,QAAM,kBAGF;AAAA,IACF,GAAG;AAAA,EACL;AACA,aAAW,UAAU,2BAA2B;AAC9C,UAAM,mBAAmB,OAAO,YAAY;AAC5C,UAAM,eAAe,OAAO,KAAK,aAAa,EAAE;AAAA,MAC9C,CAAC,QAAQ,IAAI,YAAY,MAAM;AAAA,IACjC;AACA,QAAI,CAAC,cAAc;AACjB,sBAAgB,MAAM,IAAI;AAAA,IAC5B;AAAA,EACF;AAEA,QAAM,iBAAiC;AAAA,IACrC;AAAA,IACA,aAAa;AAAA,EACf;AAKA,MAAI;AACJ,MAAI,aAAa;AAGjB,QAAM,iBAAiB,cAAc,QAAQ,gBAAgB,UAAU;AACvE,MAAI;AACJ,MAAI,iBAAiB;AAGrB,QAAM,sBAAsB,OAC1B,OACA,aACoB;AACpB,QAAI;AACF,aAAO,MAAM,OAAO,YAAY,OAAO,QAAQ;AAAA,IACjD,QAAQ;AAEN,YAAM,aAAa,SAAS;AAAA,QAC1B,CAAC,KAAK,MAAM,OAAO,EAAE,SAAS,UAAU;AAAA,QACxC;AAAA,MACF;AACA,aAAO,KAAK,MAAM,aAAa,wBAAwB;AAAA,IACzD;AAAA,EACF;AAGA,QAAM,0BAA0B,OAC9B,WACgC;AAChC,QAAI,CAAC,OAAQ,QAAO;AACpB,QAAI;AAEF,YAAM,WAAyB,CAAC,EAAE,MAAM,aAAa,SAAS,OAAO,CAAC;AACtE,aAAO,MAAM,OAAO,YAAY,QAAQ,OAAO,QAAQ;AAAA,IACzD,QAAQ;AAEN,aAAO;AAAA,IACT;AAAA,EACF;AAcA,QAAM,yBAAyB;AAAA,IAC7B,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAEA,QAAM,UAAU,IAAI,aAAa,MAAM,EACpC,UAAU,QAAQ,KAAK,EACvB,mBAAmB,sBAAsB,EACzC,WAAW,IAAI,aAAa,kBAAkB,CAAC,EAC/C,UAAU;AAAA,IACT,WAAW;AAAA;AAAA,MAET,gBAAgB,OAAO,YAAY;AACjC,YAAI,QAAQ,gBAAiB;AAC7B;AAEA,YAAI,KAAK;AAEP,gBAAM,iBAAiB,MAAM;AAAA,YAC3B,QAAQ,QAAQ;AAAA,YAChB,QAAQ,QAAQ;AAAA,UAClB;AACA,cAAI,iBAAiB,aAAa,GAAG,QAAQ,QAAQ,OAAO,cAAc;AAAA,QAC5E;AAAA,MACF;AAAA;AAAA,MAGA,gBAAgB,OAAO,YAAY;AACjC,YAAI,QAAQ,gBAAiB;AAG7B,YAAI,KAAK;AACP,cAAI,kBAAkB,QAAQ,QAAQ,QAAQ;AAAA,QAChD;AAEA,YAAI,gBAAgB;AAClB,cAAI,CAAC,eAAe;AAClB,4BAAgB,MAAM,iBAAiB,cAAc;AAAA,UACvD;AACA,cAAI,eAAe;AACjB,kBAAM,WAAW,GAAG,iBAAiB,cAAc,CAAC;AACpD,kBAAM,UAAU,iBAAiB,QAAQ,QAAQ,QAAQ;AACzD,kBAAM,aAAa,eAAe,UAAU,OAAO;AAAA,UACrD;AAAA,QACF;AAAA,MACF;AAAA;AAAA,MAGA,eAAe,OAAO,YAAY;AAChC,YAAI,QAAQ,gBAAiB;AAC7B,YAAI,CAAC,IAAK;AAGV,cAAM,wBAAwB,UAAU,eAAe,QAAQ,eAAe;AAC9E,YAAI,sBAAsB,qBAAqB;AAAA,MACjD;AAAA;AAAA,MAGA,mBAAmB,OAAO,YAAY;AACpC,YAAI,QAAQ,gBAAiB;AAG7B,gBAAQ,QAAQ;AAChB,qBAAa,KAAK,IAAI,YAAY,QAAQ,YAAY,CAAC;AAGvD,YAAI;AACJ,YAAI,QAAQ,SAAS,OAAO,eAAe;AACzC,cAAI;AACF,kBAAM,YAAY,QAAQ,QAAQ,MAAM,SAAS,GAAG,IAChD,QAAQ,QAAQ,MAAM,MAAM,GAAG,EAAE,CAAC,IAClC,QAAQ,QAAQ;AACpB,kBAAM,aAAa,OAAO,cAAc;AAAA,cACtC;AAAA,cACA,QAAQ,MAAM;AAAA,cACd,QAAQ,MAAM;AAAA,cACd,QAAQ,MAAM,qBAAqB;AAAA,cACnC,QAAQ,MAAM,4BAA4B;AAAA,YAC5C;AACA,gBAAI,WAAY,YAAW,WAAW;AAAA,UACxC,QAAQ;AAAA,UAER;AAAA,QACF;AAEA,YAAI,KAAK;AACP,cAAI,oBAAoB;AAAA,YACtB,WAAW,QAAQ,YAAY;AAAA,YAC/B,OAAO,QAAQ,QAAQ;AAAA,YACvB,aAAa,QAAQ,OAAO;AAAA,YAC5B,cAAc,QAAQ,OAAO;AAAA,YAC7B,mBAAmB,QAAQ,OAAO;AAAA,YAClC,gBAAgB,IAAI,kBAAkB;AAAA,YACtC,MAAM;AAAA,YACN,cAAc,QAAQ,gBAAgB;AAAA,YACtC,aAAa,QAAQ;AAAA,UACvB,CAAC;AAAA,QACH;AAGA,YAAI,eAAe;AACjB,gBAAM,WAAW,GAAG,iBAAiB,cAAc,CAAC;AACpD,gBAAM,aAAa,eAAe,UAAU,QAAQ,WAAW;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAYA,aAAa;AAAA,MACX,uBAAuB,OAAO,QAAQ;AAEpC,cAAM,uBAAuB,IAAI,WAAW,YAAY;AACxD,cAAM,iBAAiB,OAAO,QAAQ,eAAe,EAAE;AAAA,UACrD,CAAC,CAAC,GAAG,MAAM,IAAI,YAAY,MAAM;AAAA,QACnC,IAAI,CAAC;AACL,cAAM,OAAO,kBAAkB,eAAe;AAG9C,YAAI,SAAS,WAAW;AACtB,iBAAO,EAAE,QAAQ,UAAU;AAAA,QAC7B;AAGA,cAAM,WAAW,cAAc,IAAI,KAAK;AACxC,cAAM,YAAa,IAAI,OAA8B,UAAU;AAC/D,cAAM,YAAY,YAAY;AAG9B,YAAI,CAAC,WAAW;AACd,cAAI,SAAS,qBAAqB;AAChC,mBAAO;AAAA,cACL,QAAQ;AAAA,cACR,iBAAiB;AAAA;AAAA,EAAoB,IAAI,UAAU;AAAA,YACrD;AAAA,UACF;AACA,cAAI,SAAS,UAAU;AACrB,mBAAO;AAAA,cACL,QAAQ;AAAA,cACR,iBAAiB;AAAA;AAAA,EAAoB,IAAI,UAAU;AAAA,YACrD;AAAA,UACF;AACA,iBAAO,EAAE,QAAQ,UAAU;AAAA,QAC7B;AAGA,YAAI,KAAK;AACP,gBAAM,WAAW,MAAM,IAAI,aAAa;AAAA,YACtC,YAAY,IAAI;AAAA,YAChB,YAAY,IAAI;AAAA,UAClB,CAAC;AAED,cAAI,aAAa,SAAS,aAAa,UAAU;AAE/C,mBAAO,EAAE,QAAQ,UAAU;AAAA,UAC7B;AACA,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,iBAAiB;AAAA;AAAA;AAAA,UACnB;AAAA,QACF;AAGA,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,iBAAiB;AAAA;AAAA,EAAoB,IAAI,UAAU;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAGH,MAAI,QAAQ,QAAQ;AAClB,YAAQ,WAAW,QAAQ,MAAM;AAAA,EACnC;AACA,MAAI,QAAQ,kBAAkB,QAAW;AACvC,YAAQ,kBAAkB,QAAQ,aAAa;AAAA,EACjD;AACA,MAAI,QAAQ,gBAAgB,QAAW;AACrC,YAAQ,gBAAgB,QAAQ,WAAW;AAAA,EAC7C;AAIA,MAAI,KAAK;AACP,YAAQ,aAAa,OAAO,aAAqB;AAC/C,aAAO,IAAI,aAAa,UAAU,SAAS;AAAA,IAC7C,CAAC;AAAA,EACH;AAGA,UAAQ,WAAW,gBAAgB,MAAM;AAGzC,QAAM,UAAU,SAAS,OAAO;AAChC,MAAI,QAAQ,SAAS,GAAG;AACtB,YAAQ,YAAY,GAAG,OAAO;AAAA,EAChC;AAGA,MAAI,QAAQ,mBAAmB;AAC7B,YAAQ,sBAAsB,QAAQ,iBAAiB;AAAA,EACzD;AACA,MAAI,QAAQ,iBAAiB;AAC3B,YAAQ,oBAAoB,QAAQ,eAAe;AAAA,EACrD;AACA,MAAI,QAAQ,iBAAiB;AAC3B,YAAQ,oBAAoB,QAAQ,eAAe;AAAA,EACrD;AAKA,UAAQ;AAAA,IACN;AAAA,IACA;AAAA,MACE,SACE;AAAA,MACF,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAIA,UAAQ,oBAAoB,aAAa;AAIzC,UAAQ,2BAA2B;AAAA,IACjC,YAAY;AAAA,IACZ,kBAAkB,CAACC,WAAU,EAAE,SAASA,OAAM,MAAM,OAAO,MAAM,OAAO;AAAA,IACxE,eAAe,CAACA,UAAS,iBAAOA,KAAI;AAAA,EACtC,CAAC;AAID,UAAQ;AAAA,IAAoB,CAAC,QAC3B;AAAA,MACE,cAAc,IAAI,YAAY,CAAC,IAAI,IAAI,aAAa;AAAA,MACpD;AAAA,IACF,EAAE,KAAK,GAAG;AAAA,EACZ;AAGA,QAAM,qBAAqB,OAAO,eAAuB;AAEvD,QAAI,KAAK;AACP,UAAI,WAAW;AACf,cAAQ,WAAW,IAAI,eAAe,CAAC;AAAA,IACzC;AAGA,QAAI;AACJ,QAAI,QAAQ,SAAS,QAAQ,OAAO;AAClC,YAAM,QAAuB,CAAC,KAAK,UAAU,CAAC;AAC9C,UAAI,QAAQ,OAAO;AACjB,cAAM,KAAK,MAAM,cAAc,QAAQ,KAAK,CAAC;AAAA,MAC/C;AACA,UAAI,QAAQ,OAAO;AACjB,cAAM,KAAK,MAAM,cAAc,QAAQ,KAAK,CAAC;AAAA,MAC/C;AACA,cAAQ,QAAQ,eAAe,KAAK;AAAA,IACtC,OAAO;AACL,cAAQ,QAAQ,IAAI,UAAU;AAAA,IAChC;AAIA,QAAI;AACJ,QAAI,KAAK;AACP,wBAAkB,IAAI,gBAAgB,MAAM,QAAQ,CAAC;AAAA,IACvD;AAGA,qBAAiB,SAAS,MAAM,IAAI,GAAG;AACrC,UAAI,KAAK;AAEP,YAAI,YAAY,KAAK;AAGrB,YAAI,MAAM,SAAS,mBAAmB,MAAM,OAAO,MAAM;AACvD,cAAI,cAAc,MAAM,OAAO,IAAI;AAAA,QACrC;AAAA,MACF,OAAO;AAEL,YAAI,MAAM,SAAS,QAAQ;AACzB,cAAI,OAAO,MAAM,MAAM,OAAO;AAAA,QAChC,WACE,MAAM,SAAS,mBACf,MAAM,OAAO,eAAe,cAC5B,MAAM,OAAO,QACb;AAEA,cAAI,OAAO,MAAM,GAAG,MAAM,OAAO,MAAM;AAAA,CAAI;AAAA,QAC7C;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK;AACP,UAAI,UAAU;AAAA,IAChB;AAGA,QAAI,iBAAiB;AACnB,sBAAgB;AAAA,IAClB;AAAA,EACF;AAIA,MAAI,KAAK;AAEP,QAAI,gBAAgB;AACpB,QAAI,CAAC,eAAe;AAClB,sBAAgB,MAAM,IAAI,cAAc;AAAA,IAC1C;AAGA,WAAO,MAAM;AACX,UAAI;AACF,cAAM,mBAAmB,aAAa;AAAA,MACxC,SAAS,OAAO;AAEd,YAAI,CAAC,aAAa,KAAK,GAAG;AACxB,gBAAM;AAAA,QACR;AAAA,MACF;AAGA,sBAAgB,MAAM,IAAI,cAAc;AAAA,IAC1C;AAAA,EACF,OAAO;AAEL,QAAI;AACF,YAAM,mBAAmB,MAAM;AAAA,IACjC,SAAS,OAAO;AACd,UAAI,CAAC,aAAa,KAAK,GAAG;AACxB,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAUO,SAAS,qBACd,SACA,KACA,QACA,iBACM;AACN,QAAM,MAAM,QACT,QAAQ,SAAS,KAAK,EACtB,YAAY,kDAAkD,EAC9D;AAAA,IACC;AAAA,IACA;AAAA,EACF;AAEF,kBAAgB,KAAK,MAAM;AAE3B,MAAI;AAAA,IAAO,CAAC,QAAQ,YAClB,cAAc,MAAM;AAElB,YAAM,gBAAiC;AAAA,QACrC,GAAI;AAAA,QACJ,gBAAgB,SAAS,iBAAiB;AAAA,QAC1C,WAAW,QAAQ;AAAA,QACnB;AAAA,MACF;AACA,aAAO,aAAa,QAAQ,eAAe,GAAG;AAAA,IAChD,GAAG,GAAG;AAAA,EACR;AACF;;;A2BhmBA;AACA;AACA;AAEA;AAuBA,eAAsB,gBACpB,WACA,SACA,KACe;AACf,QAAM,SAAS,MAAM,cAAc,WAAW,GAAG;AACjD,QAAM,SAAS,IAAI,aAAa;AAChC,QAAM,QAAQ,aAAa,QAAQ,KAAK;AAExC,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,QAAQ,QAAQ;AAClB,YAAQ,UAAU,QAAQ,MAAM;AAAA,EAClC;AAGA,MAAI,QAAQ,SAAS,QAAQ,OAAO;AAClC,UAAM,QAAuB,CAAC,KAAK,MAAM,CAAC;AAE1C,QAAI,QAAQ,OAAO;AACjB,YAAM,KAAK,MAAM,cAAc,QAAQ,KAAK,CAAC;AAAA,IAC/C;AACA,QAAI,QAAQ,OAAO;AACjB,YAAM,KAAK,MAAM,cAAc,QAAQ,KAAK,CAAC;AAAA,IAC/C;AAEA,YAAQ,kBAAkB,KAAK;AAAA,EACjC,OAAO;AACL,YAAQ,QAAQ,MAAM;AAAA,EACxB;AAEA,QAAM,WAAW,QAAQ,MAAM;AAG/B,QAAM,iBAAiB,cAAc,QAAQ,gBAAgB,UAAU;AACvE,MAAI;AAGJ,MAAI,gBAAgB;AAClB,oBAAgB,MAAM,iBAAiB,cAAc;AACrD,QAAI,eAAe;AACjB,YAAM,WAAW;AACjB,YAAM,UAAU,iBAAiB,QAAQ;AACzC,YAAM,aAAa,eAAe,UAAU,OAAO;AAAA,IACrD;AAAA,EACF;AAEA,QAAM,SAAS,OAAO,OAAO;AAAA,IAC3B;AAAA,IACA;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB,WAAW,QAAQ;AAAA,EACrB,CAAC;AAED,QAAM,UAAU,IAAI,cAAc,IAAI,MAAM;AAC5C,QAAM,YAAa,IAAI,OAA8B,UAAU;AAC/D,QAAM,WAAW,IAAI,eAAe,IAAI,QAAQ,WAAW,OAAO,aAAa;AAG/E,QAAM,uBAAuB,KAAK,MAAM,OAAO,SAAS,wBAAwB;AAChF,WAAS,UAAU,OAAO,oBAAoB;AAE9C,MAAI;AACJ,MAAI;AACJ,MAAI,sBAAsB;AAE1B,mBAAiB,SAAS,QAAQ;AAEhC,QAAI,MAAM,OAAO;AACf,cAAQ,MAAM;AACd,UAAI,MAAM,MAAM,aAAa;AAC3B,iBAAS,eAAe,MAAM,MAAM,aAAa,KAAK;AAAA,MACxD;AACA,UAAI,MAAM,MAAM,cAAc;AAC5B,iBAAS,gBAAgB,MAAM,MAAM,cAAc,KAAK;AAAA,MAC1D;AAAA,IACF;AACA,QAAI,MAAM,MAAM;AACd,eAAS,MAAM;AACf,6BAAuB,MAAM;AAC7B,eAAS,OAAO,oBAAoB,MAAM;AAC1C,cAAQ,MAAM,MAAM,IAAI;AAAA,IAC1B;AACA,QAAI,MAAM,iBAAiB,QAAW;AACpC,qBAAe,MAAM;AAAA,IACvB;AAAA,EACF;AAEA,WAAS,QAAQ,KAAK;AACtB,WAAS,SAAS;AAClB,UAAQ,cAAc;AAGtB,MAAI,eAAe;AACjB,UAAM,WAAW;AACjB,UAAM,aAAa,eAAe,UAAU,mBAAmB;AAAA,EACjE;AAGA,MAAI,aAAa,CAAC,QAAQ,OAAO;AAC/B,UAAM,UAAU,cAAc,EAAE,cAAc,OAAO,MAAM,SAAS,aAAa,EAAE,CAAC;AACpF,QAAI,SAAS;AACX,UAAI,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AAAA,IACjC;AAAA,EACF;AACF;AAUO,SAAS,wBACd,SACA,KACA,QACM;AACN,QAAM,MAAM,QACT,QAAQ,SAAS,QAAQ,EACzB,YAAY,oDAAoD,EAChE,SAAS,YAAY,sEAAsE;AAE9F,qBAAmB,KAAK,MAAM;AAE9B,MAAI;AAAA,IAAO,CAAC,QAAQ,YAClB,cAAc,MAAM,gBAAgB,QAAQ,SAA+B,GAAG,GAAG,GAAG;AAAA,EACtF;AACF;;;AC9JA,SAAS,cAAAC,aAAY,WAAW,qBAAqB;AACrD,SAAS,eAAe;;;ACFxB,SAAS,YAAY,oBAAoB;AACzC,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,aAAY;AACrB,SAAS,QAAQ,iBAAiB;;;ACHlC,SAAS,WAAW;AAab,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YACE,SACgB,YACA,YAChB;AACA,UAAM,aAAa,YAAY,UAAU,MAAM,OAAO,KAAK,OAAO;AAHlD;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAWO,SAAS,qBAAqB,SAAwB,YAA0B;AACrF,QAAM,MAAM,IAAI,IAAI;AAAA,IAClB,OAAO;AAAA;AAAA,IACP,YAAY;AAAA;AAAA,IACZ,UAAU;AAAA;AAAA,EACZ,CAAC;AAID,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,OAAO,GAAG;AACtD,QAAI;AACF,UAAI,aAAa,IAAI,IAAI,IAAI,QAAQ;AAAA,IACvC,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QACrD;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAYO,SAAS,gBACd,KACA,UACA,UAAmC,CAAC,GACpC,YACQ;AACR,MAAI;AAEF,UAAM,cAAc;AAAA,MAClB,GAAG;AAAA,MACH,KAAK,QAAQ;AAAA,MACb,OAAM,oBAAI,KAAK,GAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA;AAAA,IAC7C;AACA,WAAO,IAAI,aAAa,UAAU,WAAW;AAAA,EAC/C,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MACrD;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAUO,SAAS,gBAAgB,SAAwB,YAA2B;AAEjF,QAAM,MAAM,qBAAqB,SAAS,UAAU;AAGpD,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,OAAO,GAAG;AACtD,QAAI;AAGF,UAAI,aAAa,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC;AAAA,IACxC,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,QACrD;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAUO,SAAS,gBAAgB,UAAkB,YAAqB,YAA2B;AAEhG,QAAM,gBAAgB;AACtB,QAAM,UAAU,SAAS,SAAS,aAAa;AAE/C,aAAW,SAAS,SAAS;AAC3B,UAAM,UAAU,MAAM,CAAC;AACvB,QAAI,QAAQ,IAAI,OAAO,MAAM,QAAW;AACtC,YAAM,IAAI;AAAA,QACR,yBAAyB,OAAO;AAAA,QAChC;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AASO,SAAS,kBAAkB,KAAsB;AACtD,SAAO,IAAI,SAAS,IAAI;AAC1B;;;ADjHA,IAAM,0BAAmD,CAAC,WAAW,UAAU,mBAAmB;AA+HlG,IAAM,qBAAqB,oBAAI,IAAI,CAAC,aAAa,YAAY,WAAW,CAAC;AAGzE,IAAM,mBAA+B,CAAC,SAAS,SAAS,SAAS,QAAQ,QAAQ,SAAS,OAAO;AAGjG,IAAM,uBAAuB,oBAAI,IAAI;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AACF,CAAC;AAGD,IAAM,oBAAoB,oBAAI,IAAI;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AACF,CAAC;AAGD,IAAM,oBAAoB,oBAAI,IAAI,CAAC,SAAS,QAAQ,WAAW,SAAS,UAAU,OAAO,CAAC;AAG1F,IAAM,qBAAqB,oBAAI,IAAI,CAAC,SAAS,SAAS,UAAU,SAAS,UAAU,OAAO,CAAC;AAG3F,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACjC,GAAG;AAAA,EACH,GAAG;AAAA,EACH;AAAA,EACA;AACF,CAAC;AAKM,SAAS,gBAAwB;AACtC,SAAOC,MAAKC,SAAQ,GAAG,WAAW,UAAU;AAC9C;AAKO,IAAM,cAAN,cAA0B,MAAM;AAAA,EACrC,YACE,SACgBC,OAChB;AACA,UAAMA,QAAO,GAAGA,KAAI,KAAK,OAAO,KAAK,OAAO;AAF5B,gBAAAA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AAKA,SAAS,eAAe,OAAgB,KAAa,SAAyB;AAC5E,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,mBAAmB;AAAA,EAC9D;AACA,SAAO;AACT;AAKA,SAAS,eACP,OACA,KACA,SACA,MACQ;AACR,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,mBAAmB;AAAA,EAC9D;AACA,MAAI,MAAM,WAAW,CAAC,OAAO,UAAU,KAAK,GAAG;AAC7C,UAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,qBAAqB;AAAA,EAChE;AACA,MAAI,MAAM,QAAQ,UAAa,QAAQ,KAAK,KAAK;AAC/C,UAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,eAAe,KAAK,GAAG,EAAE;AAAA,EACpE;AACA,MAAI,MAAM,QAAQ,UAAa,QAAQ,KAAK,KAAK;AAC/C,UAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,eAAe,KAAK,GAAG,EAAE;AAAA,EACpE;AACA,SAAO;AACT;AAKA,SAAS,gBAAgB,OAAgB,KAAa,SAA0B;AAC9E,MAAI,OAAO,UAAU,WAAW;AAC9B,UAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,oBAAoB;AAAA,EAC/D;AACA,SAAO;AACT;AAKA,SAAS,oBAAoB,OAAgB,KAAa,SAA2B;AACnF,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,UAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,mBAAmB;AAAA,EAC9D;AACA,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI,OAAO,MAAM,CAAC,MAAM,UAAU;AAChC,YAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,IAAI,CAAC,oBAAoB;AAAA,IACpE;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,iBAAiB,OAAgB,SAAoC;AAC5E,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAI,OAAO,MAAM,CAAC,MAAM,UAAU;AAChC,cAAM,IAAI,YAAY,IAAI,OAAO,cAAc,CAAC,oBAAoB;AAAA,MACtE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,QAAM,IAAI,YAAY,IAAI,OAAO,iDAAiD;AACpF;AAMA,SAAS,6BACP,OACA,cACA,SACgB;AAChB,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACvE,UAAM,IAAI;AAAA,MACR,IAAI,OAAO,KAAK,YAAY;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,SAAyB,CAAC;AAChC,QAAM,SAAS;AAEf,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC/C,QAAI,QAAQ,SAAS;AACnB,UAAI,OAAO,QAAQ,UAAU;AAC3B,cAAM,IAAI,YAAY,IAAI,OAAO,KAAK,YAAY,yBAAyB;AAAA,MAC7E;AACA,aAAO,QAAQ;AAAA,IACjB,WAAW,QAAQ,iBAAiB;AAClC,UAAI,OAAO,QAAQ,YAAY,CAAC,OAAO,UAAU,GAAG,KAAK,MAAM,GAAG;AAChE,cAAM,IAAI;AAAA,UACR,IAAI,OAAO,KAAK,YAAY;AAAA,QAC9B;AAAA,MACF;AACA,aAAO,gBAAgB;AAAA,IACzB,OAAO;AAEL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,0BAA0B,OAAgB,SAAoC;AACrF,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACvE,UAAM,IAAI;AAAA,MACR,IAAI,OAAO;AAAA,IACb;AAAA,EACF;AAEA,QAAM,SAA4B,CAAC;AACnC,aAAW,CAAC,cAAc,MAAM,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACrF,WAAO,YAAY,IAAI,6BAA6B,QAAQ,cAAc,GAAG,OAAO,YAAY;AAAA,EAClG;AACA,SAAO;AACT;AAMA,SAAS,6BAA6B,OAAgB,SAAuC;AAC3F,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACvE,UAAM,IAAI,YAAY,IAAI,OAAO,mBAAmB;AAAA,EACtD;AAEA,QAAM,SAA+B,CAAC;AACtC,QAAM,SAAS;AAEf,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC/C,QAAI,QAAQ,iBAAiB;AAC3B,UAAI,OAAO,QAAQ,UAAU;AAC3B,cAAM,IAAI,YAAY,IAAI,OAAO,kCAAkC;AAAA,MACrE;AACA,aAAO,eAAe,IAAI;AAAA,IAC5B,OAAO;AAEL,aAAO,GAAG,IAAI,6BAA6B,KAAK,KAAK,OAAO;AAAA,IAC9D;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,uBAAuB,OAAgB,SAAyC;AACvF,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACvE,UAAM,IAAI;AAAA,MACR,IAAI,OAAO;AAAA,IACb;AAAA,EACF;AAEA,QAAM,SAAiC,CAAC;AACxC,aAAW,CAAC,YAAY,IAAI,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACjF,QAAI,OAAO,SAAS,UAAU;AAC5B,YAAM,IAAI,YAAY,IAAI,OAAO,qBAAqB,UAAU,mBAAmB;AAAA,IACrF;AACA,QAAI,CAAC,wBAAwB,SAAS,IAA6B,GAAG;AACpE,YAAM,IAAI;AAAA,QACR,IAAI,OAAO,qBAAqB,UAAU,oBAAoB,wBAAwB,KAAK,IAAI,CAAC;AAAA,MAClG;AAAA,IACF;AACA,WAAO,UAAU,IAAI;AAAA,EACvB;AACA,SAAO;AACT;AAKA,SAAS,sBACP,KACA,SACwE;AACxE,QAAM,SAAiF,CAAC;AAExF,MAAI,eAAe,KAAK;AACtB,UAAM,QAAQ,eAAe,IAAI,WAAW,GAAG,aAAa,OAAO;AACnE,QAAI,CAAC,iBAAiB,SAAS,KAAiB,GAAG;AACjD,YAAM,IAAI;AAAA,QACR,IAAI,OAAO,+BAA+B,iBAAiB,KAAK,IAAI,CAAC;AAAA,MACvE;AAAA,IACF;AACA,WAAO,WAAW,IAAI;AAAA,EACxB;AACA,MAAI,cAAc,KAAK;AACrB,WAAO,UAAU,IAAI,eAAe,IAAI,UAAU,GAAG,YAAY,OAAO;AAAA,EAC1E;AACA,MAAI,eAAe,KAAK;AACtB,WAAO,WAAW,IAAI,gBAAgB,IAAI,WAAW,GAAG,aAAa,OAAO;AAAA,EAC9E;AAEA,SAAO;AACT;AAKA,SAAS,mBACP,KACA,SAC8B;AAC9B,QAAM,SAAuC,CAAC;AAE9C,MAAI,WAAW,KAAK;AAClB,WAAO,QAAQ,eAAe,IAAI,OAAO,SAAS,OAAO;AAAA,EAC3D;AACA,MAAI,YAAY,KAAK;AACnB,WAAO,SAAS,eAAe,IAAI,QAAQ,UAAU,OAAO;AAAA,EAC9D;AACA,MAAI,iBAAiB,KAAK;AACxB,WAAO,cAAc,eAAe,IAAI,aAAa,eAAe,SAAS;AAAA,MAC3E,KAAK;AAAA,MACL,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AACA,MAAI,cAAc,KAAK;AACrB,WAAO,WAAW,iBAAiB,IAAI,UAAU,OAAO;AAAA,EAC1D;AAEA,SAAO;AACT;AAKA,SAAS,qBAAqB,KAAc,SAA+B;AACzE,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,UAAM,IAAI,YAAY,IAAI,OAAO,mBAAmB;AAAA,EACtD;AAEA,QAAM,SAAS;AAGf,aAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,QAAI,CAAC,mBAAmB,IAAI,GAAG,GAAG;AAChC,YAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,wBAAwB;AAAA,IACnE;AAAA,EACF;AAEA,SAAO,sBAAsB,QAAQ,OAAO;AAC9C;AAKA,SAAS,uBAAuB,KAAc,SAAiC;AAC7E,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,UAAM,IAAI,YAAY,IAAI,OAAO,mBAAmB;AAAA,EACtD;AAEA,QAAM,SAAS;AAGf,aAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,QAAI,CAAC,qBAAqB,IAAI,GAAG,GAAG;AAClC,YAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,wBAAwB;AAAA,IACnE;AAAA,EACF;AAEA,QAAM,SAAyB;AAAA,IAC7B,GAAG,mBAAmB,QAAQ,OAAO;AAAA,IACrC,GAAG,sBAAsB,QAAQ,OAAO;AAAA,EAC1C;AAEA,MAAI,gBAAgB,QAAQ;AAC1B,WAAO,YAAY,IAAI,eAAe,OAAO,YAAY,GAAG,cAAc,SAAS;AAAA,MACjF,SAAS;AAAA,MACT,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AACA,MAAI,WAAW,QAAQ;AACrB,WAAO,QAAQ,gBAAgB,OAAO,OAAO,SAAS,OAAO;AAAA,EAC/D;AACA,MAAI,sBAAsB,QAAQ;AAChC,WAAO,kBAAkB,IAAI;AAAA,MAC3B,OAAO,kBAAkB;AAAA,MACzB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,oBAAoB,KAAc,SAA8B;AACvE,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,UAAM,IAAI,YAAY,IAAI,OAAO,mBAAmB;AAAA,EACtD;AAEA,QAAM,SAAS;AAGf,aAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,QAAI,CAAC,kBAAkB,IAAI,GAAG,GAAG;AAC/B,YAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,wBAAwB;AAAA,IACnE;AAAA,EACF;AAEA,QAAM,SAAsB;AAAA,IAC1B,GAAG,mBAAmB,QAAQ,OAAO;AAAA,IACrC,GAAG,sBAAsB,QAAQ,OAAO;AAAA,EAC1C;AAEA,MAAI,oBAAoB,QAAQ;AAC9B,WAAO,gBAAgB,IAAI,eAAe,OAAO,gBAAgB,GAAG,kBAAkB,SAAS;AAAA,MAC7F,SAAS;AAAA,MACT,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AAEA,MAAI,aAAa,QAAQ;AACvB,WAAO,UAAU,oBAAoB,OAAO,SAAS,WAAW,OAAO;AAAA,EACzE;AACA,MAAI,gBAAgB,QAAQ;AAC1B,WAAO,YAAY,IAAI,oBAAoB,OAAO,YAAY,GAAG,cAAc,OAAO;AAAA,EACxF;AACA,MAAI,mBAAmB,QAAQ;AAC7B,WAAO,eAAe,IAAI;AAAA,MACxB,OAAO,eAAe;AAAA,MACtB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,QAAQ;AACtB,WAAO,SAAS,oBAAoB,OAAO,QAAQ,UAAU,OAAO;AAAA,EACtE;AACA,MAAI,cAAc,QAAQ;AACxB,WAAO,WAAW,gBAAgB,OAAO,UAAU,YAAY,OAAO;AAAA,EACxE;AACA,MAAI,yBAAyB,QAAQ;AACnC,WAAO,qBAAqB,IAAI;AAAA,MAC9B,OAAO,qBAAqB;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,yBAAyB,QAAQ;AACnC,WAAO,qBAAqB,IAAI;AAAA,MAC9B,OAAO,qBAAqB;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,uBAAuB,QAAQ;AACjC,WAAO,mBAAmB,IAAI;AAAA,MAC5B,OAAO,mBAAmB;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,uBAAuB,QAAQ;AACjC,WAAO,mBAAmB,IAAI;AAAA,MAC5B,OAAO,mBAAmB;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,qBAAqB,QAAQ;AAC/B,WAAO,iBAAiB,IAAI,uBAAuB,OAAO,iBAAiB,GAAG,OAAO;AAAA,EACvF;AACA,MAAI,eAAe,QAAQ;AACzB,WAAO,YAAY,0BAA0B,OAAO,WAAW,OAAO;AAAA,EACxE;AACA,MAAI,WAAW,QAAQ;AACrB,WAAO,QAAQ,gBAAgB,OAAO,OAAO,SAAS,OAAO;AAAA,EAC/D;AACA,MAAI,sBAAsB,QAAQ;AAChC,WAAO,kBAAkB,IAAI;AAAA,MAC3B,OAAO,kBAAkB;AAAA,MACzB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,oBAAoB,KAAc,SAA8B;AACvE,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,UAAM,IAAI,YAAY,IAAI,OAAO,mBAAmB;AAAA,EACtD;AAEA,QAAM,SAAS;AAGf,aAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,QAAI,CAAC,kBAAkB,IAAI,GAAG,GAAG;AAC/B,YAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,wBAAwB;AAAA,IACnE;AAAA,EACF;AAEA,QAAM,SAAsB,CAAC;AAE7B,MAAI,WAAW,QAAQ;AACrB,WAAO,QAAQ,eAAe,OAAO,OAAO,SAAS,OAAO;AAAA,EAC9D;AACA,MAAI,UAAU,QAAQ;AACpB,WAAO,OAAO,eAAe,OAAO,MAAM,QAAQ,OAAO;AAAA,EAC3D;AACA,MAAI,aAAa,QAAQ;AACvB,WAAO,UAAU,eAAe,OAAO,SAAS,WAAW,OAAO;AAAA,EACpE;AACA,MAAI,WAAW,QAAQ;AACrB,WAAO,QAAQ,eAAe,OAAO,OAAO,SAAS,SAAS;AAAA,MAC5D,SAAS;AAAA,MACT,KAAK;AAAA,MACL,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AACA,MAAI,YAAY,QAAQ;AACtB,WAAO,SAAS,eAAe,OAAO,QAAQ,UAAU,OAAO;AAAA,EACjE;AACA,MAAI,WAAW,QAAQ;AACrB,WAAO,QAAQ,gBAAgB,OAAO,OAAO,SAAS,OAAO;AAAA,EAC/D;AAEA,SAAO;AACT;AAKA,SAAS,qBAAqB,KAAc,SAA+B;AACzE,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,UAAM,IAAI,YAAY,IAAI,OAAO,mBAAmB;AAAA,EACtD;AAEA,QAAM,SAAS;AAGf,aAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,QAAI,CAAC,mBAAmB,IAAI,GAAG,GAAG;AAChC,YAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,wBAAwB;AAAA,IACnE;AAAA,EACF;AAEA,QAAM,SAAuB,CAAC;AAE9B,MAAI,WAAW,QAAQ;AACrB,WAAO,QAAQ,eAAe,OAAO,OAAO,SAAS,OAAO;AAAA,EAC9D;AACA,MAAI,WAAW,QAAQ;AACrB,WAAO,QAAQ,eAAe,OAAO,OAAO,SAAS,OAAO;AAAA,EAC9D;AACA,MAAI,YAAY,QAAQ;AACtB,WAAO,SAAS,eAAe,OAAO,QAAQ,UAAU,OAAO;AAAA,EACjE;AACA,MAAI,WAAW,QAAQ;AACrB,WAAO,QAAQ,eAAe,OAAO,OAAO,SAAS,SAAS;AAAA,MAC5D,KAAK;AAAA,MACL,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AACA,MAAI,YAAY,QAAQ;AACtB,WAAO,SAAS,eAAe,OAAO,QAAQ,UAAU,OAAO;AAAA,EACjE;AACA,MAAI,WAAW,QAAQ;AACrB,WAAO,QAAQ,gBAAgB,OAAO,OAAO,SAAS,OAAO;AAAA,EAC/D;AAEA,SAAO;AACT;AAKA,SAAS,wBAAwB,OAAgB,OAAe,SAAmC;AACjG,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,WAAW;AAC3D,WAAO;AAAA,EACT;AACA,QAAM,IAAI,YAAY,IAAI,OAAO,KAAK,KAAK,8BAA8B;AAC3E;AAKA,SAAS,qBAAqB,KAAc,SAAsC;AAChF,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,UAAM,IAAI,YAAY,IAAI,OAAO,mBAAmB;AAAA,EACtD;AAEA,QAAM,SAAS;AAGf,aAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,QAAI,CAAC,mBAAmB,IAAI,GAAG,GAAG;AAChC,YAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,wBAAwB;AAAA,IACnE;AAAA,EACF;AAGA,MAAI,OAAoB;AACxB,MAAI,UAAU,QAAQ;AACpB,UAAM,YAAY,eAAe,OAAO,MAAM,QAAQ,OAAO;AAC7D,QAAI,cAAc,WAAW,cAAc,YAAY;AACrD,YAAM,IAAI,YAAY,IAAI,OAAO,sCAAsC;AAAA,IACzE;AACA,WAAO;AAAA,EACT;AAGA,QAAM,SAA8B;AAAA,IAClC,GAAG,mBAAmB,QAAQ,OAAO;AAAA,IACrC;AAAA,EACF;AAEA,MAAI,iBAAiB,QAAQ;AAC3B,WAAO,cAAc,eAAe,OAAO,aAAa,eAAe,OAAO;AAAA,EAChF;AAGA,MAAI,oBAAoB,QAAQ;AAC9B,WAAO,gBAAgB,IAAI,eAAe,OAAO,gBAAgB,GAAG,kBAAkB,SAAS;AAAA,MAC7F,SAAS;AAAA,MACT,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AAEA,MAAI,aAAa,QAAQ;AACvB,WAAO,UAAU,oBAAoB,OAAO,SAAS,WAAW,OAAO;AAAA,EACzE;AACA,MAAI,gBAAgB,QAAQ;AAC1B,WAAO,YAAY,IAAI,oBAAoB,OAAO,YAAY,GAAG,cAAc,OAAO;AAAA,EACxF;AACA,MAAI,mBAAmB,QAAQ;AAC7B,WAAO,eAAe,IAAI;AAAA,MACxB,OAAO,eAAe;AAAA,MACtB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,QAAQ;AACtB,WAAO,SAAS,oBAAoB,OAAO,QAAQ,UAAU,OAAO;AAAA,EACtE;AACA,MAAI,cAAc,QAAQ;AACxB,WAAO,WAAW,gBAAgB,OAAO,UAAU,YAAY,OAAO;AAAA,EACxE;AACA,MAAI,yBAAyB,QAAQ;AACnC,WAAO,qBAAqB,IAAI;AAAA,MAC9B,OAAO,qBAAqB;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,yBAAyB,QAAQ;AACnC,WAAO,qBAAqB,IAAI;AAAA,MAC9B,OAAO,qBAAqB;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,uBAAuB,QAAQ;AACjC,WAAO,mBAAmB,IAAI;AAAA,MAC5B,OAAO,mBAAmB;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,uBAAuB,QAAQ;AACjC,WAAO,mBAAmB,IAAI;AAAA,MAC5B,OAAO,mBAAmB;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,MAAI,qBAAqB,QAAQ;AAC/B,WAAO,iBAAiB,IAAI,uBAAuB,OAAO,iBAAiB,GAAG,OAAO;AAAA,EACvF;AACA,MAAI,eAAe,QAAQ;AACzB,WAAO,YAAY,0BAA0B,OAAO,WAAW,OAAO;AAAA,EACxE;AAGA,MAAI,gBAAgB,QAAQ;AAC1B,WAAO,YAAY,IAAI,eAAe,OAAO,YAAY,GAAG,cAAc,SAAS;AAAA,MACjF,SAAS;AAAA,MACT,KAAK;AAAA,IACP,CAAC;AAAA,EACH;AAGA,MAAI,WAAW,QAAQ;AACrB,WAAO,QAAQ,gBAAgB,OAAO,OAAO,SAAS,OAAO;AAAA,EAC/D;AAGA,SAAO,OAAO,QAAQ,sBAAsB,QAAQ,OAAO,CAAC;AAE5D,SAAO;AACT;AAMA,SAAS,sBAAsB,KAAc,SAAgC;AAC3E,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,UAAM,IAAI,YAAY,IAAI,OAAO,mBAAmB;AAAA,EACtD;AAEA,QAAM,SAAwB,CAAC;AAC/B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAA8B,GAAG;AACzE,QAAI,OAAO,UAAU,UAAU;AAC7B,YAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,mBAAmB;AAAA,IAC9D;AACA,WAAO,GAAG,IAAI;AAAA,EAChB;AACA,SAAO;AACT;AAOO,SAAS,eAAe,KAAc,YAAgC;AAC3E,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,UAAM,IAAI,YAAY,+BAA+B,UAAU;AAAA,EACjE;AAEA,QAAM,SAAS;AACf,QAAM,SAAoB,CAAC;AAE3B,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI;AACF,UAAI,QAAQ,UAAU;AACpB,eAAO,SAAS,qBAAqB,OAAO,GAAG;AAAA,MACjD,WAAW,QAAQ,YAAY;AAC7B,eAAO,WAAW,uBAAuB,OAAO,GAAG;AAAA,MACrD,WAAW,QAAQ,SAAS;AAC1B,eAAO,QAAQ,oBAAoB,OAAO,GAAG;AAAA,MAC/C,WAAW,QAAQ,SAAS;AAC1B,eAAO,QAAQ,oBAAoB,OAAO,GAAG;AAAA,MAC/C,WAAW,QAAQ,UAAU;AAC3B,eAAO,SAAS,qBAAqB,OAAO,GAAG;AAAA,MACjD,WAAW,QAAQ,WAAW;AAC5B,eAAO,UAAU,sBAAsB,OAAO,GAAG;AAAA,MACnD,WAAW,QAAQ,aAAa;AAC9B,eAAO,YAAY,6BAA6B,OAAO,GAAG;AAAA,MAC5D,OAAO;AAEL,eAAO,GAAG,IAAI,qBAAqB,OAAO,GAAG;AAAA,MAC/C;AAAA,IACF,SAAS,OAAO;AACd,UAAI,iBAAiB,aAAa;AAChC,cAAM,IAAI,YAAY,MAAM,SAAS,UAAU;AAAA,MACjD;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO;AACT;AAQO,SAAS,aAAwB;AACtC,QAAM,aAAa,cAAc;AAEjC,MAAI,CAAC,WAAW,UAAU,GAAG;AAC3B,WAAO,CAAC;AAAA,EACV;AAEA,MAAI;AACJ,MAAI;AACF,cAAU,aAAa,YAAY,OAAO;AAAA,EAC5C,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,+BAA+B,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,MACvF;AAAA,IACF;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACF,UAAM,UAAU,OAAO;AAAA,EACzB,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,wBAAwB,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,MAChF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,YAAY,eAAe,KAAK,UAAU;AAChD,QAAM,YAAY,mBAAmB,WAAW,UAAU;AAC1D,SAAO,yBAAyB,WAAW,UAAU;AACvD;AAKO,SAAS,sBAAsB,QAA6B;AACjE,QAAM,WAAW,oBAAI,IAAI;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,SAAO,OAAO,KAAK,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,SAAS,IAAI,GAAG,CAAC;AAC/D;AAWO,SAAS,yBAAyB,QAAmB,YAAgC;AAC1F,QAAM,UAAU,OAAO,WAAW,CAAC;AAGnC,QAAM,aAAa,OAAO,KAAK,OAAO,EAAE,SAAS;AAGjD,MAAI,eAAe;AACnB,aAAW,CAAC,aAAa,OAAO,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3D,QAAI,gBAAgB,YAAY,gBAAgB,UAAW;AAC3D,QAAI,CAAC,WAAW,OAAO,YAAY,SAAU;AAE7C,UAAM,aAAa;AACnB,QAAI,OAAO,WAAW,WAAW,YAAY,kBAAkB,WAAW,MAAM,GAAG;AACjF,qBAAe;AACf;AAAA,IACF;AAAA,EACF;AAGA,aAAW,YAAY,OAAO,OAAO,OAAO,GAAG;AAC7C,QAAI,kBAAkB,QAAQ,GAAG;AAC/B,qBAAe;AACf;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,cAAc,CAAC,cAAc;AAChC,WAAO;AAAA,EACT;AAGA,MAAI;AACF,oBAAgB,SAAS,UAAU;AAAA,EACrC,SAAS,OAAO;AACd,QAAI,iBAAiB,eAAe;AAClC,YAAM,IAAI,YAAY,MAAM,SAAS,UAAU;AAAA,IACjD;AACA,UAAM;AAAA,EACR;AAGA,aAAW,CAAC,MAAM,QAAQ,KAAK,OAAO,QAAQ,OAAO,GAAG;AACtD,QAAI;AACF,sBAAgB,UAAU,MAAM,UAAU;AAAA,IAC5C,SAAS,OAAO;AACd,UAAI,iBAAiB,eAAe;AAClC,cAAM,IAAI,YAAY,MAAM,SAAS,UAAU;AAAA,MACjD;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAGA,QAAM,MAAM,qBAAqB,SAAS,UAAU;AACpD,QAAM,SAAS,EAAE,GAAG,OAAO;AAG3B,aAAW,CAAC,aAAa,OAAO,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3D,QAAI,gBAAgB,YAAY,gBAAgB,UAAW;AAC3D,QAAI,CAAC,WAAW,OAAO,YAAY,SAAU;AAE7C,UAAM,aAAa;AACnB,QAAI,OAAO,WAAW,WAAW,YAAY,kBAAkB,WAAW,MAAM,GAAG;AAEjF,UAAI;AACF,wBAAgB,WAAW,QAAQ,QAAW,UAAU;AAAA,MAC1D,SAAS,OAAO;AACd,YAAI,iBAAiB,eAAe;AAClC,gBAAM,IAAI,YAAY,IAAI,WAAW,aAAa,MAAM,OAAO,IAAI,UAAU;AAAA,QAC/E;AACA,cAAM;AAAA,MACR;AAGA,UAAI;AACF,cAAM,WAAW,gBAAgB,KAAK,WAAW,QAAQ,CAAC,GAAG,UAAU;AACvE,eAAO,WAAW,IAAI;AAAA,UACpB,GAAG;AAAA,UACH,QAAQ;AAAA,QACV;AAAA,MACF,SAAS,OAAO;AACd,YAAI,iBAAiB,eAAe;AAClC,gBAAM,IAAI,YAAY,IAAI,WAAW,aAAa,MAAM,OAAO,IAAI,UAAU;AAAA,QAC/E;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAiBA,SAAS,eACP,SACA,kBACA,aACA,YACU;AACV,QAAM,aAAa,aAAa;AAChC,QAAM,kBAAkB,YAAY;AACpC,QAAM,eAAe,gBAAgB;AACrC,QAAM,kBAAkB,mBAAmB;AAG3C,MAAI,mBAAmB,CAAC,YAAY;AAClC,YAAQ;AAAA,MACN,sBAAsB,WAAW;AAAA,IACnC;AAAA,EACF;AAGA,OAAK,cAAc,qBAAqB,gBAAgB,kBAAkB;AACxE,UAAM,IAAI;AAAA,MACR,IAAI,WAAW;AAAA,MAEf;AAAA,IACF;AAAA,EACF;AAGA,MAAI,YAAY;AACd,WAAO,QAAQ;AAAA,EACjB;AACA,MAAI,iBAAiB;AACnB,WAAO,QAAQ;AAAA,EACjB;AAGA,MAAI,SAAS,CAAC,GAAG,gBAAgB;AAGjC,MAAI,iBAAiB;AACnB,UAAM,WAAW,IAAI,IAAI,QAAQ,eAAe,CAAa;AAC7D,aAAS,OAAO,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;AAAA,EAChD;AAGA,MAAI,cAAc;AAChB,UAAM,QAAQ,QAAQ,YAAY;AAClC,WAAO,KAAK,GAAG,KAAK;AAAA,EACtB;AAEA,SAAO;AACT;AAgBO,SAAS,mBAAmB,QAAmB,YAAgC;AACpF,QAAM,WAAoD,CAAC;AAC3D,QAAM,YAAY,oBAAI,IAAY;AAElC,WAAS,eAAe,MAAuC;AAE7D,QAAI,QAAQ,UAAU;AACpB,aAAO,SAAS,IAAI;AAAA,IACtB;AAGA,QAAI,UAAU,IAAI,IAAI,GAAG;AACvB,YAAM,IAAI,YAAY,kCAAkC,IAAI,IAAI,UAAU;AAAA,IAC5E;AAEA,UAAM,UAAU,OAAO,IAAI;AAC3B,QAAI,YAAY,UAAa,OAAO,YAAY,UAAU;AACxD,YAAM,IAAI,YAAY,wCAAwC,IAAI,IAAI,UAAU;AAAA,IAClF;AAEA,cAAU,IAAI,IAAI;AAGlB,UAAM,aAAa;AACnB,UAAM,cAAc,WAAW;AAC/B,UAAM,eAAyB,cAC3B,MAAM,QAAQ,WAAW,IACvB,cACA,CAAC,WAAW,IACd,CAAC;AAGL,QAAI,SAAkC,CAAC;AACvC,eAAW,UAAU,cAAc;AACjC,YAAM,iBAAiB,eAAe,MAAM;AAC5C,eAAS,EAAE,GAAG,QAAQ,GAAG,eAAe;AAAA,IAC1C;AAGA,UAAM,mBAAoB,OAAO,WAAoC,CAAC;AAGtE,UAAM;AAAA,MACJ,UAAU;AAAA,MACV,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,GAAG;AAAA,IACL,IAAI;AACJ,aAAS,EAAE,GAAG,QAAQ,GAAG,UAAU;AAGnC,UAAM,kBAAkB,eAAe,YAAY,kBAAkB,MAAM,UAAU;AACrF,QAAI,gBAAgB,SAAS,GAAG;AAC9B,aAAO,UAAU;AAAA,IACnB;AAGA,WAAO,OAAO,QAAQ;AACtB,WAAO,OAAO,YAAY;AAC1B,WAAO,OAAO,eAAe;AAE7B,cAAU,OAAO,IAAI;AACrB,aAAS,IAAI,IAAI;AACjB,WAAO;AAAA,EACT;AAGA,aAAW,QAAQ,OAAO,KAAK,MAAM,GAAG;AACtC,mBAAe,IAAI;AAAA,EACrB;AAEA,SAAO;AACT;;;ADtsCA,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyDvB,eAAsB,YACpB,UACA,KACe;AACf,QAAM,aAAa,cAAc;AACjC,QAAM,YAAY,QAAQ,UAAU;AAGpC,MAAIC,YAAW,UAAU,GAAG;AAC1B,QAAI,OAAO,MAAM,mCAAmC,UAAU;AAAA,CAAI;AAClE,QAAI,OAAO,MAAM,IAAI;AACrB,QAAI,OAAO,MAAM,oBAAoB,UAAU;AAAA,CAAI;AACnD,QAAI,OAAO,MAAM,mBAAmB,UAAU;AAAA,CAAmB;AACjE;AAAA,EACF;AAGA,MAAI,CAACA,YAAW,SAAS,GAAG;AAC1B,cAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC1C;AAGA,gBAAc,YAAY,gBAAgB,OAAO;AAGjD,MAAI,OAAO,MAAM,WAAW,UAAU;AAAA,CAAI;AAC1C,MAAI,OAAO,MAAM,IAAI;AACrB,MAAI,OAAO,MAAM,eAAe;AAChC,MAAI,OAAO,MAAM,0BAA0B;AAC3C,MAAI,OAAO,MAAM,uCAAuC;AACxD,MAAI,OAAO,MAAM,0CAA0C;AAC3D,MAAI,OAAO,MAAM,oCAAoC;AACrD,MAAI,OAAO,MAAM,IAAI;AACrB,MAAI,OAAO,MAAM;AAAA,CAA+B;AAChD,MAAI,OAAO,MAAM,kBAAkB,UAAU;AAAA,CAAI;AACjD,MAAI,OAAO,MAAM,IAAI;AACrB,MAAI,OAAO,MAAM,yBAAyB;AAC1C,MAAI,OAAO;AAAA,IACT;AAAA,EACF;AACA,MAAI,OAAO,MAAM,IAAI;AACrB,MAAI,OAAO,MAAM,2CAA2C;AAC9D;AAKO,SAAS,oBAAoB,SAAkB,KAA2B;AAC/E,UACG,QAAQ,SAAS,IAAI,EACrB,YAAY,uDAAuD,EACnE,OAAO,CAAC,YAAgC,cAAc,MAAM,YAAY,SAAS,GAAG,GAAG,GAAG,CAAC;AAChG;;;AG7HA;AAEA;AALA,OAAO,cAAc;AACrB,OAAOC,YAAW;AAuClB,IAAM,gBAAwC;AAAA,EAC5C,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AACT;AAMO,SAAS,oBAAoB,QAA6D;AAC/F,SAAO,CAAC,SAAiB;AACvB,UAAM,UAAyB,EAAE,KAAK;AAGtC,QAAI,QAAQ,UAAU;AACpB,YAAM,QAAQ,OAAO,SAAS,YAAY;AAC1C,UAAI,SAAS,eAAe;AAC1B,gBAAQ,WAAW,cAAc,KAAK;AAAA,MACxC;AAAA,IACF;AAGA,QAAI,QAAQ,aAAa,QAAW;AAClC,cAAQ,WAAW,OAAO;AAAA,IAC5B;AAKA,QAAI,QAAQ,SAAS;AACnB,YAAM,kBAAkB,QAAQ,IAAI;AACpC,cAAQ,IAAI,kBAAkB,OAAO;AACrC,YAAM,SAAS,aAAa,OAAO;AAEnC,UAAI,oBAAoB,QAAW;AACjC,eAAO,QAAQ,IAAI;AAAA,MACrB,OAAO;AACL,gBAAQ,IAAI,kBAAkB;AAAA,MAChC;AACA,aAAO;AAAA,IACT;AAGA,QAAI,CAAC,QAAQ,IAAI,iBAAiB;AAChC,cAAQ,OAAO;AAAA,IACjB;AAEA,WAAO,aAAa,OAAO;AAAA,EAC7B;AACF;AAKA,SAAS,qBACP,OACA,QACuC;AACvC,SAAO,CAAC,aAAqB;AAC3B,WAAO,IAAI,QAAQ,CAACC,aAAY;AAC9B,YAAM,KAAK,SAAS,gBAAgB;AAAA,QAClC,OAAO;AAAA,QACP,QAAQ;AAAA,MACV,CAAC;AAED,aAAO,MAAM,IAAI;AACjB,aAAO,MAAM,GAAGD,OAAM,KAAK,SAAI,OAAO,EAAE,CAAC,CAAC;AAAA,CAAI;AAC9C,aAAO,MAAMA,OAAM,KAAK,KAAK,yBAAkB,CAAC;AAChD,aAAO,MAAM,GAAG,QAAQ;AAAA,CAAI;AAC5B,aAAO,MAAM,GAAGA,OAAM,KAAK,SAAI,OAAO,EAAE,CAAC,CAAC;AAAA,CAAI;AAC9C,SAAG,SAASA,OAAM,MAAM,KAAK,OAAO,GAAG,CAAC,WAAW;AACjD,WAAG,MAAM;AACT,QAAAC,SAAQ,MAAM;AAAA,MAChB,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;AASO,SAAS,yBAAyB,cAAgD;AACvF,QAAM,QAAQ,QAAQ,QAAQ,MAAM,KAAK;AAEzC,SAAO;AAAA,IACL,MAAM,QAAQ;AAAA,IACd,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ;AAAA,IAChB,QAAQ,QAAQ;AAAA,IAChB,cAAc,MAAM,IAAI,OAAO;AAAA,IAC/B,aAAa,CAAC,SAAiB;AAC7B,cAAQ,WAAW;AAAA,IACrB;AAAA,IACA;AAAA,IACA,cAAc,oBAAoB,YAAY;AAAA,IAC9C;AAAA,IACA,QAAQ,QACJ,qBAAqB,QAAQ,OAAO,QAAQ,MAAM,IAClD,YAAY;AACV,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AAAA,EACN;AACF;;;ACpIA,SAAS,yBACP,SACA,QACgB;AAEhB,QAAM,mBACJ,OAAO,WAAW,MAAM,UACxB,OAAO,UAAU,MAAM,UACvB,OAAO,WAAW,MAAM;AAE1B,MAAI,CAAC,kBAAkB;AACrB,WAAO;AAAA,EACT;AAGA,QAAM,eAAgC;AAAA,IACpC,UAAU,OAAO,WAAW,KAAK,QAAQ,cAAc;AAAA,IACvD,SAAS,OAAO,UAAU,KAAK,QAAQ,cAAc;AAAA,IACrD,UAAU,OAAO,WAAW,KAAK,QAAQ,cAAc;AAAA,EACzD;AAGA,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA,cAAc,oBAAoB,YAAY;AAAA,EAChD;AACF;AAcO,SAAS,sBACd,SACA,MACA,QACA,KACA,iBACM;AACN,QAAM,OAAO,OAAO,QAAQ;AAC5B,QAAM,cAAc,OAAO,eAAe,UAAU,IAAI;AAExD,QAAM,MAAM,QACT,QAAQ,IAAI,EACZ,YAAY,WAAW,EACvB,SAAS,YAAY,6DAA6D;AAErF,MAAI,SAAS,YAAY;AAEvB,uBAAmB,KAAK,MAAM;AAE9B,QAAI,OAAO,CAAC,QAAQ,eAAe;AAEjC,YAAM,SAAS,yBAAyB,KAAK,MAAM;AACnD,aAAO,cAAc,YAAY;AAE/B,cAAM,iBAAiB,wBAAwB,MAAM;AACrD,cAAM,UAA8B;AAAA,UAClC,GAAG;AAAA,UACH,GAAI;AAAA,QACN;AACA,cAAM,gBAAgB,QAAQ,SAAS,MAAM;AAAA,MAC/C,GAAG,MAAM;AAAA,IACX,CAAC;AAAA,EACH,OAAO;AAEL,oBAAgB,KAAK,MAAM;AAE3B,QAAI,OAAO,CAAC,QAAQ,eAAe;AAEjC,YAAM,SAAS,yBAAyB,KAAK,MAAM;AACnD,aAAO,cAAc,YAAY;AAE/B,cAAM,iBAAiB,qBAAqB,MAAM;AAClD,cAAM,UAA2B;AAAA,UAC/B,GAAG;AAAA,UACH,GAAI;AAAA,UACJ;AAAA,QACF;AACA,cAAM,aAAa,QAAQ,SAAS,MAAM;AAAA,MAC5C,GAAG,MAAM;AAAA,IACX,CAAC;AAAA,EACH;AACF;;;ACpGA;AACA;AALA,OAAOC,YAAW;;;ACKlB;AAJA,SAAS,uBAAuB;AAChC,OAAOC,YAAW;AAmClB,eAAsB,oBACpB,QACA,KACkC;AAClC,MAAI,CAAC,QAAQ;AACX,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,aAAa,mBAAmB,QAAQ,EAAE,QAAQ,UAAU,CAAC;AAKnE,MAAI,CAAC,WAAW,cAAc,OAAO,KAAK,WAAW,UAAU,EAAE,WAAW,GAAG;AAC7E,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,KAAK,gBAAgB,EAAE,OAAO,IAAI,OAAO,QAAQ,IAAI,OAAO,CAAC;AACnE,QAAM,SAAkC,CAAC;AAEzC,MAAI;AACF,eAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,WAAW,UAAU,GAAG;AAC/D,YAAM,QAAQ,MAAM,eAAe,IAAI,KAAK,MAAM,WAAW,YAAY,CAAC,CAAC;AAC3E,UAAI,UAAU,QAAW;AACvB,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF,UAAE;AACA,OAAG,MAAM;AAAA,EACX;AAGA,QAAM,SAAS,OAAO,UAAU,MAAM;AACtC,MAAI,CAAC,OAAO,SAAS;AACnB,UAAM,SAAS,OAAO,MAAM,OAAO,IAAI,CAAC,MAAM,KAAK,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI;AAC9F,UAAM,IAAI,MAAM;AAAA,EAAwB,MAAM,EAAE;AAAA,EAClD;AAEA,SAAO,OAAO;AAChB;AAKA,eAAe,eACb,IACA,KACA,MACA,UACkB;AAClB,QAAM,aAAa,SAAS,SAAS,GAAG;AACxC,QAAM,WAAW,eAAe,IAAI;AACpC,QAAM,cACJ,KAAK,YAAY,SAAYA,OAAM,IAAI,cAAc,KAAK,UAAU,KAAK,OAAO,CAAC,GAAG,IAAI;AAC1F,QAAM,iBAAiB,aAAaA,OAAM,IAAI,GAAG,IAAI;AAGrD,MAAI,SAAS;AAAA,EAAKA,OAAM,KAAK,KAAK,GAAG,CAAC,GAAG,cAAc;AACvD,MAAI,KAAK,aAAa;AACpB,cAAUA,OAAM,IAAI,MAAM,KAAK,WAAW,EAAE;AAAA,EAC9C;AACA,YAAU;AAAA,IAAO,QAAQ,GAAG,WAAW;AAAA,IAAOA,OAAM,MAAM,GAAG,CAAC;AAE9D,QAAM,SAAS,MAAM,GAAG,SAAS,MAAM;AACvC,QAAM,UAAU,OAAO,KAAK;AAG5B,MAAI,CAAC,SAAS;AACZ,QAAI,KAAK,YAAY,QAAW;AAC9B,aAAO;AAAA,IACT;AACA,QAAI,CAAC,YAAY;AACf,aAAO;AAAA,IACT;AACA,UAAM,IAAI,MAAM,cAAc,GAAG,gBAAgB;AAAA,EACnD;AAGA,SAAO,WAAW,SAAS,MAAM,GAAG;AACtC;AAKA,SAAS,eAAe,MAAkC;AAExD,MAAI,KAAK,MAAM;AACb,WAAOA,OAAM,OAAO,IAAI,KAAK,KAAK,KAAK,KAAK,CAAC,GAAG;AAAA,EAClD;AAGA,MAAI,KAAK,SAAS,SAAS;AACzB,UAAM,QAAQ,KAAK;AACnB,QAAI,OAAO,MAAM;AACf,aAAOA,OAAM,OAAO,IAAI,MAAM,KAAK,KAAK,KAAK,CAAC,qBAAqB;AAAA,IACrE;AACA,UAAM,WAAW,OAAO,QAAQ;AAChC,WAAOA,OAAM,OAAO,IAAI,QAAQ,qBAAqB;AAAA,EACvD;AAGA,MAAI,KAAK,SAAS,YAAY,KAAK,YAAY;AAC7C,WAAOA,OAAM,OAAO,wBAAwB;AAAA,EAC9C;AAGA,SAAOA,OAAM,OAAO,IAAI,KAAK,QAAQ,KAAK,GAAG;AAC/C;AAKA,SAAS,WAAW,OAAe,MAA0B,KAAsB;AACjF,QAAM,OAAO,KAAK;AAGlB,MAAI,SAAS,YAAY,SAAS,WAAW;AAC3C,UAAM,MAAM,OAAO,KAAK;AACxB,QAAI,OAAO,MAAM,GAAG,GAAG;AACrB,YAAM,IAAI,MAAM,uBAAuB,GAAG,MAAM,KAAK,EAAE;AAAA,IACzD;AACA,QAAI,SAAS,aAAa,CAAC,OAAO,UAAU,GAAG,GAAG;AAChD,YAAM,IAAI,MAAM,yBAAyB,GAAG,WAAW,KAAK,EAAE;AAAA,IAChE;AACA,WAAO;AAAA,EACT;AAGA,MAAI,SAAS,WAAW;AACtB,UAAM,QAAQ,MAAM,YAAY;AAChC,QAAI,CAAC,QAAQ,OAAO,KAAK,GAAG,EAAE,SAAS,KAAK,EAAG,QAAO;AACtD,QAAI,CAAC,SAAS,MAAM,KAAK,GAAG,EAAE,SAAS,KAAK,EAAG,QAAO;AACtD,UAAM,IAAI,MAAM,wBAAwB,GAAG,MAAM,KAAK,gCAAgC;AAAA,EACxF;AAGA,MAAI,SAAS,SAAS;AACpB,UAAM,QAAQ,MACX,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AACjB,UAAM,WAAW,KAAK,OAAO;AAG7B,QAAI,aAAa,YAAY,aAAa,WAAW;AACnD,aAAO,MAAM,IAAI,CAAC,SAAS;AACzB,cAAM,MAAM,OAAO,IAAI;AACvB,YAAI,OAAO,MAAM,GAAG,EAAG,OAAM,IAAI,MAAM,sBAAsB,GAAG,YAAY,IAAI,EAAE;AAClF,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AACA,QAAI,aAAa,WAAW;AAC1B,aAAO,MAAM,IAAI,CAAC,SAAS;AACzB,cAAM,QAAQ,KAAK,YAAY;AAC/B,YAAI,CAAC,QAAQ,OAAO,KAAK,GAAG,EAAE,SAAS,KAAK,EAAG,QAAO;AACtD,YAAI,CAAC,SAAS,MAAM,KAAK,GAAG,EAAE,SAAS,KAAK,EAAG,QAAO;AACtD,cAAM,IAAI,MAAM,uBAAuB,GAAG,YAAY,IAAI,EAAE;AAAA,MAC9D,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAGA,MAAI,SAAS,UAAU;AACrB,QAAI;AACF,aAAO,KAAK,MAAM,KAAK;AAAA,IACzB,QAAQ;AACN,YAAM,IAAI,MAAM,qBAAqB,GAAG,MAAM,KAAK,EAAE;AAAA,IACvD;AAAA,EACF;AAGA,SAAO;AACT;AAQA,eAAsB,cACpB,OACkC;AAClC,QAAM,SAAmB,CAAC;AAE1B,mBAAiB,SAAS,OAAO;AAC/B,QAAI,OAAO,UAAU,UAAU;AAC7B,aAAO,KAAK,KAAK;AAAA,IACnB,OAAO;AACL,aAAO,KAAK,MAAM,SAAS,MAAM,CAAC;AAAA,IACpC;AAAA,EACF;AAEA,QAAM,UAAU,OAAO,KAAK,EAAE,EAAE,KAAK;AAErC,MAAI,CAAC,SAAS;AACZ,WAAO,CAAC;AAAA,EACV;AAEA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,OAAO;AACjC,QAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,MAAM,QAAQ,MAAM,GAAG;AAC1E,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAChF;AACA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,aAAa;AAChC,YAAM,IAAI,MAAM,4BAA4B,MAAM,OAAO,EAAE;AAAA,IAC7D;AACA,UAAM;AAAA,EACR;AACF;;;ADzMA,eAAe,aACb,MACA,YACA,KAC0B;AAC1B,QAAM,UAAU,MAAM,YAAY,CAAC,IAAI,GAAG,GAAG;AAE7C,MAAI,QAAQ,WAAW,GAAG;AACxB,UAAM,IAAI;AAAA,MACR,wBAAwB,IAAI;AAAA;AAAA,IAC9B;AAAA,EACF;AAGA,MAAI,QAAQ,WAAW,GAAG;AACxB,UAAM,SAAS,QAAQ,CAAC;AACxB,UAAM,OAAO,OAAO,QAAQ,OAAO,YAAY;AAC/C,WAAO,EAAE,QAAQ,KAAK;AAAA,EACxB;AAGA,QAAM,QAAQ,QAAQ,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,IAAI;AAE7D,MAAI,CAAC,YAAY;AACf,UAAM,IAAI;AAAA,MACR,SAAS,IAAI,aAAa,QAAQ,MAAM;AAAA;AAAA,IAEtC,MAAM,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI;AAAA,IAC1C;AAAA,EACF;AAGA,QAAM,QAAQ,QAAQ,KAAK,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,UAAU,UAAU;AAE/E,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR,WAAW,UAAU,mBAAmB,IAAI;AAAA;AAAA,IAE1C,MAAM,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI;AAAA,IAC1C;AAAA,EACF;AAEA,SAAO,EAAE,QAAQ,OAAO,MAAM,WAAW;AAC3C;AAMA,eAAe,iBACb,MACA,SACA,KACe;AACf,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,EAAE,QAAQ,KAAK,IAAI,MAAM,aAAa,MAAM,QAAQ,MAAM,GAAG;AAEnE,MAAI,OAAO,MAAMC,OAAM,KAAK,KAAK;AAAA,4BAAwB,IAAI;AAAA,CAAI,CAAC;AAGlE,MAAI;AAEJ,MAAI,IAAI,OAAO;AAEb,aAAS,MAAM,oBAAoB,OAAO,iBAAiB;AAAA,MACzD,OAAO,IAAI;AAAA,MACX,QAAQ,IAAI;AAAA;AAAA,IACd,CAAC;AAAA,EACH,OAAO;AAEL,QAAI,OAAO,MAAMA,OAAM,IAAI,oCAAoC,CAAC;AAChE,UAAM,cAAc,MAAM,cAAc,IAAI,KAAK;AAGjD,QAAI,OAAO,iBAAiB;AAC1B,YAAMC,UAAS,OAAO,gBAAgB,UAAU,WAAW;AAC3D,UAAI,CAACA,QAAO,SAAS;AACnB,cAAM,SAASA,QAAO,MAAM,OACzB,IAAI,CAAC,MAAM,KAAK,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAChD,KAAK,IAAI;AACZ,cAAM,IAAI,MAAM;AAAA,EAAwB,MAAM,EAAE;AAAA,MAClD;AACA,eAASA,QAAO;AAAA,IAClB,OAAO;AACL,eAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI,OAAO,MAAMD,OAAM,IAAI,kBAAkB,CAAC;AAG9C,QAAM,YAAY,KAAK,IAAI;AAC3B,MAAI;AACJ,MAAI;AAEJ,MAAI;AACF,QAAI;AACJ,QAAI,OAAO,aAAa,OAAO,YAAY,GAAG;AAC5C,kBAAY,MAAM,QAAQ,KAAK;AAAA,QAC7B,QAAQ,QAAQ,OAAO,QAAQ,MAAM,CAAC;AAAA,QACtC,IAAI;AAAA,UAAe,CAAC,GAAG,WACrB;AAAA,YACE,MAAM,OAAO,IAAI,MAAM,0BAA0B,OAAO,SAAS,IAAI,CAAC;AAAA,YACtE,OAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,OAAO;AACL,kBAAY,MAAM,QAAQ,QAAQ,OAAO,QAAQ,MAAM,CAAC;AAAA,IAC1D;AAEA,aAAS,OAAO,cAAc,WAAW,YAAY,UAAU;AAC/D,WAAO,OAAO,cAAc,WAAW,UAAU,OAAO;AAAA,EAC1D,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM,IAAI,MAAM,qBAAqB,OAAO,EAAE;AAAA,EAChD;AAEA,QAAM,UAAU,KAAK,IAAI,IAAI;AAC7B,QAAM,WAAW,SAAS,UAAa,OAAO,IAAI,YAAY,KAAK,QAAQ,CAAC,CAAC,MAAM;AACnF,MAAI,OAAO,MAAMA,OAAM,MAAM;AAAA,sBAAoB,OAAO,KAAK,QAAQ;AAAA;AAAA,CAAM,CAAC;AAG5E,eAAa,QAAQ,SAAS,IAAI,MAAM;AAC1C;AAKA,SAAS,aACP,QACA,SACA,QACM;AAEN,MAAI,QAAQ,KAAK;AACf,WAAO,MAAM,MAAM;AACnB,QAAI,CAAC,OAAO,SAAS,IAAI,EAAG,QAAO,MAAM,IAAI;AAC7C;AAAA,EACF;AAGA,MAAI,QAAQ,QAAQ,cAAc,MAAM,GAAG;AACzC,QAAI;AACF,YAAM,SAAS,KAAK,MAAM,MAAM;AAChC,aAAO,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AACnD;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,SAAO,MAAM,MAAM;AACnB,MAAI,CAAC,OAAO,SAAS,IAAI,EAAG,QAAO,MAAM,IAAI;AAC/C;AAKA,SAAS,cAAc,KAAsB;AAC3C,QAAM,UAAU,IAAI,KAAK;AACzB,SACG,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,KAC/C,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG;AAEpD;AAMA,eAAe,kBACb,MACA,SACA,KACe;AACf,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,EAAE,QAAQ,KAAK,IAAI,MAAM,aAAa,MAAM,QAAQ,MAAM,GAAG;AAEnE,MAAI,QAAQ,MAAM;AAEhB,UAAM,OAAO,gBAAgB,QAAQ,IAAI;AACzC,QAAI,OAAO,MAAM,KAAK,UAAU,MAAM,MAAM,CAAC,IAAI,IAAI;AACrD;AAAA,EACF;AAGA,MAAI,OAAO,MAAM,IAAI;AACrB,MAAI,OAAO,MAAMA,OAAM,KAAK,KAAK,GAAG,IAAI;AAAA,CAAI,CAAC;AAC7C,MAAI,OAAO,MAAMA,OAAM,KAAK,SAAI,OAAO,KAAK,MAAM,CAAC,IAAI,MAAM;AAG7D,MAAI,OAAO,MAAMA,OAAM,KAAK,gBAAgB,CAAC;AAC7C,MAAI,OAAO,MAAM,KAAK,OAAO,WAAW;AAAA;AAAA,CAAM;AAG9C,MAAI,OAAO,iBAAiB;AAC1B,QAAI,OAAO,MAAMA,OAAM,KAAK,eAAe,CAAC;AAC5C,UAAM,aAAa,mBAAmB,OAAO,iBAAiB,EAAE,QAAQ,UAAU,CAAC;AACnF,QAAI,OAAO,MAAM,mBAAmB,YAAY,IAAI,IAAI,MAAM;AAAA,EAChE,OAAO;AACL,QAAI,OAAO,MAAMA,OAAM,IAAI,6BAA6B,CAAC;AAAA,EAC3D;AAGA,MAAI,OAAO,WAAW;AACpB,QAAI,OAAO,MAAMA,OAAM,KAAK,YAAY,CAAC;AACzC,QAAI,OAAO,MAAM,KAAK,OAAO,SAAS;AAAA;AAAA,CAAQ;AAAA,EAChD;AAGA,MAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;AACjD,QAAI,OAAO,MAAMA,OAAM,KAAK,aAAa,CAAC;AAC1C,eAAW,WAAW,OAAO,UAAU;AACrC,UAAI,QAAQ,SAAS;AACnB,YAAI,OAAO,MAAMA,OAAM,IAAI,OAAO,QAAQ,OAAO;AAAA,CAAI,CAAC;AAAA,MACxD;AACA,UAAI,OAAO,MAAM,YAAYA,OAAM,KAAK,KAAK,UAAU,QAAQ,MAAM,CAAC,CAAC;AAAA,CAAI;AAC3E,UAAI,QAAQ,WAAW,QAAW;AAChC,YAAI,OAAO,MAAM,aAAaA,OAAM,MAAM,QAAQ,MAAM,CAAC;AAAA,CAAI;AAAA,MAC/D;AACA,UAAI,OAAO,MAAM,IAAI;AAAA,IACvB;AAAA,EACF;AACF;AAKA,SAAS,gBAAgB,QAAwB,MAAuC;AACtF,QAAM,OAAgC;AAAA,IACpC;AAAA,IACA,aAAa,OAAO;AAAA,EACtB;AAEA,MAAI,OAAO,iBAAiB;AAC1B,SAAK,SAAS,mBAAmB,OAAO,iBAAiB,EAAE,QAAQ,UAAU,CAAC;AAAA,EAChF;AAEA,MAAI,OAAO,WAAW;AACpB,SAAK,YAAY,OAAO;AAAA,EAC1B;AAEA,MAAI,OAAO,YAAY,OAAO,SAAS,SAAS,GAAG;AACjD,SAAK,WAAW,OAAO;AAAA,EACzB;AAEA,SAAO;AACT;AAKA,SAAS,mBAAmB,QAAiC,SAAS,IAAY;AAChF,QAAM,QAAkB,CAAC;AACzB,QAAM,aAAc,OAAO,cAAc,CAAC;AAC1C,QAAM,WAAY,OAAO,YAAY,CAAC;AAEtC,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,UAAU,GAAG;AACpD,UAAM,OAAO,KAAK;AAClB,UAAM,cAAc,KAAK;AACzB,UAAM,aAAa,SAAS,SAAS,GAAG;AACxC,UAAM,aAAa,KAAK;AACxB,UAAM,eAAe,KAAK;AAG1B,QAAI,OAAO,GAAG,MAAM,GAAGA,OAAM,KAAK,GAAG,CAAC;AAGtC,QAAI,YAAY;AACd,cAAQA,OAAM,IAAI,GAAG;AAAA,IACvB;AAGA,QAAI,SAAS,SAAS;AACpB,YAAM,QAAQ,KAAK;AACnB,YAAM,WAAW,OAAO,QAAQ;AAChC,cAAQA,OAAM,IAAI,KAAK,QAAQ,KAAK;AAAA,IACtC,WAAW,SAAS,YAAY,KAAK,YAAY;AAC/C,cAAQA,OAAM,IAAI,WAAW;AAAA,IAC/B,OAAO;AACL,cAAQA,OAAM,IAAI,KAAK,IAAI,GAAG;AAAA,IAChC;AAGA,QAAI,iBAAiB,QAAW;AAC9B,cAAQA,OAAM,IAAI,cAAc,KAAK,UAAU,YAAY,CAAC,GAAG;AAAA,IACjE;AAGA,QAAI,aAAa;AACf,cAAQ,KAAK,WAAW;AAAA,IAC1B;AAGA,QAAI,YAAY;AACd,cAAQA,OAAM,OAAO,cAAc,WAAW,KAAK,IAAI,CAAC,EAAE;AAAA,IAC5D;AAEA,UAAM,KAAK,IAAI;AAGf,QAAI,SAAS,YAAY,KAAK,YAAY;AACxC,YAAM,KAAK,mBAAmB,MAAM,SAAS,IAAI,CAAC;AAAA,IACpD;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAMA,eAAe,sBAAsB,MAAc,KAAoC;AACrF,QAAM,MAAM,QAAQ,IAAI;AAExB,MAAI;AACF,UAAM,UAAU,MAAM,YAAY,CAAC,IAAI,GAAG,GAAG;AAE7C,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,IAAI;AAAA,QACR;AAAA,MAKF;AAAA,IACF;AAGA,UAAM,SAAmB,CAAC;AAE1B,eAAW,UAAU,SAAS;AAC5B,YAAM,OAAO,OAAO,QAAQ,OAAO,YAAY;AAG/C,UAAI,CAAC,OAAO,aAAa;AACvB,eAAO,KAAK,GAAG,IAAI,mCAAmC;AAAA,MACxD;AAGA,UAAI,OAAO,iBAAiB;AAC1B,YAAI;AACF,+BAAqB,OAAO,iBAAiB,IAAI;AAAA,QACnD,SAAS,aAAa;AACpB,gBAAM,UAAU,uBAAuB,QAAQ,YAAY,UAAU,OAAO,WAAW;AACvF,iBAAO,KAAK,GAAG,IAAI,KAAK,OAAO,EAAE;AAAA,QACnC;AAAA,MACF;AAGA,UAAI,OAAO,OAAO,YAAY,YAAY;AACxC,eAAO,KAAK,GAAG,IAAI,+BAA+B;AAAA,MACpD;AAAA,IACF;AAEA,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,IAAI,MAAM;AAAA,EAAuB,OAAO,IAAI,CAAC,MAAM,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,IACnF;AAGA,QAAI,OAAO,MAAMA,OAAM,MAAM,KAAK,oBAAe,CAAC;AAClD,QAAI,OAAO,MAAMA,OAAM,KAAK,kBAAkB,CAAC;AAE/C,eAAW,UAAU,SAAS;AAC5B,YAAM,OAAO,OAAO,QAAQ,OAAO,YAAY;AAC/C,YAAM,aAAa,OAAO,kBACtBA,OAAM,KAAK,eAAe,IAC1BA,OAAM,IAAI,aAAa;AAC3B,UAAI,OAAO,MAAM,KAAKA,OAAM,KAAK,IAAI,CAAC,IAAI,UAAU;AAAA,CAAI;AACxD,UAAI,OAAO,MAAMA,OAAM,IAAI,OAAO,OAAO,WAAW;AAAA,CAAI,CAAC;AAAA,IAC3D;AAEA,QAAI,OAAO,MAAM,IAAI;AAAA,EACvB,SAAS,OAAO;AACd,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,QAAI,OAAO,MAAMA,OAAM,IAAI,KAAK;AAAA;AAAA;AAAA,CAAiB,CAAC;AAClD,QAAI,OAAO,MAAM,GAAG,OAAO;AAAA;AAAA,CAAM;AACjC,QAAI,YAAY,CAAC;AAAA,EACnB;AACF;AAQO,SAAS,sBAAsB,SAAkB,KAA2B;AACjF,QAAM,YAAY,QACf,QAAQ,QAAQ,EAChB,YAAY,kDAAkD;AAGjE,YACG,QAAQ,YAAY,EACpB,YAAY,0DAA0D,EACtE,OAAO,mBAAmB,2DAA2D,EACrF,OAAO,UAAU,sCAAsC,EACvD,OAAO,SAAS,gDAAgD,EAChE;AAAA,IAAO,CAAC,MAAc,YACrB,cAAc,MAAM,iBAAiB,MAAM,SAAS,GAAG,GAAG,GAAG;AAAA,EAC/D;AAGF,YACG,QAAQ,aAAa,EACrB,YAAY,mDAAmD,EAC/D,OAAO,mBAAmB,2DAA2D,EACrF,OAAO,UAAU,0CAA0C,EAC3D;AAAA,IAAO,CAAC,MAAc,YACrB,cAAc,MAAM,kBAAkB,MAAM,SAAS,GAAG,GAAG,GAAG;AAAA,EAChE;AAGF,YACG,QAAQ,iBAAiB,EACzB,YAAY,wCAAwC,EACpD,OAAO,CAAC,SAAiB,cAAc,MAAM,sBAAsB,MAAM,GAAG,GAAG,GAAG,CAAC;AACxF;;;AE5dA,SAAS,iBAAAE,sBAAqB;AAY9B,IAAM,sBAAsB;AAsB5B,eAAsB,aACpB,WACA,SACA,KACe;AACf,QAAM,SAAS,MAAM,cAAc,WAAW,GAAG;AACjD,QAAM,SAAS,IAAI,aAAa;AAEhC,QAAM,QAAQ,QAAQ;AACtB,QAAM,IAAI,QAAQ,QAAQ,OAAO,SAAS,QAAQ,OAAO,EAAE,IAAI;AAE/D,QAAM,YAAa,IAAI,OAA8B,UAAU;AAE/D,MAAI,CAAC,QAAQ,SAAS,WAAW;AAC/B,QAAI,OAAO,MAAM,GAAG,cAAc,0BAA0B,KAAK;AAAA,CAAO;AAAA,EAC1E;AAEA,QAAM,SAAS,MAAM,OAAO,MAAM,SAAS;AAAA,IACzC;AAAA,IACA;AAAA,IACA,MAAM,QAAQ;AAAA,IACd,SAAS,QAAQ;AAAA,IACjB;AAAA,IACA,gBAAgB,QAAQ,SAAS,aAAa;AAAA,EAChD,CAAC;AAGD,MAAI,QAAQ,QAAQ;AAElB,UAAM,YAAY,OAAO,OAAO,CAAC;AACjC,QAAI,UAAU,SAAS;AACrB,YAAM,SAAS,OAAO,KAAK,UAAU,SAAS,QAAQ;AACtD,MAAAC,eAAc,QAAQ,QAAQ,MAAM;AACpC,UAAI,CAAC,QAAQ,OAAO;AAClB,YAAI,OAAO,MAAM,GAAG,cAAc,mBAAmB,QAAQ,MAAM;AAAA,CAAI;AAAA,MACzE;AAAA,IACF,WAAW,UAAU,KAAK;AAExB,UAAI,OAAO,MAAM,GAAG,UAAU,GAAG;AAAA,CAAI;AAAA,IACvC;AAAA,EACF,OAAO;AAEL,eAAW,SAAS,OAAO,QAAQ;AACjC,UAAI,MAAM,KAAK;AACb,YAAI,OAAO,MAAM,GAAG,MAAM,GAAG;AAAA,CAAI;AAAA,MACnC,WAAW,MAAM,SAAS;AAExB,YAAI,OAAO,MAAM,MAAM,OAAO;AAAA,MAChC;AAAA,IACF;AAAA,EACF;AAGA,MAAI,CAAC,QAAQ,SAAS,WAAW;AAC/B,UAAM,QAAQ;AAAA,MACZ,GAAG,OAAO,OAAO,MAAM;AAAA,MACvB,SAAS,OAAO,MAAM,IAAI;AAAA,MAC1B,YAAY,OAAO,MAAM,OAAO;AAAA,IAClC;AACA,QAAI,OAAO,SAAS,QAAW;AAC7B,YAAM,KAAK,SAAS,WAAW,OAAO,IAAI,CAAC,EAAE;AAAA,IAC/C;AACA,QAAI,OAAO,MAAM,GAAG,cAAc,IAAI,MAAM,KAAK,KAAK,CAAC;AAAA,CAAI;AAAA,EAC7D;AACF;AASO,SAAS,qBACd,SACA,KACA,QACM;AACN,UACG,QAAQ,SAAS,KAAK,EACtB,YAAY,qCAAqC,EACjD,SAAS,YAAY,oEAAoE,EACzF,OAAO,aAAa,OAAO,oBAAoB,OAAO,QAAQ,SAAS,mBAAmB,EAC1F,OAAO,aAAa,WAAW,oBAAoB,WAAW,QAAQ,IAAI,EAC1E,OAAO,aAAa,cAAc,oBAAoB,cAAc,QAAQ,OAAO,EACnF,OAAO,aAAa,YAAY,oBAAoB,YAAY,QAAQ,OAAO,SAAS,CAAC,EACzF,OAAO,aAAa,aAAa,oBAAoB,aAAa,QAAQ,MAAM,EAChF,OAAO,aAAa,OAAO,oBAAoB,OAAO,QAAQ,SAAS,KAAK,EAC5E;AAAA,IAAO,CAAC,QAAQ,YACf,cAAc,MAAM,aAAa,QAAQ,SAAgC,GAAG,GAAG,GAAG;AAAA,EACpF;AACJ;;;ACzHA;AAJA,OAAOC,YAAW;AAmBlB,eAAe,oBACb,SACA,KACe;AACf,QAAM,SAAS,IAAI,aAAa;AAIhC,QAAM,WAAW,QAAQ,OAAO,QAAQ,QAAS,CAAC,QAAQ,SAAS,CAAC,QAAQ;AAC5E,QAAM,YAAY,QAAQ,OAAO,QAAQ;AACzC,QAAM,aAAa,QAAQ,OAAO,QAAQ;AAG1C,QAAM,aAAa,WAAW,OAAO,cAAc,WAAW,QAAQ,QAAQ,IAAI,CAAC;AACnF,QAAM,cAAc,YAChB,OAAO,MAAM,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,YAAY,EAAE,aAAa,QAAQ,QAAQ,IAC5F,CAAC;AACL,QAAM,eAAe,aACjB,OAAO,OAAO,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,YAAY,EAAE,aAAa,QAAQ,QAAQ,IAC7F,CAAC;AAEL,MAAI,QAAQ,WAAW,QAAQ;AAC7B,eAAW,YAAY,aAAa,cAAc,IAAI,MAAM;AAAA,EAC9D,OAAO;AACL,oBAAgB,YAAY,aAAa,cAAc,QAAQ,WAAW,OAAO,IAAI,MAAM;AAAA,EAC7F;AACF;AAKA,SAAS,gBACP,YACA,aACA,cACA,SACA,QACM;AACN,QAAM,eAAe,WAAW,SAAS,KAAK,YAAY,SAAS,KAAK,aAAa,SAAS;AAE9F,MAAI,CAAC,cAAc;AACjB,WAAO,MAAMC,OAAM,OAAO,wDAAwD,CAAC;AACnF;AAAA,EACF;AAEA,SAAO,MAAMA,OAAM,KAAK,KAAK,sBAAsB,CAAC;AACpD,SAAO,MAAMA,OAAM,KAAK,IAAI,OAAO,EAAE,CAAC,IAAI,MAAM;AAGhD,MAAI,WAAW,SAAS,GAAG;AACzB,oBAAgB,YAAY,SAAS,MAAM;AAAA,EAC7C;AAGA,MAAI,YAAY,SAAS,GAAG;AAC1B,qBAAiB,aAAa,SAAS,MAAM;AAAA,EAC/C;AAGA,MAAI,aAAa,SAAS,GAAG;AAC3B,sBAAkB,cAAc,SAAS,MAAM;AAAA,EACjD;AAGA,MAAI,WAAW,SAAS,GAAG;AACzB,WAAO,MAAMA,OAAM,KAAK,QAAQ,mBAAmB,CAAC;AACpD,WAAO,MAAMA,OAAM,IAAI,SAAI,OAAO,EAAE,CAAC,IAAI,IAAI;AAE7C,UAAM,YAAY,OAAO,QAAQ,aAAa,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;AACvF,eAAW,CAAC,UAAU,QAAQ,KAAK,WAAW;AAC5C,aAAO;AAAA,QACLA,OAAM,KAAK,KAAK,SAAS,OAAO,EAAE,CAAC,EAAE,IAAIA,OAAM,IAAI,UAAK,IAAIA,OAAM,MAAM,QAAQ,IAAI;AAAA,MACtF;AAAA,IACF;AACA,WAAO,MAAM,IAAI;AAAA,EACnB;AACF;AAKA,SAAS,gBACP,QACA,SACA,QACM;AAEN,QAAM,UAAU,oBAAI,IAAyB;AAC7C,aAAW,SAAS,QAAQ;AAC1B,UAAM,WAAW,MAAM;AACvB,QAAI,CAAC,QAAQ,IAAI,QAAQ,GAAG;AAC1B,cAAQ,IAAI,UAAU,CAAC,CAAC;AAAA,IAC1B;AACA,YAAQ,IAAI,QAAQ,EAAG,KAAK,KAAK;AAAA,EACnC;AAEA,SAAO,MAAMA,OAAM,KAAK,KAAK,6BAAsB,CAAC;AACpD,SAAO,MAAMA,OAAM,IAAI,SAAI,OAAO,EAAE,CAAC,IAAI,MAAM;AAG/C,QAAM,YAAY,MAAM,KAAK,QAAQ,KAAK,CAAC,EAAE,KAAK;AAClD,aAAW,YAAY,WAAW;AAChC,UAAM,iBAAiB,QAAQ,IAAI,QAAQ;AAC3C,UAAM,eAAe,SAAS,OAAO,CAAC,EAAE,YAAY,IAAI,SAAS,MAAM,CAAC;AAExE,WAAO,MAAMA,OAAM,KAAK,OAAO,GAAG,YAAY;AAAA,CAAI,CAAC;AAEnD,QAAI,SAAS;AACX,yBAAmB,gBAAgB,MAAM;AAAA,IAC3C,OAAO;AACL,yBAAmB,gBAAgB,MAAM;AAAA,IAC3C;AAEA,WAAO,MAAM,IAAI;AAAA,EACnB;AACF;AAEA,SAAS,mBAAmB,QAAqB,QAAqC;AAEpF,QAAM,UAAU;AAChB,QAAM,YAAY;AAClB,QAAM,eAAe;AACrB,QAAM,aAAa;AACnB,QAAM,cAAc;AAGpB,SAAO;AAAA,IACLA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,eAAe,aAAa,cAAc,CAAC,CAAC,IAAI;AAAA,EAC7F;AACA,SAAO;AAAA,IACLA,OAAM;AAAA,MACJ,WAAW,OAAO,OAAO,IACvB,OACA,eAAe,OAAO,SAAS,IAC/B,OACA,UAAU,OAAO,YAAY,IAC7B,OACA,QAAQ,OAAO,UAAU,IACzB,OACA,SAAS,OAAO,WAAW;AAAA,IAC/B,IAAI;AAAA,EACN;AACA,SAAO;AAAA,IACLA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,eAAe,aAAa,cAAc,CAAC,CAAC,IAAI;AAAA,EAC7F;AAGA,aAAW,SAAS,QAAQ;AAC1B,UAAM,mBAAmBC,cAAa,MAAM,aAAa;AACzD,UAAM,aAAa,IAAI,MAAM,QAAQ,MAAM,QAAQ,CAAC,CAAC;AACrD,UAAM,cAAc,IAAI,MAAM,QAAQ,OAAO,QAAQ,CAAC,CAAC;AAEvD,WAAO;AAAA,MACLD,OAAM,MAAM,MAAM,QAAQ,OAAO,OAAO,CAAC,IACvC,OACAA,OAAM,MAAM,MAAM,YAAY,OAAO,SAAS,CAAC,IAC/C,OACAA,OAAM,OAAO,iBAAiB,OAAO,YAAY,CAAC,IAClD,OACAA,OAAM,KAAK,WAAW,OAAO,UAAU,CAAC,IACxC,OACAA,OAAM,KAAK,YAAY,OAAO,WAAW,CAAC,IAC1C;AAAA,IACJ;AAAA,EACF;AAEA,SAAO;AAAA,IACLA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,eAAe,aAAa,cAAc,CAAC,CAAC,IAAI;AAAA,EAC7F;AACA,SAAO,MAAMA,OAAM,IAAI;AAAA,CAAgC,CAAC;AAC1D;AAEA,SAAS,mBAAmB,QAAqB,QAAqC;AACpF,aAAW,SAAS,QAAQ;AAC1B,WAAO,MAAMA,OAAM,KAAK,MAAM;AAAA,IAAO,MAAM,OAAO;AAAA,CAAI,CAAC;AACvD,WAAO,MAAMA,OAAM,IAAI,OAAO,SAAI,OAAO,EAAE,CAAC,IAAI,IAAI;AACpD,WAAO,MAAM,KAAKA,OAAM,IAAI,OAAO,CAAC,YAAYA,OAAM,MAAM,MAAM,WAAW,CAAC;AAAA,CAAI;AAClF,WAAO;AAAA,MACL,KAAKA,OAAM,IAAI,UAAU,CAAC,SAASA,OAAM,OAAOC,cAAa,MAAM,aAAa,CAAC,CAAC;AAAA;AAAA,IACpF;AACA,WAAO;AAAA,MACL,KAAKD,OAAM,IAAI,aAAa,CAAC,MAAMA,OAAM,OAAOC,cAAa,MAAM,eAAe,CAAC,CAAC;AAAA;AAAA,IACtF;AACA,WAAO;AAAA,MACL,KAAKD,OAAM,IAAI,UAAU,CAAC,SAASA,OAAM,KAAK,IAAI,MAAM,QAAQ,MAAM,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAIA,OAAM,IAAI,GAAG,CAAC,IAAIA,OAAM,KAAK,IAAI,MAAM,QAAQ,OAAO,QAAQ,CAAC,CAAC,SAAS,CAAC,IAAIA,OAAM,IAAI,iBAAiB,CAAC;AAAA;AAAA,IACzM;AAEA,QAAI,MAAM,QAAQ,gBAAgB,QAAW;AAC3C,aAAO;AAAA,QACL,KAAKA,OAAM,IAAI,eAAe,CAAC,IAAIA,OAAM,KAAK,IAAI,MAAM,QAAQ,YAAY,QAAQ,CAAC,CAAC,gBAAgB,CAAC;AAAA;AAAA,MACzG;AAAA,IACF;AAEA,QAAI,MAAM,iBAAiB;AACzB,aAAO,MAAM,KAAKA,OAAM,IAAI,YAAY,CAAC,OAAO,MAAM,eAAe;AAAA,CAAI;AAAA,IAC3E;AAGA,UAAM,WAAqB,CAAC;AAC5B,QAAI,MAAM,SAAS,UAAW,UAAS,KAAK,WAAW;AACvD,QAAI,MAAM,SAAS,gBAAiB,UAAS,KAAK,kBAAkB;AACpE,QAAI,MAAM,SAAS,OAAQ,UAAS,KAAK,QAAQ;AACjD,QAAI,MAAM,SAAS,UAAW,UAAS,KAAK,WAAW;AACvD,QAAI,MAAM,SAAS,kBAAmB,UAAS,KAAK,oBAAoB;AACxE,QAAI,MAAM,SAAS,WAAY,UAAS,KAAK,aAAa;AAE1D,QAAI,SAAS,SAAS,GAAG;AACvB,aAAO,MAAM,KAAKA,OAAM,IAAI,WAAW,CAAC,QAAQA,OAAM,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC;AAAA,CAAI;AAAA,IACrF;AAGA,QAAI,MAAM,UAAU;AAClB,UAAI,MAAM,SAAS,QAAQ;AACzB,eAAO,MAAM,KAAKA,OAAM,IAAI,SAAS,CAAC,UAAU,MAAM,SAAS,MAAM;AAAA,CAAI;AAAA,MAC3E;AACA,UAAI,MAAM,SAAS,aAAa;AAC9B,eAAO,MAAM,KAAKA,OAAM,IAAI,WAAW,CAAC,QAAQ,MAAM,SAAS,WAAW;AAAA,CAAI;AAAA,MAChF;AACA,UAAI,MAAM,SAAS,OAAO;AACxB,eAAO,MAAM,KAAKA,OAAM,IAAI,QAAQ,CAAC,WAAWA,OAAM,OAAO,MAAM,SAAS,KAAK,CAAC;AAAA,CAAI;AAAA,MACxF;AAAA,IACF;AAAA,EACF;AACA,SAAO,MAAM,IAAI;AACnB;AAKA,SAAS,iBACP,QACA,SACA,QACM;AACN,SAAO,MAAMA,OAAM,KAAK,MAAM,qCAA8B,CAAC;AAC7D,SAAO,MAAMA,OAAM,IAAI,SAAI,OAAO,EAAE,CAAC,IAAI,MAAM;AAG/C,QAAM,UAAU,oBAAI,IAA8B;AAClD,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,QAAQ,IAAI,MAAM,QAAQ,GAAG;AAChC,cAAQ,IAAI,MAAM,UAAU,CAAC,CAAC;AAAA,IAChC;AACA,YAAQ,IAAI,MAAM,QAAQ,EAAG,KAAK,KAAK;AAAA,EACzC;AAEA,aAAW,CAAC,UAAU,cAAc,KAAK,MAAM,KAAK,QAAQ,QAAQ,CAAC,EAAE,KAAK,GAAG;AAC7E,UAAM,eAAe,SAAS,OAAO,CAAC,EAAE,YAAY,IAAI,SAAS,MAAM,CAAC;AACxE,WAAO,MAAMA,OAAM,KAAK,OAAO,GAAG,YAAY;AAAA,CAAI,CAAC;AAEnD,QAAI,SAAS;AACX,iBAAW,SAAS,gBAAgB;AAClC,eAAO,MAAMA,OAAM,KAAK,MAAM;AAAA,IAAO,MAAM,OAAO;AAAA,CAAI,CAAC;AACvD,eAAO,MAAMA,OAAM,IAAI,OAAO,SAAI,OAAO,EAAE,CAAC,IAAI,IAAI;AACpD,eAAO,MAAM,KAAKA,OAAM,IAAI,OAAO,CAAC,SAASA,OAAM,MAAM,MAAM,WAAW,CAAC;AAAA,CAAI;AAC/E,eAAO;AAAA,UACL,KAAKA,OAAM,IAAI,QAAQ,CAAC,QAAQA,OAAM,OAAO,MAAM,eAAe,KAAK,IAAI,CAAC,CAAC;AAAA;AAAA,QAC/E;AACA,YAAI,MAAM,oBAAoB;AAC5B,iBAAO;AAAA,YACL,KAAKA,OAAM,IAAI,YAAY,CAAC,IAAIA,OAAM,OAAO,MAAM,mBAAmB,KAAK,IAAI,CAAC,CAAC;AAAA;AAAA,UACnF;AAAA,QACF;AACA,eAAO,MAAM,KAAKA,OAAM,IAAI,aAAa,CAAC,IAAIA,OAAM,OAAO,MAAM,UAAU,SAAS,CAAC,CAAC;AAAA,CAAI;AAC1F,eAAO,MAAM,KAAKA,OAAM,IAAI,UAAU,CAAC,MAAMA,OAAM,KAAK,iBAAiB,KAAK,CAAC,CAAC;AAAA,CAAI;AACpF,YAAI,MAAM,UAAU;AAClB,gBAAM,WAAqB,CAAC;AAC5B,cAAI,MAAM,SAAS,cAAe,UAAS,KAAK,gBAAgB;AAChE,cAAI,MAAM,SAAS,aAAc,UAAS,KAAK,cAAc;AAC7D,cAAI,MAAM,SAAS,eAAgB,UAAS,KAAK,gBAAgB;AACjE,cAAI,SAAS,SAAS,GAAG;AACvB,mBAAO,MAAM,KAAKA,OAAM,IAAI,WAAW,CAAC,KAAKA,OAAM,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC;AAAA,CAAI;AAAA,UAClF;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,UAAU;AAChB,YAAM,YAAY;AAClB,YAAM,aAAa;AACnB,YAAM,aAAa;AAEnB,aAAO,MAAMA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,aAAa,aAAa,CAAC,CAAC,IAAI,IAAI;AAC5F,aAAO;AAAA,QACLA,OAAM;AAAA,UACJ,WAAW,OAAO,OAAO,IACvB,OACA,eAAe,OAAO,SAAS,IAC/B,OACA,QAAQ,OAAO,UAAU,IACzB,OACA,QAAQ,OAAO,UAAU;AAAA,QAC7B,IAAI;AAAA,MACN;AACA,aAAO,MAAMA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,aAAa,aAAa,CAAC,CAAC,IAAI,IAAI;AAE5F,iBAAW,SAAS,gBAAgB;AAClC,cAAM,QACJ,MAAM,eAAe,SAAS,IAC1B,MAAM,eAAe,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,IAAI,QAC9C,MAAM,eAAe,KAAK,IAAI;AAEpC,eAAO;AAAA,UACLA,OAAM,MAAM,MAAM,QAAQ,OAAO,OAAO,CAAC,IACvC,OACAA,OAAM,MAAM,MAAM,YAAY,UAAU,GAAG,YAAY,CAAC,EAAE,OAAO,SAAS,CAAC,IAC3E,OACAA,OAAM,OAAO,MAAM,OAAO,UAAU,CAAC,IACrC,OACAA,OAAM,KAAK,iBAAiB,KAAK,EAAE,OAAO,UAAU,CAAC,IACrD;AAAA,QACJ;AAAA,MACF;AACA,aAAO,MAAMA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,aAAa,aAAa,CAAC,CAAC,IAAI,IAAI;AAAA,IAC9F;AAEA,WAAO,MAAM,IAAI;AAAA,EACnB;AACF;AAKA,SAAS,kBACP,QACA,SACA,QACM;AACN,SAAO,MAAMA,OAAM,KAAK,QAAQ,iCAA0B,CAAC;AAC3D,SAAO,MAAMA,OAAM,IAAI,SAAI,OAAO,EAAE,CAAC,IAAI,MAAM;AAG/C,QAAM,UAAU,oBAAI,IAA+B;AACnD,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,QAAQ,IAAI,MAAM,QAAQ,GAAG;AAChC,cAAQ,IAAI,MAAM,UAAU,CAAC,CAAC;AAAA,IAChC;AACA,YAAQ,IAAI,MAAM,QAAQ,EAAG,KAAK,KAAK;AAAA,EACzC;AAEA,aAAW,CAAC,UAAU,cAAc,KAAK,MAAM,KAAK,QAAQ,QAAQ,CAAC,EAAE,KAAK,GAAG;AAC7E,UAAM,eAAe,SAAS,OAAO,CAAC,EAAE,YAAY,IAAI,SAAS,MAAM,CAAC;AACxE,WAAO,MAAMA,OAAM,KAAK,OAAO,GAAG,YAAY;AAAA,CAAI,CAAC;AAEnD,QAAI,SAAS;AACX,iBAAW,SAAS,gBAAgB;AAClC,eAAO,MAAMA,OAAM,KAAK,MAAM;AAAA,IAAO,MAAM,OAAO;AAAA,CAAI,CAAC;AACvD,eAAO,MAAMA,OAAM,IAAI,OAAO,SAAI,OAAO,EAAE,CAAC,IAAI,IAAI;AACpD,eAAO,MAAM,KAAKA,OAAM,IAAI,OAAO,CAAC,OAAOA,OAAM,MAAM,MAAM,WAAW,CAAC;AAAA,CAAI;AAC7E,eAAO;AAAA,UACL,KAAKA,OAAM,IAAI,SAAS,CAAC,KAAKA,OAAM,OAAO,MAAM,OAAO,OAAO,SAAS,CAAC,CAAC;AAAA;AAAA,QAC5E;AACA,YAAI,MAAM,OAAO,UAAU,GAAG;AAC5B,iBAAO,MAAM,eAAeA,OAAM,IAAI,MAAM,OAAO,KAAK,IAAI,CAAC,CAAC;AAAA,CAAI;AAAA,QACpE,OAAO;AACL,iBAAO,MAAM,eAAeA,OAAM,IAAI,MAAM,OAAO,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,IAAI,KAAK,CAAC;AAAA,CAAI;AAAA,QACxF;AACA,eAAO,MAAM,KAAKA,OAAM,IAAI,UAAU,CAAC,IAAIA,OAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,CAAC,CAAC;AAAA,CAAI;AACrF,eAAO;AAAA,UACL,KAAKA,OAAM,IAAI,YAAY,CAAC,IAAIA,OAAM,OAAO,MAAM,eAAe,SAAS,CAAC,CAAC;AAAA;AAAA,QAC/E;AACA,eAAO,MAAM,KAAKA,OAAM,IAAI,UAAU,CAAC,IAAIA,OAAM,KAAK,kBAAkB,KAAK,CAAC,CAAC;AAAA,CAAI;AACnF,YAAI,MAAM,UAAU;AAClB,gBAAM,WAAqB,CAAC;AAC5B,cAAI,MAAM,SAAS,aAAc,UAAS,KAAK,eAAe;AAC9D,cAAI,MAAM,SAAS,kBAAmB,UAAS,KAAK,oBAAoB;AACxE,cAAI,MAAM,SAAS,UAAW,UAAS,KAAK,GAAG,MAAM,SAAS,SAAS,YAAY;AACnF,cAAI,SAAS,SAAS,GAAG;AACvB,mBAAO,MAAM,KAAKA,OAAM,IAAI,WAAW,CAAC,IAAIA,OAAM,KAAK,SAAS,KAAK,IAAI,CAAC,CAAC;AAAA,CAAI;AAAA,UACjF;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,UAAU;AAChB,YAAM,YAAY;AAClB,YAAM,cAAc;AACpB,YAAM,aAAa;AAEnB,aAAO;AAAA,QACLA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,cAAc,aAAa,CAAC,CAAC,IAAI;AAAA,MAC9E;AACA,aAAO;AAAA,QACLA,OAAM;AAAA,UACJ,WAAW,OAAO,OAAO,IACvB,OACA,eAAe,OAAO,SAAS,IAC/B,OACA,SAAS,OAAO,WAAW,IAC3B,OACA,QAAQ,OAAO,UAAU;AAAA,QAC7B,IAAI;AAAA,MACN;AACA,aAAO;AAAA,QACLA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,cAAc,aAAa,CAAC,CAAC,IAAI;AAAA,MAC9E;AAEA,iBAAW,SAAS,gBAAgB;AAClC,eAAO;AAAA,UACLA,OAAM,MAAM,MAAM,QAAQ,OAAO,OAAO,CAAC,IACvC,OACAA,OAAM,MAAM,MAAM,YAAY,UAAU,GAAG,YAAY,CAAC,EAAE,OAAO,SAAS,CAAC,IAC3E,OACAA,OAAM,OAAO,GAAG,MAAM,OAAO,MAAM,UAAU,OAAO,WAAW,CAAC,IAChE,OACAA,OAAM,KAAK,kBAAkB,KAAK,EAAE,OAAO,UAAU,CAAC,IACtD;AAAA,QACJ;AAAA,MACF;AACA,aAAO;AAAA,QACLA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,cAAc,aAAa,CAAC,CAAC,IAAI;AAAA,MAC9E;AAAA,IACF;AAEA,WAAO,MAAM,IAAI;AAAA,EACnB;AACF;AAKA,SAAS,iBAAiB,OAA+B;AACvD,MAAI,MAAM,QAAQ,aAAa,QAAW;AACxC,WAAO,IAAI,MAAM,QAAQ,SAAS,QAAQ,CAAC,CAAC;AAAA,EAC9C;AACA,MAAI,MAAM,QAAQ,QAAQ;AACxB,UAAM,SAAS,OAAO,OAAO,MAAM,QAAQ,MAAM;AACjD,UAAM,WAAW,KAAK;AAAA,MACpB,GAAG,OAAO,QAAQ,CAAC,MAAO,OAAO,MAAM,WAAW,CAAC,CAAC,IAAI,OAAO,OAAO,CAAC,CAAE;AAAA,IAC3E;AACA,UAAM,WAAW,KAAK;AAAA,MACpB,GAAG,OAAO,QAAQ,CAAC,MAAO,OAAO,MAAM,WAAW,CAAC,CAAC,IAAI,OAAO,OAAO,CAAC,CAAE;AAAA,IAC3E;AACA,QAAI,aAAa,UAAU;AACzB,aAAO,IAAI,SAAS,QAAQ,CAAC,CAAC;AAAA,IAChC;AACA,WAAO,IAAI,SAAS,QAAQ,CAAC,CAAC,IAAI,SAAS,QAAQ,CAAC,CAAC;AAAA,EACvD;AACA,SAAO;AACT;AAKA,SAAS,kBAAkB,OAAgC;AACzD,MAAI,MAAM,QAAQ,iBAAiB,QAAW;AAC5C,UAAM,aAAa,MAAM,QAAQ,eAAe;AAChD,WAAO,IAAI,WAAW,QAAQ,CAAC,CAAC;AAAA,EAClC;AACA,MAAI,MAAM,QAAQ,cAAc,QAAW;AACzC,WAAO,KAAK,MAAM,QAAQ,UAAU,QAAQ,CAAC,CAAC;AAAA,EAChD;AACA,SAAO;AACT;AAEA,SAAS,WACP,YACA,aACA,cACA,QACM;AACN,QAAM,SAAkC,CAAC;AAEzC,MAAI,WAAW,SAAS,GAAG;AACzB,WAAO,aAAa,WAAW,IAAI,CAAC,WAAW;AAAA,MAC7C,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM;AAAA,MACf,aAAa,MAAM;AAAA,MACnB,eAAe,MAAM;AAAA,MACrB,iBAAiB,MAAM;AAAA,MACvB,SAAS;AAAA,QACP,OAAO,MAAM,QAAQ;AAAA,QACrB,QAAQ,MAAM,QAAQ;AAAA,QACtB,aAAa,MAAM,QAAQ;AAAA,QAC3B,UAAU;AAAA,QACV,KAAK;AAAA,MACP;AAAA,MACA,iBAAiB,MAAM;AAAA,MACvB,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,IAClB,EAAE;AACF,WAAO,YAAY;AAAA,EACrB;AAEA,MAAI,YAAY,SAAS,GAAG;AAC1B,WAAO,cAAc,YAAY,IAAI,CAAC,WAAW;AAAA,MAC/C,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM;AAAA,MACf,aAAa,MAAM;AAAA,MACnB,gBAAgB,MAAM;AAAA,MACtB,oBAAoB,MAAM;AAAA,MAC1B,WAAW,MAAM;AAAA,MACjB,SAAS,MAAM;AAAA,MACf,UAAU,MAAM;AAAA,IAClB,EAAE;AAAA,EACJ;AAEA,MAAI,aAAa,SAAS,GAAG;AAC3B,WAAO,eAAe,aAAa,IAAI,CAAC,WAAW;AAAA,MACjD,UAAU,MAAM;AAAA,MAChB,SAAS,MAAM;AAAA,MACf,aAAa,MAAM;AAAA,MACnB,QAAQ,MAAM;AAAA,MACd,SAAS,MAAM;AAAA,MACf,gBAAgB,MAAM;AAAA,MACtB,SAAS,MAAM;AAAA,MACf,UAAU,MAAM;AAAA,IAClB,EAAE;AAAA,EACJ;AAEA,SAAO,MAAM,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AACrD;AAEA,SAASC,cAAa,OAAuB;AAC3C,MAAI,SAAS,KAAW;AACtB,WAAO,IAAI,QAAQ,KAAW,QAAQ,CAAC,CAAC;AAAA,EAC1C,WAAW,SAAS,KAAO;AACzB,WAAO,IAAI,QAAQ,KAAO,QAAQ,CAAC,CAAC;AAAA,EACtC,OAAO;AACL,WAAO,GAAG,KAAK;AAAA,EACjB;AACF;AAEO,SAAS,sBAAsB,SAAkB,KAA2B;AACjF,UACG,QAAQ,SAAS,MAAM,EACvB,YAAY,sDAAsD,EAClE,OAAO,qBAAqB,gDAAgD,EAC5E,OAAO,qBAAqB,gCAAgC,OAAO,EACnE,OAAO,aAAa,mCAAmC,KAAK,EAC5D,OAAO,UAAU,qDAAqD,EACtE,OAAO,WAAW,8BAA8B,EAChD,OAAO,YAAY,wBAAwB,EAC3C,OAAO,SAAS,4CAA4C,EAC5D;AAAA,IAAO,CAAC,YACP,cAAc,MAAM,oBAAoB,SAAiC,GAAG,GAAG,GAAG;AAAA,EACpF;AACJ;;;AC1iBA,SAAS,iBAAAC,sBAAqB;AAY9B,IAAM,uBAAuB;AAK7B,IAAM,gBAAgB;AAsBtB,eAAsB,cACpB,SACA,SACA,KACe;AACf,QAAMC,QAAO,MAAM,cAAc,SAAS,GAAG;AAC7C,QAAM,SAAS,IAAI,aAAa;AAEhC,QAAM,QAAQ,QAAQ;AACtB,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,QAAQ,QAAQ,QAAQ,OAAO,WAAW,QAAQ,KAAK,IAAI;AAEjE,QAAM,YAAa,IAAI,OAA8B,UAAU;AAE/D,MAAI,CAAC,QAAQ,SAAS,WAAW;AAC/B,QAAI,OAAO,MAAM,GAAG,cAAc,2BAA2B,KAAK,YAAY,KAAK;AAAA,CAAQ;AAAA,EAC7F;AAEA,QAAM,SAAS,MAAM,OAAO,OAAO,SAAS;AAAA,IAC1C;AAAA,IACA,OAAOA;AAAA,IACP;AAAA,IACA,gBAAgB,QAAQ;AAAA,IACxB;AAAA,EACF,CAAC;AAGD,QAAM,cAAc,OAAO,KAAK,OAAO,KAAK;AAG5C,MAAI,QAAQ,QAAQ;AAElB,IAAAC,eAAc,QAAQ,QAAQ,WAAW;AACzC,QAAI,CAAC,QAAQ,OAAO;AAClB,UAAI,OAAO,MAAM,GAAG,cAAc,mBAAmB,QAAQ,MAAM;AAAA,CAAI;AAAA,IACzE;AAAA,EACF,OAAO;AAEL,QAAI,OAAO,MAAM,WAAW;AAAA,EAC9B;AAGA,MAAI,CAAC,QAAQ,SAAS,WAAW;AAC/B,UAAM,QAAQ,CAAC,GAAG,OAAO,MAAM,cAAc,eAAe,WAAW,OAAO,MAAM,EAAE;AACtF,QAAI,OAAO,SAAS,QAAW;AAC7B,YAAM,KAAK,SAAS,WAAW,OAAO,IAAI,CAAC,EAAE;AAAA,IAC/C;AACA,QAAI,OAAO,MAAM,GAAG,cAAc,IAAI,MAAM,KAAK,KAAK,CAAC;AAAA,CAAI;AAAA,EAC7D;AACF;AASO,SAAS,sBACd,SACA,KACA,QACM;AACN,UACG,QAAQ,SAAS,MAAM,EACvB,YAAY,kCAAkC,EAC9C,SAAS,UAAU,sEAAsE,EACzF,OAAO,aAAa,OAAO,oBAAoB,OAAO,QAAQ,SAAS,oBAAoB,EAC3F,OAAO,aAAa,OAAO,oBAAoB,OAAO,QAAQ,SAAS,aAAa,EACpF,OAAO,aAAa,cAAc,oBAAoB,cAAc,QAAQ,MAAM,EAClF,OAAO,aAAa,aAAa,oBAAoB,aAAa,QAAQ,OAAO,SAAS,CAAC,EAC3F,OAAO,aAAa,cAAc,oBAAoB,cAAc,QAAQ,MAAM,EAClF,OAAO,aAAa,OAAO,oBAAoB,OAAO,QAAQ,SAAS,KAAK,EAC5E;AAAA,IAAO,CAACD,OAAM,YACb,cAAc,MAAM,cAAcA,OAAM,SAAiC,GAAG,GAAG,GAAG;AAAA,EACpF;AACJ;;;ACtGA;AA2BA,eAAsB,cACpB,WACA,SACA,KACe;AACf,QAAM,SAAS,IAAI,aAAa;AAChC,QAAM,QAAQ,aAAa,QAAQ,KAAK;AAGxC,QAAM,cAAc,MAAM,eAAe,SAAS;AAGlD,QAAM,SAAS,QAAQ,UAAU;AAEjC,QAAM,YAAa,IAAI,OAA8B,UAAU;AAE/D,MAAI,CAAC,QAAQ,SAAS,WAAW;AAC/B,QAAI,OAAO,MAAM,GAAG,cAAc,yBAAyB,KAAK;AAAA,CAAO;AAAA,EACzE;AAGA,QAAM,SAAS,MAAM,OAAO,OAAO,QAAQ;AAAA,IACzC;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA,WAAW,QAAQ;AAAA,EACrB,CAAC;AAGD,MAAI,OAAO,MAAM,MAAM;AACvB,MAAI,OAAO,MAAM,IAAI;AACvB;AAQO,SAAS,sBAAsB,SAAkB,KAA2B;AACjF,UACG,QAAQ,SAAS,UAAU,QAAQ,EACnC,YAAY,8CAA8C,EAC1D,SAAS,WAAW,+BAA+B,EACnD;AAAA,IACC,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB;AAAA;AAAA,EACF,EACC,OAAO,yBAAyB,wDAAwD,EACxF;AAAA,IACC,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,oBAAoB,EAAE,OAAO,cAAc,SAAS,MAAM,KAAK,EAAE,CAAC;AAAA,EACpE,EACC,OAAO,aAAa,OAAO,oBAAoB,KAAK,EACpD;AAAA,IAAO,CAAC,WAAmB,YAC1B,cAAc,MAAM,cAAc,WAAW,SAAS,GAAG,GAAG,GAAG;AAAA,EACjE;AACJ;;;AxClEA,SAAS,cAAc,OAA4B;AACjD,QAAM,aAAa,MAAM,YAAY;AACrC,MAAI,CAAC,WAAW,SAAS,UAAU,GAAG;AACpC,UAAM,IAAIE,sBAAqB,6BAA6B,WAAW,KAAK,IAAI,CAAC,EAAE;AAAA,EACrF;AACA,SAAO;AACT;AAkBO,SAAS,cAAc,KAAqB,QAA6B;AAC9E,QAAM,UAAU,IAAI,QAAQ;AAE5B,UACG,KAAK,QAAQ,EACb,YAAY,eAAe,EAC3B,QAAQ,gBAAY,OAAO,EAC3B,OAAO,aAAa,UAAU,oBAAoB,UAAU,aAAa,EACzE,OAAO,aAAa,SAAS,oBAAoB,OAAO,EACxD,OAAO,aAAa,UAAU,oBAAoB,QAAQ,EAC1D,gBAAgB;AAAA,IACf,UAAU,CAAC,QAAQ,IAAI,OAAO,MAAM,GAAG;AAAA,IACvC,UAAU,CAAC,QAAQ,IAAI,OAAO,MAAM,GAAG;AAAA,EACzC,CAAC;AAGH,0BAAwB,SAAS,KAAK,QAAQ,QAAQ;AACtD,uBAAqB,SAAS,KAAK,QAAQ,OAAO,QAAQ,SAAS;AACnE,uBAAqB,SAAS,KAAK,QAAQ,KAAK;AAChD,wBAAsB,SAAS,KAAK,QAAQ,MAAM;AAClD,wBAAsB,SAAS,GAAG;AAClC,wBAAsB,SAAS,GAAG;AAClC,wBAAsB,SAAS,GAAG;AAClC,sBAAoB,SAAS,GAAG;AAGhC,MAAI,QAAQ;AACV,UAAM,cAAc,sBAAsB,MAAM;AAChD,eAAW,QAAQ,aAAa;AAC9B,YAAM,YAAY,OAAO,IAAI;AAC7B,4BAAsB,SAAS,MAAM,WAAW,KAAK,OAAO,SAAS;AAAA,IACvE;AAAA,EACF;AAEA,SAAO;AACT;AAkBA,eAAsB,OACpB,YAAqD,CAAC,GACvC;AAEf,QAAM,OACJ,SAAS,aAAa,YAAY,YAC7B,YACD,EAAE,KAAK,UAAqC;AAIlD,QAAM,SAAS,KAAK,WAAW,SAAY,KAAK,SAAS,WAAW;AACpE,QAAM,eAAe,KAAK,OAAO,CAAC;AAGlC,QAAM,YAAY,IAAI,QAAQ;AAC9B,YACG,OAAO,aAAa,UAAU,oBAAoB,UAAU,aAAa,EACzE,OAAO,aAAa,SAAS,oBAAoB,OAAO,EACxD,OAAO,aAAa,UAAU,oBAAoB,QAAQ,EAC1D,mBAAmB,EACnB,qBAAqB,EACrB,WAAW,KAAK;AAEnB,YAAU,MAAM,QAAQ,IAAI;AAC5B,QAAM,aAAa,UAAU,KAAoB;AAIjD,QAAM,eAAgC;AAAA,IACpC,UAAU,WAAW,YAAY,OAAO,SAAS,WAAW;AAAA,IAC5D,SAAS,WAAW,WAAW,OAAO,SAAS,UAAU;AAAA,IACzD,UAAU,WAAW,YAAY,OAAO,SAAS,WAAW;AAAA,EAC9D;AAEA,QAAM,aAAa,yBAAyB,YAAY;AACxD,QAAM,MAAsB;AAAA,IAC1B,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACA,QAAM,UAAU,cAAc,KAAK,MAAM;AACzC,QAAM,QAAQ,WAAW,IAAI,IAAI;AACnC;;;AyCpJA,OAAO,EAAE,MAAM,CAAC,UAAU;AACxB,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAQ,OAAO,MAAM,GAAG,cAAc,WAAW,OAAO;AAAA,CAAI;AAC5D,UAAQ,WAAW;AACrB,CAAC;","names":["InvalidArgumentError","fs","path","pathToFileURL","z","z","fs","path","z","fs","path","z","fs","z","readFile","z","fs","fs","path","z","z","path","fs","z","z","readFile","fs","path","path","fs","path","fs","pathToFileURL","writeFile","chalk","text","elapsedSeconds","termWidth","chalk","line","SPINNER_FRAMES","YELLOW","GREEN","CYAN","MAGENTA","RESET","WHITE","text","resolve","Box","chalk","chalk","Box","Box","resolve","Box","resolve","Box","gadgets","text","existsSync","homedir","join","join","homedir","path","existsSync","chalk","resolve","chalk","chalk","chalk","result","writeFileSync","writeFileSync","chalk","chalk","formatTokens","writeFileSync","text","writeFileSync","InvalidArgumentError"]}