llmist 2.2.0 â 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -9
- package/dist/cli.cjs +11 -4
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +11 -4
- package/dist/cli.js.map +1 -1
- package/package.json +11 -4
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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/approval/manager.ts","../src/cli/approval/context-providers.ts","../src/cli/approval/diff-renderer.ts","../src/cli/builtin-gadgets.ts","../src/cli/gadgets.ts","../src/cli/builtins/filesystem/list-directory.ts","../src/cli/builtins/filesystem/utils.ts","../src/cli/builtins/filesystem/read-file.ts","../src/cli/builtins/filesystem/write-file.ts","../src/cli/builtins/filesystem/edit-file.ts","../src/cli/builtins/run-command.ts","../src/cli/builtins/index.ts","../src/cli/llm-logging.ts","../src/cli/utils.ts","../src/cli/ui/formatters.ts","../src/cli/option-helpers.ts","../src/cli/docker/types.ts","../src/cli/config.ts","../src/cli/templates.ts","../src/cli/docker/docker-config.ts","../src/cli/docker/dockerfile.ts","../src/cli/docker/image-manager.ts","../src/cli/docker/docker-wrapper.ts","../src/cli/complete-command.ts","../src/cli/gadget-command.ts","../src/cli/gadget-prompts.ts","../src/cli/models-command.ts","../src/cli/environment.ts","../src/cli/custom-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} as const;\n\n/** Valid log level names */\nexport const LOG_LEVELS = [\"silly\", \"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"] as const;\nexport type LogLevelName = (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 docker: \"--docker\",\n dockerRo: \"--docker-ro\",\n noDocker: \"--no-docker\",\n dockerDev: \"--docker-dev\",\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: \"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 docker: \"Run agent in a Docker sandbox container for security isolation.\",\n dockerRo: \"Run in Docker with current directory mounted read-only.\",\n noDocker: \"Disable Docker sandboxing (override config).\",\n dockerDev: \"Run in Docker dev mode (mount local source instead of npm install).\",\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 {\n type CLIConfig,\n type CustomCommandConfig,\n getCustomCommandNames,\n loadConfig,\n} from \"./config.js\";\nimport { registerGadgetCommand } from \"./gadget-command.js\";\nimport { registerModelsCommand } from \"./models-command.js\";\nimport { registerCustomCommand } from \"./custom-command.js\";\nimport {\n CLI_DESCRIPTION,\n CLI_NAME,\n LOG_LEVELS,\n type LogLevelName,\n OPTION_DESCRIPTIONS,\n OPTION_FLAGS,\n} from \"./constants.js\";\nimport type { CLIEnvironment, CLILoggerConfig } from \"./environment.js\";\nimport { createDefaultEnvironment } from \"./environment.js\";\n\n/**\n * Parses and validates the log level option value.\n */\nfunction parseLogLevel(value: string): LogLevelName {\n const normalized = value.toLowerCase() as LogLevelName;\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?: LogLevelName;\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);\n registerModelsCommand(program, env);\n registerGadgetCommand(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);\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 // Pass Docker config from [docker] section\n dockerConfig: config.docker,\n };\n const program = createProgram(env, config);\n await program.parseAsync(env.argv);\n}\n","{\n \"name\": \"llmist\",\n \"version\": \"2.1.0\",\n \"description\": \"Universal TypeScript LLM client with streaming-first agent framework. Works with any model - no structured outputs or native tool calling required. Implements its own flexible grammar for function calling.\",\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 },\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 ],\n \"author\": \"\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@anthropic-ai/sdk\": \"^0.69.0\",\n \"@google/genai\": \"^1.27.0\",\n \"chalk\": \"^5.6.2\",\n \"commander\": \"^12.1.0\",\n \"diff\": \"^8.0.2\",\n \"eta\": \"^4.4.1\",\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 { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport type { Command } from \"commander\";\nimport { AgentBuilder } from \"../agent/builder.js\";\nimport { isAbortError } from \"../core/errors.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 { ApprovalManager, type ApprovalConfig } from \"./approval/index.js\";\nimport { builtinGadgets } from \"./builtin-gadgets.js\";\nimport type { AgentConfig } from \"./config.js\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { loadGadgets } from \"./gadgets.js\";\nimport {\n createSessionDir,\n formatCallNumber,\n formatLlmRequest,\n resolveLogDir,\n writeLogFile,\n} from \"./llm-logging.js\";\nimport { addAgentOptions, type AgentCommandOptions } from \"./option-helpers.js\";\nimport {\n createEscKeyListener,\n createSigintListener,\n executeAction,\n isInteractive,\n renderSummary,\n resolvePrompt,\n StreamPrinter,\n StreamProgress,\n} from \"./utils.js\";\nimport {\n formatGadgetSummary,\n renderMarkdownWithSeparators,\n renderOverallSummary,\n} from \"./ui/formatters.js\";\nimport {\n createDockerContext,\n DockerSkipError,\n executeInDocker,\n resolveDevMode,\n resolveDockerEnabled,\n type DockerOptions,\n} from \"./docker/index.js\";\n\n/**\n * Keyboard/signal listener management for ESC key and Ctrl+C (SIGINT) handling.\n * Allows pausing and restoring the ESC listener during readline operations.\n */\ninterface KeyboardManager {\n cleanupEsc: (() => void) | null;\n cleanupSigint: (() => void) | null;\n restore: () => void;\n}\n\n/**\n * Creates a human input handler for interactive mode.\n * Only returns a handler if stdin is a TTY (terminal), not a pipe.\n *\n * @param env - CLI environment\n * @param progress - Progress indicator to pause during input\n * @param keyboard - Keyboard listener manager for ESC handling\n * @returns Human input handler function or undefined if not interactive\n */\nfunction createHumanInputHandler(\n env: CLIEnvironment,\n progress: StreamProgress,\n keyboard: KeyboardManager,\n): ((question: string) => Promise<string>) | undefined {\n const stdout = env.stdout as NodeJS.WriteStream;\n if (!isInteractive(env.stdin) || typeof stdout.isTTY !== \"boolean\" || !stdout.isTTY) {\n return undefined;\n }\n\n return async (question: string): Promise<string> => {\n progress.pause(); // Pause progress indicator during human input\n\n // Temporarily disable ESC listener for readline (raw mode conflict)\n if (keyboard.cleanupEsc) {\n keyboard.cleanupEsc();\n keyboard.cleanupEsc = null;\n }\n\n const rl = createInterface({ input: env.stdin, output: env.stdout });\n try {\n // Display question on first prompt only (with markdown rendering and separators)\n const questionLine = question.trim() ? `\\n${renderMarkdownWithSeparators(question.trim())}` : \"\";\n let isFirst = true;\n\n // Loop until non-empty input (like a REPL)\n while (true) {\n const statsPrompt = progress.formatPrompt();\n const prompt = isFirst ? `${questionLine}\\n${statsPrompt}` : statsPrompt;\n isFirst = false;\n\n const answer = await rl.question(prompt);\n const trimmed = answer.trim();\n if (trimmed) {\n return trimmed;\n }\n // Empty input - show prompt again (no question repeat)\n }\n } finally {\n rl.close();\n // Restore ESC listener after readline closes\n keyboard.restore();\n }\n };\n}\n\n// formatGadgetSummary is now imported from ./ui/formatters.js\n// This demonstrates clean code organization and reusability\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: AgentCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n // Check if Docker sandboxing is enabled\n const dockerOptions: DockerOptions = {\n docker: options.docker ?? false,\n dockerRo: options.dockerRo ?? false,\n noDocker: options.noDocker ?? false,\n dockerDev: options.dockerDev ?? false,\n };\n\n const dockerEnabled = resolveDockerEnabled(\n env.dockerConfig,\n dockerOptions,\n options.docker, // Profile-level docker: true/false\n );\n\n if (dockerEnabled) {\n // Resolve dev mode settings (for mounting local source)\n const devMode = resolveDevMode(env.dockerConfig, dockerOptions.dockerDev);\n\n // Execute inside Docker container\n const ctx = createDockerContext(\n env.dockerConfig,\n dockerOptions,\n env.argv.slice(2), // Remove 'node' and script path\n process.cwd(),\n options.dockerCwdPermission, // Profile-level CWD permission override\n );\n\n try {\n await executeInDocker(ctx, devMode);\n // executeInDocker calls process.exit(), so we won't reach here\n } catch (error) {\n // DockerSkipError means we're already inside a container, continue normally\n if (error instanceof DockerSkipError) {\n // Continue with normal execution\n } else {\n throw error;\n }\n }\n }\n\n const prompt = await resolvePrompt(promptArg, env);\n const client = env.createClient();\n\n // SHOWCASE: llmist's GadgetRegistry for dynamic tool loading\n // This demonstrates how to build extensible CLIs with plugin-like functionality\n const registry = new GadgetRegistry();\n\n // Register built-in gadgets for basic agent interaction\n // SHOWCASE: Built-in gadgets enable conversation without any custom tools\n //\n // AskUser: Prompts user for input during agent execution\n // TellUser: Displays formatted messages and optionally ends the loop\n //\n // Flags control built-in behavior:\n // --no-builtins: Exclude all built-in gadgets\n // --no-builtin-interaction: Exclude only AskUser (keeps TellUser for output)\n //\n // AskUser is also auto-excluded when stdin is not interactive (piped input)\n const stdinIsInteractive = isInteractive(env.stdin);\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 (gadget.name === \"AskUser\" && (options.builtinInteraction === false || !stdinIsInteractive)) {\n continue;\n }\n registry.registerByClass(gadget);\n }\n }\n\n // Load user-provided gadgets from file paths\n // SHOWCASE: Dynamic gadget loading enables custom tools without recompiling\n // Users can provide gadgets via -g/--gadget flag, supporting any TypeScript class\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 // Later registrations can override earlier ones\n // This allows users to customize built-in behavior\n registry.registerByClass(gadget);\n }\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 // Set up cancellation support for ESC key and Ctrl+C (SIGINT) handling\n const abortController = new AbortController();\n let wasCancelled = false;\n let isStreaming = false; // Track if LLM call is in progress\n const stdinStream = env.stdin as NodeJS.ReadStream;\n\n // Shared cancel handler for both ESC and Ctrl+C\n const handleCancel = () => {\n if (!abortController.signal.aborted) {\n wasCancelled = true;\n abortController.abort();\n progress.pause();\n env.stderr.write(chalk.yellow(`\\n[Cancelled] ${progress.formatStats()}\\n`));\n } else {\n // Already cancelled - treat as quit request (like double Ctrl+C)\n // This ensures the user can always exit even if the abort didn't fully propagate\n handleQuit();\n }\n };\n\n // Create keyboard manager for ESC/SIGINT listener coordination with readline\n const keyboard: KeyboardManager = {\n cleanupEsc: null,\n cleanupSigint: null,\n restore: () => {\n // Only restore ESC listener if not cancelled - when wasCancelled is true,\n // the executeAgent function is terminating and we don't need the listener.\n // This is called after readline closes to re-enable ESC key detection.\n if (stdinIsInteractive && stdinStream.isTTY && !wasCancelled) {\n keyboard.cleanupEsc = createEscKeyListener(stdinStream, handleCancel, handleCancel);\n }\n },\n };\n\n // Quit handler for double Ctrl+C - shows summary and exits\n const handleQuit = () => {\n // Clean up listeners\n keyboard.cleanupEsc?.();\n keyboard.cleanupSigint?.();\n\n progress.complete();\n printer.ensureNewline();\n\n // Show final summary\n const summary = renderOverallSummary({\n totalTokens: usage?.totalTokens,\n iterations,\n elapsedSeconds: progress.getTotalElapsedSeconds(),\n cost: progress.getTotalCost(),\n });\n\n if (summary) {\n env.stderr.write(`${chalk.dim(\"â\".repeat(40))}\\n`);\n env.stderr.write(`${summary}\\n`);\n }\n\n env.stderr.write(chalk.dim(\"[Quit]\\n\"));\n process.exit(130); // SIGINT convention: 128 + signal number (2)\n };\n\n // Set up ESC key and Ctrl+C listener if in interactive TTY mode\n // Both ESC and Ctrl+C trigger handleCancel during streaming\n if (stdinIsInteractive && stdinStream.isTTY) {\n keyboard.cleanupEsc = createEscKeyListener(stdinStream, handleCancel, handleCancel);\n }\n\n // Set up SIGINT (Ctrl+C) listener - always active for graceful cancellation\n keyboard.cleanupSigint = createSigintListener(\n handleCancel,\n handleQuit,\n () => isStreaming && !abortController.signal.aborted,\n env.stderr,\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<string, \"allowed\" | \"denied\" | \"approval-required\"> = {\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 const approvalManager = new ApprovalManager(approvalConfig, env, progress, keyboard);\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 (model: string, messages: LLMMessage[]): 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((sum, m) => sum + (m.content?.length ?? 0), 0);\n return Math.round(totalChars / FALLBACK_CHARS_PER_TOKEN);\n }\n };\n\n // Count tokens for gadget output text\n const countGadgetOutputTokens = async (output: string | undefined): 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 const builder = new AgentBuilder(client)\n .withModel(options.model)\n .withLogger(env.createLogger(\"llmist:cli:agent\"))\n .withHooks({\n observers: {\n // onLLMCallStart: Start progress indicator for each LLM call\n // This showcases how to react to agent lifecycle events\n onLLMCallStart: async (context) => {\n isStreaming = true; // Mark that we're actively streaming (for SIGINT handling)\n llmCallCounter++;\n\n // Count input tokens accurately using provider-specific methods\n // This ensures we never show ~ for input tokens\n const inputTokens = await countMessagesTokens(\n context.options.model,\n context.options.messages,\n );\n progress.startCall(context.options.model, inputTokens);\n // Mark input tokens as accurate (not estimated)\n progress.setInputTokens(inputTokens, false);\n },\n\n // onLLMCallReady: Log the exact request being sent to the LLM\n // This fires AFTER controller modifications (e.g., trailing messages)\n onLLMCallReady: async (context) => {\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 // onStreamChunk: Real-time updates as LLM generates tokens\n // This enables responsive UIs that show progress during generation\n onStreamChunk: async (context) => {\n // Update estimated output tokens from accumulated text length\n progress.update(context.accumulatedText.length);\n\n // Use exact token counts when available from streaming response\n // SHOWCASE: Provider responses include token usage for accurate tracking\n if (context.usage) {\n if (context.usage.inputTokens) {\n progress.setInputTokens(context.usage.inputTokens, false);\n }\n if (context.usage.outputTokens) {\n progress.setOutputTokens(context.usage.outputTokens, false);\n }\n // Update cached token counts for live cost estimation\n progress.setCachedTokens(\n context.usage.cachedInputTokens ?? 0,\n context.usage.cacheCreationInputTokens ?? 0,\n );\n }\n },\n\n // onLLMCallComplete: Finalize metrics after each LLM call\n // This is where you'd typically log metrics or update dashboards\n onLLMCallComplete: async (context) => {\n isStreaming = false; // Mark that streaming is complete (for SIGINT handling)\n\n // Capture completion metadata for final summary\n usage = context.usage;\n iterations = Math.max(iterations, context.iteration + 1);\n\n // Update with final exact token counts from provider\n // SHOWCASE: llmist normalizes token usage across all providers\n if (context.usage) {\n if (context.usage.inputTokens) {\n progress.setInputTokens(context.usage.inputTokens, false);\n }\n if (context.usage.outputTokens) {\n progress.setOutputTokens(context.usage.outputTokens, false);\n }\n }\n\n // Calculate per-call cost for the summary (accounting for cached tokens)\n // Use context.options.model (resolved) instead of options.model (raw CLI input)\n // This ensures aliases like \"sonnet\" are resolved to \"claude-sonnet-4-5\"\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 // Get per-call elapsed time before endCall resets it\n const callElapsed = progress.getCallElapsedSeconds();\n\n // End this call's progress tracking and switch to cumulative mode\n progress.endCall(context.usage);\n\n // SHOWCASE: Print per-call summary after each LLM call\n // This gives users visibility into each iteration's metrics\n // Skip summaries in quiet mode\n if (!options.quiet) {\n const summary = renderSummary({\n iterations: context.iteration + 1,\n model: options.model,\n usage: context.usage,\n elapsedSeconds: callElapsed,\n cost: callCost,\n finishReason: context.finishReason,\n });\n if (summary) {\n env.stderr.write(`${summary}\\n`);\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 const mode = approvalManager.getApprovalMode(ctx.gadgetName);\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 // Interactive mode: use approval manager\n const result = await approvalManager.requestApproval(ctx.gadgetName, ctx.parameters);\n\n if (!result.approved) {\n return {\n action: \"skip\",\n syntheticResult: `status=denied\\n\\nDenied: ${result.reason ?? \"by user\"}`,\n };\n }\n\n return { action: \"proceed\" };\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 const humanInputHandler = createHumanInputHandler(env, progress, keyboard);\n if (humanInputHandler) {\n builder.onHumanInput(humanInputHandler);\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\\nHere's what I can do:\\n- Analyze your codebase\\n- Execute commands\\n- Answer questions\\n\\nWhat would you like me to work on?\",\n done: false,\n type: \"info\",\n },\n \"âšī¸ đ Hello! I'm ready to help.\\n\\nHere's what I can do:\\n- Analyze your codebase\\n- Execute commands\\n- Answer questions\\n\\nWhat would you like me to work on?\",\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: what gadget invocations can you make in parallel right now?\",\n \"Maximize efficiency by batching independent operations in a single response.\",\n ].join(\" \"),\n );\n\n // Build and start the agent\n const agent = builder.ask(prompt);\n\n // SHOWCASE: llmist's event-driven agent execution\n // The agent emits events as it runs, enabling reactive UIs\n //\n // Event types:\n // - \"text\": LLM-generated text chunks (streaming or complete)\n // - \"gadget_result\": Results from gadget/tool executions\n // - \"human_input_required\": Agent needs user input (handled via callback)\n //\n // This pattern allows building:\n // - Real-time streaming UIs\n // - Progress indicators during tool execution\n // - Separation of business logic (agent) from presentation (UI)\n\n // Buffer for accumulating text chunks - markdown rendering requires complete content\n let textBuffer = \"\";\n const flushTextBuffer = () => {\n if (textBuffer) {\n // Use separators in normal mode, plain text in quiet mode\n const output = options.quiet ? textBuffer : renderMarkdownWithSeparators(textBuffer);\n printer.write(output);\n textBuffer = \"\";\n }\n };\n\n try {\n for await (const event of agent.run()) {\n if (event.type === \"text\") {\n // Accumulate text chunks - we'll render markdown when complete\n progress.pause();\n textBuffer += event.content;\n } else if (event.type === \"gadget_result\") {\n // Flush any accumulated text before showing gadget result\n flushTextBuffer();\n // Show gadget execution feedback on stderr\n progress.pause();\n\n if (options.quiet) {\n // In quiet mode, only output TellUser messages (to stdout, plain unrendered text)\n if (event.result.gadgetName === \"TellUser\" && event.result.parameters?.message) {\n const message = String(event.result.parameters.message);\n env.stdout.write(`${message}\\n`);\n }\n } else {\n // Normal mode: show full gadget summary on stderr\n const tokenCount = await countGadgetOutputTokens(event.result.result);\n env.stderr.write(`${formatGadgetSummary({ ...event.result, tokenCount })}\\n`);\n }\n // Progress automatically resumes on next LLM call (via onLLMCallStart hook)\n }\n // Note: human_input_required handled by callback (see createHumanInputHandler)\n }\n } catch (error) {\n // Handle abort gracefully - message already shown in ESC handler\n if (!isAbortError(error)) {\n throw error;\n }\n // Keep partial response in buffer for flushing below\n } finally {\n // Always cleanup keyboard and signal listeners\n isStreaming = false;\n keyboard.cleanupEsc?.();\n\n // Replace the complex SIGINT handler with a simple exit handler\n // This ensures Ctrl+C always works even if something keeps the event loop alive\n if (keyboard.cleanupSigint) {\n keyboard.cleanupSigint();\n process.once(\"SIGINT\", () => process.exit(130)); // 130 = 128 + SIGINT (2)\n }\n }\n\n // Flush any remaining buffered text with markdown rendering (includes partial on cancel)\n flushTextBuffer();\n\n progress.complete();\n printer.ensureNewline();\n\n // SHOWCASE: Show overall summary only if there were multiple iterations\n // Single-iteration runs already showed per-call summary, no need to repeat\n // Skip summaries in quiet mode\n if (!options.quiet && iterations > 1) {\n // Separator line to distinguish from per-call summaries\n env.stderr.write(`${chalk.dim(\"â\".repeat(40))}\\n`);\n\n const summary = renderOverallSummary({\n totalTokens: usage?.totalTokens,\n iterations,\n elapsedSeconds: progress.getTotalElapsedSeconds(),\n cost: progress.getTotalCost(),\n });\n if (summary) {\n env.stderr.write(`${summary}\\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): void {\n const cmd = program\n .command(COMMANDS.agent)\n .description(\"Run the llmist agent loop with optional gadgets.\")\n .argument(\"[prompt]\", \"Prompt for the agent loop. Falls back to stdin when available.\");\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: AgentCommandOptions = {\n ...(options as AgentCommandOptions),\n gadgetApproval: config?.[\"gadget-approval\"],\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","import { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport type { CLIEnvironment } from \"../environment.js\";\nimport type { StreamProgress } from \"../utils.js\";\nimport { builtinContextProviders, DefaultContextProvider } from \"./context-providers.js\";\nimport { renderColoredDiff } from \"./diff-renderer.js\";\nimport type {\n ApprovalConfig,\n ApprovalContextProvider,\n ApprovalMode,\n ApprovalResult,\n KeyboardCoordinator,\n} from \"./types.js\";\n\n/**\n * Manages gadget approval flows.\n *\n * The ApprovalManager determines whether a gadget execution should:\n * - Proceed automatically (\"allowed\")\n * - Be rejected automatically (\"denied\")\n * - Require user approval (\"approval-required\")\n *\n * For approval-required gadgets, it displays relevant context (like diffs for\n * file operations) and prompts the user interactively.\n */\nexport class ApprovalManager {\n private providers = new Map<string, ApprovalContextProvider>();\n\n /**\n * Creates a new ApprovalManager.\n *\n * @param config - Approval configuration with per-gadget modes\n * @param env - CLI environment for I/O operations\n * @param progress - Optional progress indicator to pause during prompts\n * @param keyboard - Optional keyboard coordinator to disable ESC listener during prompts\n */\n constructor(\n private readonly config: ApprovalConfig,\n private readonly env: CLIEnvironment,\n private readonly progress?: StreamProgress,\n private readonly keyboard?: KeyboardCoordinator,\n ) {\n // Register built-in context providers\n for (const provider of builtinContextProviders) {\n this.registerProvider(provider);\n }\n }\n\n /**\n * Registers a custom context provider for a gadget.\n *\n * @param provider - The context provider to register\n */\n registerProvider(provider: ApprovalContextProvider): void {\n // Case-insensitive registration\n this.providers.set(provider.gadgetName.toLowerCase(), provider);\n }\n\n /**\n * Gets the approval mode for a gadget.\n *\n * Resolution order:\n * 1. Explicit configuration for the gadget name\n * 2. Wildcard \"*\" configuration\n * 3. Default mode from config\n *\n * @param gadgetName - Name of the gadget\n * @returns The approval mode to use\n */\n getApprovalMode(gadgetName: string): ApprovalMode {\n const normalizedName = gadgetName.toLowerCase();\n\n // Check explicit configuration (case-insensitive)\n for (const [configName, mode] of Object.entries(this.config.gadgetApprovals)) {\n if (configName.toLowerCase() === normalizedName) {\n return mode;\n }\n }\n\n // Check wildcard\n if (\"*\" in this.config.gadgetApprovals) {\n return this.config.gadgetApprovals[\"*\"];\n }\n\n // Return default\n return this.config.defaultMode;\n }\n\n /**\n * Requests approval for a gadget execution.\n *\n * Behavior depends on the gadget's approval mode:\n * - \"allowed\": Returns approved immediately\n * - \"denied\": Returns denied with configuration message\n * - \"approval-required\": Prompts user interactively\n *\n * @param gadgetName - Name of the gadget\n * @param params - The gadget's execution parameters\n * @returns Approval result indicating whether to proceed\n */\n async requestApproval(\n gadgetName: string,\n params: Record<string, unknown>,\n ): Promise<ApprovalResult> {\n const mode = this.getApprovalMode(gadgetName);\n\n if (mode === \"allowed\") {\n return { approved: true };\n }\n\n if (mode === \"denied\") {\n return {\n approved: false,\n reason: `${gadgetName} is denied by configuration`,\n };\n }\n\n // mode === \"approval-required\"\n return this.promptForApproval(gadgetName, params);\n }\n\n /**\n * Prompts the user for approval interactively.\n */\n private async promptForApproval(\n gadgetName: string,\n params: Record<string, unknown>,\n ): Promise<ApprovalResult> {\n // Get context provider (case-insensitive lookup, or default)\n const provider =\n this.providers.get(gadgetName.toLowerCase()) ?? new DefaultContextProvider(gadgetName);\n\n const context = await provider.getContext(params);\n\n // Pause progress indicator if available\n this.progress?.pause();\n\n // Temporarily disable ESC listener for readline (raw mode conflict)\n // This prevents interference between ESC key detection and readline input\n if (this.keyboard?.cleanupEsc) {\n this.keyboard.cleanupEsc();\n this.keyboard.cleanupEsc = null;\n }\n\n try {\n // Render approval UI\n this.env.stderr.write(`\\n${chalk.yellow(\"đ Approval required:\")} ${context.summary}\\n`);\n\n if (context.details) {\n this.env.stderr.write(`\\n${renderColoredDiff(context.details)}\\n`);\n }\n\n // Prompt user\n const response = await this.prompt(\" â approve, or type to reject: \");\n\n // Empty input or \"y\"/\"Y\" = approved\n const isApproved = response === \"\" || response.toLowerCase() === \"y\";\n\n if (isApproved) {\n this.env.stderr.write(` ${chalk.green(\"â Approved\")}\\n\\n`);\n return { approved: true };\n }\n\n this.env.stderr.write(` ${chalk.red(\"â Denied\")}\\n\\n`);\n return { approved: false, reason: response || \"Rejected by user\" };\n } finally {\n // Restore ESC listener after readline closes\n this.keyboard?.restore();\n }\n }\n\n /**\n * Prompts for user input.\n */\n private async prompt(message: string): Promise<string> {\n const rl = createInterface({\n input: this.env.stdin,\n output: this.env.stderr,\n });\n try {\n const answer = await rl.question(message);\n return answer.trim();\n } finally {\n rl.close();\n }\n }\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { createPatch } from \"diff\";\nimport type { ApprovalContext, ApprovalContextProvider } from \"./types.js\";\nimport { formatNewFileDiff } from \"./diff-renderer.js\";\n\n/**\n * Formats a universal gadget summary: GadgetName(param1=value1, param2=value2)\n * Used by all context providers for consistent approval prompts.\n * Shows full parameter values so users know exactly what they're approving.\n */\nexport function formatGadgetSummary(gadgetName: string, params: Record<string, unknown>): string {\n const paramEntries = Object.entries(params);\n\n if (paramEntries.length === 0) {\n return `${gadgetName}()`;\n }\n\n const paramStr = paramEntries.map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(\", \");\n\n return `${gadgetName}(${paramStr})`;\n}\n\n/**\n * Context provider for WriteFile gadget.\n * Generates a unified diff when modifying existing files,\n * or shows \"new file\" content for file creation.\n */\nexport class WriteFileContextProvider implements ApprovalContextProvider {\n readonly gadgetName = \"WriteFile\";\n\n async getContext(params: Record<string, unknown>): Promise<ApprovalContext> {\n const filePath = String(params.filePath ?? params.path ?? \"\");\n const newContent = String(params.content ?? \"\");\n const resolvedPath = resolve(process.cwd(), filePath);\n\n if (!existsSync(resolvedPath)) {\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n details: formatNewFileDiff(filePath, newContent),\n };\n }\n\n const oldContent = readFileSync(resolvedPath, \"utf-8\");\n const diff = createPatch(filePath, oldContent, newContent, \"original\", \"modified\");\n\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n details: diff,\n };\n }\n}\n\n/**\n * Context provider for EditFile gadget.\n * Similar to WriteFile but handles edit-specific parameters.\n */\nexport class EditFileContextProvider implements ApprovalContextProvider {\n readonly gadgetName = \"EditFile\";\n\n async getContext(params: Record<string, unknown>): Promise<ApprovalContext> {\n const filePath = String(params.filePath ?? params.path ?? \"\");\n const resolvedPath = resolve(process.cwd(), filePath);\n\n // EditFile typically receives the full new content or edits\n // Handle both content-based and patch-based edits\n if (\"content\" in params) {\n const newContent = String(params.content);\n\n if (!existsSync(resolvedPath)) {\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n details: formatNewFileDiff(filePath, newContent),\n };\n }\n\n const oldContent = readFileSync(resolvedPath, \"utf-8\");\n const diff = createPatch(filePath, oldContent, newContent, \"original\", \"modified\");\n\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n details: diff,\n };\n }\n\n // For ed-style commands, show the commands themselves\n if (\"commands\" in params) {\n const commands = String(params.commands);\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n details: `Commands:\\n${commands}`,\n };\n }\n\n // Fallback\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n };\n }\n}\n\n/**\n * Default context provider for any gadget without a specific provider.\n * Shows gadget name and parameters.\n */\nexport class DefaultContextProvider implements ApprovalContextProvider {\n constructor(public readonly gadgetName: string) {}\n\n async getContext(params: Record<string, unknown>): Promise<ApprovalContext> {\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n };\n }\n}\n\n/**\n * Built-in context providers for common gadgets.\n * These provide custom details (diffs) while using universal summary format.\n */\nexport const builtinContextProviders: ApprovalContextProvider[] = [\n new WriteFileContextProvider(),\n new EditFileContextProvider(),\n // Note: RunCommand uses DefaultContextProvider - no custom details needed\n];\n","import chalk from \"chalk\";\n\n/**\n * Renders a unified diff with ANSI colors.\n *\n * Color scheme:\n * - Added lines (+): green\n * - Removed lines (-): red\n * - Hunk headers (@@): cyan\n * - File headers (---/+++): bold\n * - Context lines: dim\n *\n * @param diff - Unified diff string\n * @returns Colorized diff string\n */\nexport function renderColoredDiff(diff: string): string {\n return diff\n .split(\"\\n\")\n .map((line) => {\n // File headers\n if (line.startsWith(\"---\") || line.startsWith(\"+++\")) {\n return chalk.bold(line);\n }\n // Added lines (but not +++ header)\n if (line.startsWith(\"+\")) {\n return chalk.green(line);\n }\n // Removed lines (but not --- header)\n if (line.startsWith(\"-\")) {\n return chalk.red(line);\n }\n // Hunk headers\n if (line.startsWith(\"@@\")) {\n return chalk.cyan(line);\n }\n // Context lines and everything else\n return chalk.dim(line);\n })\n .join(\"\\n\");\n}\n\n/**\n * Formats a new file as a pseudo-diff showing all lines as additions.\n *\n * @param filePath - Path to the new file\n * @param content - Content of the new file\n * @returns Formatted pseudo-diff string\n */\nexport function formatNewFileDiff(filePath: string, content: string): string {\n const lines = content.split(\"\\n\");\n const header = `+++ ${filePath} (new file)`;\n const addedLines = lines.map((line) => `+ ${line}`).join(\"\\n\");\n return `${header}\\n${addedLines}`;\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 {\n BreakLoopException,\n HumanInputException,\n} 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\n .string()\n .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 HumanInputException(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\n .string()\n .optional()\n .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:\n \"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 BreakLoopException(\"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","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { BaseGadget } from \"../gadgets/gadget.js\";\nimport { getBuiltinGadget, isBuiltinGadgetName } from \"./builtins/index.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 BaseGadget {\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 *\n * @param value - Value to check\n * @returns True if value is a Gadget constructor\n */\nfunction isGadgetConstructor(value: unknown): value is new () => BaseGadget {\n if (typeof value !== \"function\") {\n return false;\n }\n\n const prototype = value.prototype as unknown;\n // Use duck typing for prototype check too\n return Boolean(prototype) && (prototype instanceof BaseGadget || 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): BaseGadget | 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): BaseGadget[] {\n const results: BaseGadget[] = [];\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 BaseGadget || isGadgetLike(value)) {\n results.push(value as BaseGadget);\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 (by name or \"builtin:\" prefix), file paths, and npm module names.\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. File paths (starting with ., /, ~) - resolve and import\n * 4. npm module names - dynamic import\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<BaseGadget[]> {\n const gadgets: BaseGadget[] = [];\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 // 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: BaseGadget[];\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 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 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 { 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\";\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)\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n proc.kill();\n reject(new Error(\"ed command timed out after 30000ms\"));\n }, 30000);\n });\n\n // Wait for process to complete or timeout\n const exitCode = await Promise.race([proc.exited, timeoutPromise]);\n\n // Collect output\n const stdout = await new Response(proc.stdout).text();\n const stderr = await new Response(proc.stderr).text();\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 { 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\n .number()\n .default(30000)\n .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: { argv: [\"gh\", \"pr\", \"review\", \"123\", \"--comment\", \"--body\", \"Review with `backticks` and 'quotes'\"], timeout: 30000 },\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\", \"pr\", \"review\", \"123\", \"--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 to complete or timeout\n const exitCode = await Promise.race([proc.exited, timeoutPromise]);\n\n // Clear timeout on normal exit to prevent dangling timer\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n // Collect output\n const stdout = await new Response(proc.stdout).text();\n const stderr = await new Response(proc.stderr).text();\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 { BaseGadget } from \"../../gadgets/gadget.js\";\nimport { listDirectory } from \"./filesystem/list-directory.js\";\nimport { readFile } from \"./filesystem/read-file.js\";\nimport { writeFile } from \"./filesystem/write-file.js\";\nimport { editFile } from \"./filesystem/edit-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, BaseGadget> = {\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): BaseGadget | 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","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport 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(option: string | boolean | undefined, subdir: string): 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 lines.push(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, TTYStream } 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: TTYStream): 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 { formatTokens, formatCost } 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\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 constructor(\n private readonly target: NodeJS.WritableStream,\n private readonly isTTY: boolean,\n private readonly modelRegistry?: ModelRegistry,\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(\":\")\n ? this.model.split(\":\")[1]\n : 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 * 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 const spinner = SPINNER_FRAMES[this.frameIndex++ % SPINNER_FRAMES.length];\n\n if (this.mode === \"streaming\") {\n this.renderStreamingMode(spinner);\n } else {\n this.renderCumulativeMode(spinner);\n }\n this.hasRendered = true;\n }\n\n private renderStreamingMode(spinner: string): void {\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 // Build status parts: #N model | â in â â out â time | cost\n const parts: string[] = [];\n\n // #N model (iteration number + model name)\n const iterPart = chalk.cyan(`#${this.currentIteration}`);\n if (this.model) {\n parts.push(`${iterPart} ${chalk.magenta(this.model)}`);\n } else {\n parts.push(iterPart);\n }\n\n // Context usage percentage (color-coded by usage level)\n const usagePercent = this.getContextUsagePercent();\n if (usagePercent !== null) {\n const formatted = `${Math.round(usagePercent)}%`;\n if (usagePercent >= 80) {\n parts.push(chalk.red(formatted)); // Danger zone - compaction threshold\n } else if (usagePercent >= 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 (this.callInputTokens > 0) {\n const prefix = this.callInputTokensEstimated ? \"~\" : \"\";\n parts.push(chalk.dim(\"â\") + chalk.yellow(` ${prefix}${formatTokens(this.callInputTokens)}`));\n }\n\n // â output tokens\n if (this.isStreaming || outTokens > 0) {\n const prefix = this.callOutputTokensEstimated ? \"~\" : \"\";\n parts.push(chalk.dim(\"â\") + chalk.green(` ${prefix}${formatTokens(outTokens)}`));\n }\n\n // Time\n parts.push(chalk.dim(`${elapsed}s`));\n\n // Live cost estimate for current call (updates as tokens stream in)\n const callCost = this.calculateCurrentCallCost(outTokens);\n if (callCost > 0) {\n parts.push(chalk.cyan(`$${formatCost(callCost)}`));\n }\n\n this.target.write(`\\r${parts.join(chalk.dim(\" | \"))} ${chalk.cyan(spinner)}`);\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 private renderCumulativeMode(spinner: string): void {\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 this.target.write(`\\r${parts.join(chalk.dim(\" | \"))} ${chalk.cyan(spinner)}`);\n }\n\n /**\n * Pauses the progress indicator and clears the line.\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 // Only clear the line if we actually rendered something\n if (this.hasRendered) {\n // Clear spinner line and ensure cursor is at column 0\n // \\r = carriage return (go to column 0)\n // \\x1b[K = clear from cursor to end of line\n // \\x1b[0G = move cursor to column 0 (ensures we're at start even after clear)\n this.target.write(\"\\r\\x1b[K\\x1b[0G\");\n this.hasRendered = false;\n }\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 { marked, type MarkedExtension } from \"marked\";\nimport { markedTerminal } from \"marked-terminal\";\nimport type { TokenUsage } from \"../../core/options.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 * 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 * 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\n/**\n * Formats a gadget execution result as a compact one-liner for stderr output.\n *\n * Provides visual feedback for gadget execution during agent runs. Different\n * icons and colors indicate success, error, or completion states.\n *\n * **Format:**\n * - Success: `â GadgetName(param=value, ...) â 248 tokens 123ms`\n * - Error: `â GadgetName(param=value) error: message 123ms`\n * - Completion: `âš GadgetName(param=value) â 2.5k tokens 123ms`\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 one-liner 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) â 248 tokens 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) error: File not found 2ms\"\n * ```\n */\n/**\n * Formats parameters as a compact inline string with color-coded keys and values.\n *\n * @param params - Parameter key-value pairs\n * @returns Formatted string with dim keys and cyan values, e.g., \"path=., recursive=true\"\n */\nfunction formatParametersInline(params: Record<string, unknown> | undefined): string {\n if (!params || Object.keys(params).length === 0) {\n return \"\";\n }\n\n return Object.entries(params)\n .map(([key, value]) => {\n // Format value compactly\n let formatted: string;\n if (typeof value === \"string\") {\n // Truncate long strings\n formatted = value.length > 30 ? `${value.slice(0, 30)}âĻ` : value;\n } else if (typeof value === \"boolean\" || typeof value === \"number\") {\n formatted = String(value);\n } else {\n // For arrays/objects, show compact JSON\n const json = JSON.stringify(value);\n formatted = json.length > 30 ? `${json.slice(0, 30)}âĻ` : json;\n }\n // Color: dim key, = sign, cyan value\n return `${chalk.dim(key)}${chalk.dim(\"=\")}${chalk.cyan(formatted)}`;\n })\n .join(chalk.dim(\", \"));\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\nexport function formatGadgetSummary(result: GadgetResult): string {\n // Format gadget name and execution time\n const gadgetLabel = chalk.magenta.bold(result.gadgetName);\n const timeLabel = chalk.dim(`${Math.round(result.executionTimeMs)}ms`);\n\n // Format parameters inline (parentheses are dim, content is color-coded)\n const paramsStr = formatParametersInline(result.parameters);\n const paramsLabel = paramsStr ? `${chalk.dim(\"(\")}${paramsStr}${chalk.dim(\")\")}` : \"\";\n\n // Error case - show error message in red (one-liner)\n if (result.error) {\n const errorMsg = result.error.length > 50 ? `${result.error.slice(0, 50)}âĻ` : result.error;\n return `${chalk.red(\"â\")} ${gadgetLabel}${paramsLabel} ${chalk.red(\"error:\")} ${errorMsg} ${timeLabel}`;\n }\n\n // Format output size: prefer token count if available, fallback to bytes\n let outputLabel: string;\n if (result.tokenCount !== undefined && result.tokenCount > 0) {\n outputLabel = chalk.green(`${formatTokens(result.tokenCount)} tokens`);\n } else if (result.result) {\n const outputBytes = Buffer.byteLength(result.result, \"utf-8\");\n outputLabel = outputBytes > 0 ? chalk.green(formatBytes(outputBytes)) : chalk.dim(\"no output\");\n } else {\n outputLabel = chalk.dim(\"no output\");\n }\n\n // Build the summary line\n const icon = result.breaksLoop ? chalk.yellow(\"âš\") : chalk.green(\"â\");\n const summaryLine = `${icon} ${gadgetLabel}${paramsLabel} ${chalk.dim(\"â\")} ${outputLabel} ${timeLabel}`;\n\n // TellUser gadget: display full message content below the summary (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 `${summaryLine}\\n${rendered}`;\n }\n\n return summaryLine;\n}\n","import type { Command } from \"commander\";\nimport type { AgentConfig, CompleteConfig, CustomCommandConfig, GadgetApprovalConfig } from \"./config.js\";\nimport { DEFAULT_MODEL, OPTION_DESCRIPTIONS, OPTION_FLAGS } from \"./constants.js\";\nimport { createNumericParser } from \"./utils.js\";\n\n/**\n * Options for the complete command (camelCase, matching Commander output).\n */\nexport interface CompleteCommandOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxTokens?: number;\n quiet?: boolean;\n logLlmRequests?: string | boolean;\n}\n\n/**\n * Options for the agent command (camelCase, matching Commander output).\n */\nexport interface AgentCommandOptions {\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?: GadgetApprovalConfig;\n quiet?: boolean;\n logLlmRequests?: string | boolean;\n /** Enable Docker sandboxing */\n docker?: boolean;\n /** Enable Docker with read-only CWD mount */\n dockerRo?: boolean;\n /** Disable Docker (override config) */\n noDocker?: boolean;\n /** Enable Docker dev mode (mount local source) */\n dockerDev?: boolean;\n /** Per-profile CWD mount permission override */\n dockerCwdPermission?: \"ro\" | \"rw\";\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(OPTION_FLAGS.logLlmRequests, OPTION_DESCRIPTIONS.logLlmRequests, defaults?.[\"log-llm-requests\"]);\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(OPTION_FLAGS.logLlmRequests, OPTION_DESCRIPTIONS.logLlmRequests, defaults?.[\"log-llm-requests\"])\n .option(OPTION_FLAGS.docker, OPTION_DESCRIPTIONS.docker)\n .option(OPTION_FLAGS.dockerRo, OPTION_DESCRIPTIONS.dockerRo)\n .option(OPTION_FLAGS.noDocker, OPTION_DESCRIPTIONS.noDocker)\n .option(OPTION_FLAGS.dockerDev, OPTION_DESCRIPTIONS.dockerDev);\n}\n\n/**\n * Converts kebab-case config to camelCase command options for complete command.\n */\nexport function configToCompleteOptions(config: CustomCommandConfig): Partial<CompleteCommandOptions> {\n const result: Partial<CompleteCommandOptions> = {};\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<AgentCommandOptions> {\n const result: Partial<AgentCommandOptions> = {};\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)\n 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.docker !== undefined) result.docker = config.docker;\n if (config[\"docker-cwd-permission\"] !== undefined)\n result.dockerCwdPermission = config[\"docker-cwd-permission\"];\n return result;\n}\n","/**\n * Docker sandboxing type definitions.\n *\n * These types define the configuration schema for running llmist agent\n * commands inside Docker containers for security isolation.\n */\n\n/**\n * Mount permission for Docker volume mounts.\n * - \"ro\": Read-only mount (safer, prevents modifications)\n * - \"rw\": Read-write mount (allows modifications)\n */\nexport type MountPermission = \"ro\" | \"rw\";\n\n/**\n * Valid mount permissions for validation.\n */\nexport const VALID_MOUNT_PERMISSIONS: MountPermission[] = [\"ro\", \"rw\"];\n\n/**\n * Configuration for an additional mount point.\n */\nexport interface MountConfig {\n /** Host path to mount (supports ~ for home directory) */\n source: string;\n /** Path inside the container */\n target: string;\n /** Mount permission mode */\n permission: MountPermission;\n}\n\n/**\n * Docker configuration section in cli.toml.\n *\n * @example\n * ```toml\n * [docker]\n * enabled = true\n * cwd-permission = \"rw\"\n * config-permission = \"ro\"\n * image-name = \"llmist-sandbox\"\n *\n * [[docker.mounts]]\n * source = \"~/data\"\n * target = \"/data\"\n * permission = \"ro\"\n * ```\n */\nexport interface DockerConfig {\n /** Enable Docker sandboxing globally (default: false) */\n enabled?: boolean;\n\n /** Custom Dockerfile contents (overrides default template) */\n dockerfile?: string;\n\n /** Permission for current working directory mount (default: \"rw\") */\n \"cwd-permission\"?: MountPermission;\n\n /** Permission for ~/.llmist config directory mount (default: \"ro\") */\n \"config-permission\"?: MountPermission;\n\n /** Additional mount points */\n mounts?: MountConfig[];\n\n /** Extra environment variables to forward to container */\n \"env-vars\"?: string[];\n\n /** Custom Docker image name (default: \"llmist-sandbox\") */\n \"image-name\"?: string;\n\n /** Enable dev mode - mount local source instead of npm install */\n \"dev-mode\"?: boolean;\n\n /** Path to llmist source for dev mode (supports ~ for home directory) */\n \"dev-source\"?: string;\n\n /** Extra arguments to pass to docker run (e.g., [\"-p\", \"3000:3000\"]) */\n \"docker-args\"?: string[];\n}\n\n/**\n * Valid keys for docker config validation.\n */\nexport const DOCKER_CONFIG_KEYS = new Set([\n \"enabled\",\n \"dockerfile\",\n \"cwd-permission\",\n \"config-permission\",\n \"mounts\",\n \"env-vars\",\n \"image-name\",\n \"dev-mode\",\n \"dev-source\",\n \"docker-args\",\n]);\n\n/**\n * Docker CLI options (resolved from config and CLI flags).\n */\nexport interface DockerOptions {\n /** Docker mode enabled via --docker flag */\n docker: boolean;\n /** Read-only CWD mount via --docker-ro flag */\n dockerRo: boolean;\n /** Explicitly disabled via --no-docker flag */\n noDocker: boolean;\n /** Dev mode - mount local source instead of npm install */\n dockerDev: boolean;\n}\n\n/**\n * Resolved Docker execution context.\n */\nexport interface DockerExecutionContext {\n /** Merged Docker configuration */\n config: DockerConfig;\n /** CLI options */\n options: DockerOptions;\n /** Original CLI arguments to forward (minus docker flags) */\n forwardArgs: string[];\n /** Current working directory on host */\n cwd: string;\n /** Profile-level CWD permission override (takes precedence over config) */\n profileCwdPermission?: MountPermission;\n}\n\n/**\n * Default Docker image name.\n */\nexport const DEFAULT_IMAGE_NAME = \"llmist-sandbox\";\n\n/**\n * Default mount permissions.\n */\nexport const DEFAULT_CWD_PERMISSION: MountPermission = \"rw\";\nexport const DEFAULT_CONFIG_PERMISSION: MountPermission = \"ro\";\n\n/**\n * API keys that are always forwarded to the container.\n */\nexport const FORWARDED_API_KEYS = [\n \"ANTHROPIC_API_KEY\",\n \"OPENAI_API_KEY\",\n \"GEMINI_API_KEY\",\n] as const;\n\n/**\n * Dev mode Docker image name (separate from production).\n */\nexport const DEV_IMAGE_NAME = \"llmist-dev-sandbox\";\n\n/**\n * Mount target for llmist source in dev mode.\n */\nexport const DEV_SOURCE_MOUNT_TARGET = \"/llmist-src\";\n\n/**\n * Resolved dev mode settings.\n */\nexport interface DevModeSettings {\n /** Whether dev mode is enabled */\n enabled: boolean;\n /** Path to llmist source directory (undefined if not enabled) */\n sourcePath: string | undefined;\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 {\n type PromptsConfig,\n TemplateError,\n createTemplateEngine,\n hasTemplateSyntax,\n resolveTemplate,\n validateEnvVars,\n validatePrompts,\n} from \"./templates.js\";\nimport type { DockerConfig } from \"./docker/types.js\";\nimport { validateDockerConfig } from \"./docker/docker-config.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 approval mode 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 GadgetApprovalMode = \"allowed\" | \"denied\" | \"approval-required\";\n\n/**\n * Valid gadget approval modes.\n */\nconst VALID_APPROVAL_MODES: GadgetApprovalMode[] = [\"allowed\", \"denied\", \"approval-required\"];\n\n/**\n * Configuration for per-gadget approval behavior.\n * Keys are gadget names (case-insensitive), values are approval modes.\n * Special key \"*\" sets the default for unconfigured gadgets.\n */\nexport type GadgetApprovalConfig = Record<string, GadgetApprovalMode>;\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 * Base options shared by both complete and agent command configurations.\n */\nexport interface BaseCommandConfig {\n model?: string;\n system?: string;\n temperature?: number;\n inherits?: string | string[];\n /** Enable Docker sandboxing for this profile/command */\n docker?: boolean;\n /** Override CWD mount permission for this profile (\"ro\" or \"rw\") */\n \"docker-cwd-permission\"?: \"ro\" | \"rw\";\n}\n\n/**\n * Configuration for the complete command.\n */\nexport interface CompleteConfig extends BaseCommandConfig {\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 agent command.\n */\nexport interface AgentConfig extends BaseCommandConfig {\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\"?: GadgetApprovalConfig;\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 prompts?: PromptsConfig;\n docker?: DockerConfig;\n [customCommand: string]:\n | CustomCommandConfig\n | CompleteConfig\n | AgentConfig\n | GlobalConfig\n | PromptsConfig\n | DockerConfig\n | undefined;\n}\n\n// Re-export DockerConfig for consumers\nexport type { DockerConfig } from \"./docker/types.js\";\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 \"docker\", // Enable Docker sandboxing (only effective for agent type)\n \"docker-cwd-permission\", // Override CWD mount permission for this profile\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 \"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 \"docker\", // Enable Docker sandboxing for this profile\n \"docker-cwd-permission\", // Override CWD mount permission for this profile\n]);\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 that a value is a gadget approval config (object mapping gadget names to modes).\n */\nfunction validateGadgetApproval(value: unknown, section: string): GadgetApprovalConfig {\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: GadgetApprovalConfig = {};\n for (const [gadgetName, mode] of Object.entries(value as Record<string, unknown>)) {\n if (typeof mode !== \"string\") {\n throw new ConfigError(\n `[${section}].gadget-approval.${gadgetName} must be a string`,\n );\n }\n if (!VALID_APPROVAL_MODES.includes(mode as GadgetApprovalMode)) {\n throw new ConfigError(\n `[${section}].gadget-approval.${gadgetName} must be one of: ${VALID_APPROVAL_MODES.join(\", \")}`,\n );\n }\n result[gadgetName] = mode as GadgetApprovalMode;\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<BaseCommandConfig> {\n const result: Partial<BaseCommandConfig> = {};\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 if (\"docker\" in raw) {\n result.docker = validateBoolean(raw.docker, \"docker\", section);\n }\n if (\"docker-cwd-permission\" in raw) {\n const perm = validateString(raw[\"docker-cwd-permission\"], \"docker-cwd-permission\", section);\n if (perm !== \"ro\" && perm !== \"rw\") {\n throw new ConfigError(`[${section}].docker-cwd-permission must be \"ro\" or \"rw\"`);\n }\n result[\"docker-cwd-permission\"] = perm as \"ro\" | \"rw\";\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(rawObj[\"gadget-remove\"], \"gadget-remove\", section);\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 (\"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 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(rawObj[\"gadget-remove\"], \"gadget-remove\", section);\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\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 === \"prompts\") {\n result.prompts = validatePromptsConfig(value, key);\n } else if (key === \"docker\") {\n result.docker = validateDockerConfig(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([\"global\", \"complete\", \"agent\", \"prompts\", \"docker\"]);\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(\n template: string,\n promptName?: string,\n configPath?: string,\n): 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","/**\n * Docker configuration validation.\n *\n * Follows the same validation patterns as the main config.ts module.\n */\n\nimport { ConfigError } from \"../config.js\";\nimport {\n type DockerConfig,\n type MountConfig,\n type MountPermission,\n DOCKER_CONFIG_KEYS,\n VALID_MOUNT_PERMISSIONS,\n} from \"./types.js\";\n\n/**\n * Valid keys for mount config objects.\n */\nconst MOUNT_CONFIG_KEYS = new Set([\"source\", \"target\", \"permission\"]);\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 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 a mount permission value.\n */\nfunction validateMountPermission(value: unknown, key: string, section: string): MountPermission {\n const str = validateString(value, key, section);\n if (!VALID_MOUNT_PERMISSIONS.includes(str as MountPermission)) {\n throw new ConfigError(\n `[${section}].${key} must be one of: ${VALID_MOUNT_PERMISSIONS.join(\", \")}`,\n );\n }\n return str as MountPermission;\n}\n\n/**\n * Validates a single mount configuration object.\n */\nfunction validateMountConfig(value: unknown, index: number, section: string): MountConfig {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new ConfigError(`[${section}].mounts[${index}] must be a table`);\n }\n\n const rawObj = value as Record<string, unknown>;\n const mountSection = `${section}.mounts[${index}]`;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!MOUNT_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${mountSection}].${key} is not a valid mount option`);\n }\n }\n\n // Required fields\n if (!(\"source\" in rawObj)) {\n throw new ConfigError(`[${mountSection}] missing required field 'source'`);\n }\n if (!(\"target\" in rawObj)) {\n throw new ConfigError(`[${mountSection}] missing required field 'target'`);\n }\n if (!(\"permission\" in rawObj)) {\n throw new ConfigError(`[${mountSection}] missing required field 'permission'`);\n }\n\n return {\n source: validateString(rawObj.source, \"source\", mountSection),\n target: validateString(rawObj.target, \"target\", mountSection),\n permission: validateMountPermission(rawObj.permission, \"permission\", mountSection),\n };\n}\n\n/**\n * Validates an array of mount configurations.\n */\nfunction validateMountsArray(value: unknown, section: string): MountConfig[] {\n if (!Array.isArray(value)) {\n throw new ConfigError(`[${section}].mounts must be an array of tables`);\n }\n\n const result: MountConfig[] = [];\n for (let i = 0; i < value.length; i++) {\n result.push(validateMountConfig(value[i], i, section));\n }\n return result;\n}\n\n/**\n * Validates the docker configuration section.\n *\n * @param raw - Raw config object from TOML parser\n * @param section - Section name for error messages (usually \"docker\")\n * @returns Validated DockerConfig\n * @throws ConfigError if validation fails\n */\nexport function validateDockerConfig(raw: unknown, section: string): DockerConfig {\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 (!DOCKER_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n const result: DockerConfig = {};\n\n if (\"enabled\" in rawObj) {\n result.enabled = validateBoolean(rawObj.enabled, \"enabled\", section);\n }\n\n if (\"dockerfile\" in rawObj) {\n result.dockerfile = validateString(rawObj.dockerfile, \"dockerfile\", section);\n }\n\n if (\"cwd-permission\" in rawObj) {\n result[\"cwd-permission\"] = validateMountPermission(\n rawObj[\"cwd-permission\"],\n \"cwd-permission\",\n section,\n );\n }\n\n if (\"config-permission\" in rawObj) {\n result[\"config-permission\"] = validateMountPermission(\n rawObj[\"config-permission\"],\n \"config-permission\",\n section,\n );\n }\n\n if (\"mounts\" in rawObj) {\n result.mounts = validateMountsArray(rawObj.mounts, section);\n }\n\n if (\"env-vars\" in rawObj) {\n result[\"env-vars\"] = validateStringArray(rawObj[\"env-vars\"], \"env-vars\", section);\n }\n\n if (\"image-name\" in rawObj) {\n result[\"image-name\"] = validateString(rawObj[\"image-name\"], \"image-name\", section);\n }\n\n if (\"dev-mode\" in rawObj) {\n result[\"dev-mode\"] = validateBoolean(rawObj[\"dev-mode\"], \"dev-mode\", section);\n }\n\n if (\"dev-source\" in rawObj) {\n result[\"dev-source\"] = validateString(rawObj[\"dev-source\"], \"dev-source\", section);\n }\n\n // Note: docker-args is intentionally only configurable in the global ~/.llmist/cli.toml.\n // Since llmist only loads config from the user's home directory (not project-level configs),\n // this is inherently safe from supply-chain attacks where a malicious project could inject\n // dangerous Docker arguments like \"--privileged\" or \"-v /:/host\".\n if (\"docker-args\" in rawObj) {\n result[\"docker-args\"] = validateStringArray(rawObj[\"docker-args\"], \"docker-args\", section);\n }\n\n return result;\n}\n","/**\n * Dockerfile templates for llmist sandboxing.\n *\n * Two templates are provided:\n * - DEFAULT_DOCKERFILE: Production mode - installs llmist from npm\n * - DEV_DOCKERFILE: Dev mode - runs from mounted source code\n *\n * Both include:\n * - Bun runtime\n * - ed (line editor for EditFile gadget)\n * - ripgrep (fast search tool)\n * - ast-grep (code search/refactoring)\n * - git (version control)\n */\n\nimport type { DockerConfig } from \"./types.js\";\nimport { DEV_SOURCE_MOUNT_TARGET } from \"./types.js\";\n\n/**\n * Default Dockerfile template.\n *\n * Uses oven/bun:1-debian as base for:\n * - Modern Bun runtime\n * - Debian's extensive package ecosystem\n * - Good compatibility with common tools\n */\nexport const DEFAULT_DOCKERFILE = `# llmist sandbox image\n# Auto-generated - customize via [docker].dockerfile in cli.toml\n\nFROM oven/bun:1-debian\n\n# Install essential tools\nRUN apt-get update && apt-get install -y --no-install-recommends \\\\\n # ed for EditFile gadget (line-oriented editor)\n ed \\\\\n # ripgrep for fast file searching\n ripgrep \\\\\n # git for version control operations\n git \\\\\n # curl for downloads and API calls\n curl \\\\\n # ca-certificates for HTTPS\n ca-certificates \\\\\n && rm -rf /var/lib/apt/lists/*\n\n# Install ast-grep for code search/refactoring\n# Using the official install script\nRUN curl -fsSL https://raw.githubusercontent.com/ast-grep/ast-grep/main/install.sh | bash \\\\\n && mv /root/.local/bin/ast-grep /usr/local/bin/ 2>/dev/null || true \\\\\n && mv /root/.local/bin/sg /usr/local/bin/ 2>/dev/null || true\n\n# Install llmist globally via bun\nRUN bun add -g llmist\n\n# Working directory (host CWD will be mounted here)\nWORKDIR /workspace\n\n# Entry point - llmist with all arguments forwarded\nENTRYPOINT [\"llmist\"]\n`;\n\n/**\n * Dev mode Dockerfile template.\n *\n * Key differences from production:\n * - Does NOT install llmist from npm\n * - Expects llmist source to be mounted at ${DEV_SOURCE_MOUNT_TARGET}\n * - Runs directly from source via bun\n */\nexport const DEV_DOCKERFILE = `# llmist DEV sandbox image\n# For development/testing with local source code\n\nFROM oven/bun:1-debian\n\n# Install essential tools (same as production)\nRUN apt-get update && apt-get install -y --no-install-recommends \\\\\n ed \\\\\n ripgrep \\\\\n git \\\\\n curl \\\\\n ca-certificates \\\\\n && rm -rf /var/lib/apt/lists/*\n\n# Install ast-grep for code search/refactoring\nRUN curl -fsSL https://raw.githubusercontent.com/ast-grep/ast-grep/main/install.sh | bash \\\\\n && mv /root/.local/bin/ast-grep /usr/local/bin/ 2>/dev/null || true \\\\\n && mv /root/.local/bin/sg /usr/local/bin/ 2>/dev/null || true\n\n# Working directory (host CWD will be mounted here)\nWORKDIR /workspace\n\n# Entry point - run llmist from mounted source\n# Source is mounted at ${DEV_SOURCE_MOUNT_TARGET}\nENTRYPOINT [\"bun\", \"run\", \"${DEV_SOURCE_MOUNT_TARGET}/src/cli.ts\"]\n`;\n\n/**\n * Resolves the Dockerfile content to use.\n *\n * Priority:\n * 1. Custom dockerfile from config (always takes precedence)\n * 2. DEV_DOCKERFILE if dev mode is enabled\n * 3. DEFAULT_DOCKERFILE (production)\n *\n * @param config - Docker configuration\n * @param devMode - Whether dev mode is enabled\n * @returns Dockerfile content\n */\nexport function resolveDockerfile(config: DockerConfig, devMode = false): string {\n // Custom Dockerfile always takes precedence\n if (config.dockerfile) {\n return config.dockerfile;\n }\n return devMode ? DEV_DOCKERFILE : DEFAULT_DOCKERFILE;\n}\n\n/**\n * Computes a hash of the Dockerfile content for cache invalidation.\n *\n * Uses Bun's fast native hash function.\n *\n * @param dockerfile - Dockerfile content\n * @returns Hex string hash\n */\nexport function computeDockerfileHash(dockerfile: string): string {\n const encoder = new TextEncoder();\n const data = encoder.encode(dockerfile);\n // Bun.hash returns a 64-bit hash as BigInt, convert to hex string\n return Bun.hash(data).toString(16);\n}\n","/**\n * Docker image building and caching.\n *\n * Handles:\n * - Building Docker images from Dockerfile content\n * - Caching image hashes to avoid unnecessary rebuilds\n * - Checking if an image needs to be rebuilt\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { computeDockerfileHash } from \"./dockerfile.js\";\nimport { DEFAULT_IMAGE_NAME } from \"./types.js\";\n\n/**\n * Cache directory for Docker-related files.\n */\nconst CACHE_DIR = join(homedir(), \".llmist\", \"docker-cache\");\n\n/**\n * File storing the current image hash.\n */\nconst HASH_FILE = \"image-hash.json\";\n\n/**\n * Cache entry structure.\n */\ninterface CacheEntry {\n imageName: string;\n dockerfileHash: string;\n builtAt: string;\n}\n\n/**\n * Ensures the cache directory exists.\n */\nfunction ensureCacheDir(): void {\n if (!existsSync(CACHE_DIR)) {\n mkdirSync(CACHE_DIR, { recursive: true });\n }\n}\n\n/**\n * Gets the cached hash for an image name.\n *\n * @param imageName - Docker image name\n * @returns Cached dockerfile hash, or undefined if not cached\n */\nfunction getCachedHash(imageName: string): string | undefined {\n const hashPath = join(CACHE_DIR, HASH_FILE);\n\n if (!existsSync(hashPath)) {\n return undefined;\n }\n\n try {\n const content = readFileSync(hashPath, \"utf-8\");\n const cache = JSON.parse(content) as Record<string, CacheEntry>;\n return cache[imageName]?.dockerfileHash;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Saves the hash for an image name to cache.\n *\n * @param imageName - Docker image name\n * @param hash - Dockerfile hash\n */\nfunction setCachedHash(imageName: string, hash: string): void {\n ensureCacheDir();\n const hashPath = join(CACHE_DIR, HASH_FILE);\n\n let cache: Record<string, CacheEntry> = {};\n\n if (existsSync(hashPath)) {\n try {\n const content = readFileSync(hashPath, \"utf-8\");\n cache = JSON.parse(content) as Record<string, CacheEntry>;\n } catch {\n // Start fresh on parse error\n cache = {};\n }\n }\n\n cache[imageName] = {\n imageName,\n dockerfileHash: hash,\n builtAt: new Date().toISOString(),\n };\n\n writeFileSync(hashPath, JSON.stringify(cache, null, 2));\n}\n\n/**\n * Error thrown when Docker image building fails.\n */\nexport class DockerBuildError extends Error {\n constructor(\n message: string,\n public readonly output: string,\n ) {\n super(message);\n this.name = \"DockerBuildError\";\n }\n}\n\n/**\n * Builds a Docker image from Dockerfile content.\n *\n * @param imageName - Name/tag for the built image\n * @param dockerfile - Dockerfile content\n * @throws DockerBuildError if build fails\n */\nasync function buildImage(imageName: string, dockerfile: string): Promise<void> {\n // Write Dockerfile to temp location\n ensureCacheDir();\n const dockerfilePath = join(CACHE_DIR, \"Dockerfile\");\n writeFileSync(dockerfilePath, dockerfile);\n\n // Build the image\n const proc = Bun.spawn(\n [\"docker\", \"build\", \"-t\", imageName, \"-f\", dockerfilePath, CACHE_DIR],\n {\n stdout: \"pipe\",\n stderr: \"pipe\",\n },\n );\n\n const exitCode = await proc.exited;\n const stdout = await new Response(proc.stdout).text();\n const stderr = await new Response(proc.stderr).text();\n\n if (exitCode !== 0) {\n const output = [stdout, stderr].filter(Boolean).join(\"\\n\");\n throw new DockerBuildError(\n `Docker build failed with exit code ${exitCode}`,\n output,\n );\n }\n}\n\n/**\n * Ensures the Docker image is built and up-to-date.\n *\n * Checks if the cached Dockerfile hash matches the current content.\n * If not, rebuilds the image.\n *\n * @param imageName - Docker image name (defaults to DEFAULT_IMAGE_NAME)\n * @param dockerfile - Dockerfile content\n * @returns The image name (for chaining)\n * @throws DockerBuildError if build fails\n */\nexport async function ensureImage(\n imageName: string = DEFAULT_IMAGE_NAME,\n dockerfile: string,\n): Promise<string> {\n const hash = computeDockerfileHash(dockerfile);\n const cachedHash = getCachedHash(imageName);\n\n if (cachedHash === hash) {\n // Image is up-to-date\n return imageName;\n }\n\n // Need to build/rebuild\n console.error(`Building Docker image '${imageName}'...`);\n await buildImage(imageName, dockerfile);\n\n // Update cache\n setCachedHash(imageName, hash);\n\n console.error(`Docker image '${imageName}' built successfully.`);\n return imageName;\n}\n\n/**\n * Checks if an image needs to be rebuilt.\n *\n * @param imageName - Docker image name\n * @param dockerfile - Dockerfile content\n * @returns true if rebuild is needed\n */\nexport function needsRebuild(imageName: string, dockerfile: string): boolean {\n const hash = computeDockerfileHash(dockerfile);\n const cachedHash = getCachedHash(imageName);\n return cachedHash !== hash;\n}\n\n/**\n * Clears the image cache for a specific image or all images.\n *\n * @param imageName - Image name to clear, or undefined to clear all\n */\nexport function clearImageCache(imageName?: string): void {\n const hashPath = join(CACHE_DIR, HASH_FILE);\n\n if (!existsSync(hashPath)) {\n return;\n }\n\n if (imageName) {\n try {\n const content = readFileSync(hashPath, \"utf-8\");\n const cache = JSON.parse(content) as Record<string, CacheEntry>;\n delete cache[imageName];\n writeFileSync(hashPath, JSON.stringify(cache, null, 2));\n } catch {\n // Ignore errors\n }\n } else {\n // Clear all\n writeFileSync(hashPath, \"{}\");\n }\n}\n","/**\n * Docker execution wrapper.\n *\n * Handles:\n * - Checking if Docker is available\n * - Building/caching the Docker image\n * - Running llmist inside the container\n * - Forwarding environment variables and mounts\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { resolveDockerfile } from \"./dockerfile.js\";\nimport { ensureImage, DockerBuildError } from \"./image-manager.js\";\nimport {\n type DevModeSettings,\n type DockerConfig,\n type DockerExecutionContext,\n type DockerOptions,\n type MountPermission,\n DEFAULT_IMAGE_NAME,\n DEFAULT_CWD_PERMISSION,\n DEFAULT_CONFIG_PERMISSION,\n DEV_IMAGE_NAME,\n DEV_SOURCE_MOUNT_TARGET,\n FORWARDED_API_KEYS,\n} from \"./types.js\";\n\n/**\n * Error thrown when Docker is not available.\n */\nexport class DockerUnavailableError extends Error {\n constructor() {\n super(\n \"Docker is required but not available. \" +\n \"Install Docker or disable Docker sandboxing in your configuration.\",\n );\n this.name = \"DockerUnavailableError\";\n }\n}\n\n/**\n * Error thrown when Docker container execution fails.\n */\nexport class DockerRunError extends Error {\n constructor(\n public readonly exitCode: number,\n public readonly stderr: string,\n ) {\n super(`Docker container exited with code ${exitCode}`);\n this.name = \"DockerRunError\";\n }\n}\n\n/**\n * Error thrown when Docker execution should be skipped.\n * This occurs when already running inside a container.\n */\nexport class DockerSkipError extends Error {\n constructor() {\n super(\"Docker execution skipped - already inside container\");\n this.name = \"DockerSkipError\";\n }\n}\n\n/**\n * Checks if Docker is available and running.\n *\n * @returns true if Docker is available\n */\nexport async function checkDockerAvailable(): Promise<boolean> {\n try {\n const proc = Bun.spawn([\"docker\", \"info\"], {\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n await proc.exited;\n return proc.exitCode === 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Checks if we're already running inside a Docker container.\n *\n * Detection methods:\n * 1. /.dockerenv file - Docker creates this in all containers\n * 2. /proc/1/cgroup contains \"docker\" or \"containerd\" - Linux cgroup detection\n *\n * @returns true if running inside a container\n */\nexport function isInsideContainer(): boolean {\n // Method 1: Check for /.dockerenv (most reliable)\n if (existsSync(\"/.dockerenv\")) {\n return true;\n }\n\n // Method 2: Check cgroup for docker/containerd (Linux)\n try {\n const cgroup = readFileSync(\"/proc/1/cgroup\", \"utf-8\");\n if (cgroup.includes(\"docker\") || cgroup.includes(\"containerd\")) {\n return true;\n }\n } catch {\n // Not on Linux or no access to /proc\n }\n\n return false;\n}\n\n/**\n * Attempts to auto-detect the llmist source directory.\n *\n * Checks if the current script is being run from an llmist source tree\n * by examining the script path and verifying package.json.\n *\n * @returns Path to llmist source directory, or undefined if not detectable\n */\nexport function autoDetectDevSource(): string | undefined {\n // Check if running from source via bun (e.g., `bun src/cli.ts`)\n const scriptPath = process.argv[1];\n if (!scriptPath || !scriptPath.endsWith(\"src/cli.ts\")) {\n return undefined;\n }\n\n const srcDir = dirname(scriptPath);\n const projectDir = dirname(srcDir);\n\n // Verify it's the llmist project by checking package.json\n const packageJsonPath = join(projectDir, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n return undefined;\n }\n\n try {\n const pkg = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n if (pkg.name === \"llmist\") {\n return projectDir;\n }\n } catch {\n // Ignore parse errors\n }\n\n return undefined;\n}\n\n/**\n * Resolves dev mode settings.\n *\n * Priority for enablement:\n * 1. CLI --docker-dev flag\n * 2. Config [docker].dev-mode\n * 3. LLMIST_DEV_MODE environment variable\n *\n * Priority for source path:\n * 1. Config [docker].dev-source\n * 2. LLMIST_DEV_SOURCE environment variable\n * 3. Auto-detect from script path\n *\n * @param config - Docker configuration\n * @param cliDevMode - Whether --docker-dev flag was used\n * @returns Resolved dev mode settings\n * @throws Error if dev mode is enabled but source path cannot be found\n */\nexport function resolveDevMode(\n config: DockerConfig | undefined,\n cliDevMode: boolean,\n): DevModeSettings {\n // Check if dev mode is enabled\n const enabled = cliDevMode || config?.[\"dev-mode\"] || process.env.LLMIST_DEV_MODE === \"1\";\n\n if (!enabled) {\n return { enabled: false, sourcePath: undefined };\n }\n\n // Resolve source path\n const sourcePath =\n config?.[\"dev-source\"] || process.env.LLMIST_DEV_SOURCE || autoDetectDevSource();\n\n if (!sourcePath) {\n throw new Error(\n \"Docker dev mode enabled but llmist source path not found. \" +\n \"Set [docker].dev-source in config, LLMIST_DEV_SOURCE env var, \" +\n \"or run from the llmist source directory (bun src/cli.ts).\",\n );\n }\n\n return { enabled: true, sourcePath };\n}\n\n/**\n * Expands ~ to home directory in a path.\n */\nfunction expandHome(path: string): string {\n if (path.startsWith(\"~\")) {\n return path.replace(/^~/, homedir());\n }\n return path;\n}\n\n/**\n * Builds the docker run command arguments.\n *\n * @param ctx - Docker execution context\n * @param imageName - Docker image name to run\n * @param devMode - Dev mode settings (for source mounting)\n * @returns Array of arguments for docker run\n */\nfunction buildDockerRunArgs(\n ctx: DockerExecutionContext,\n imageName: string,\n devMode: DevModeSettings,\n): string[] {\n const args: string[] = [\"run\", \"--rm\"];\n\n // Generate unique container name to avoid collisions\n const timestamp = Date.now();\n const random = Math.random().toString(36).slice(2, 8);\n const containerName = `llmist-${timestamp}-${random}`;\n args.push(\"--name\", containerName);\n\n // TTY handling - only add -it if stdin is a TTY\n if (process.stdin.isTTY) {\n args.push(\"-it\");\n }\n\n // Mount current working directory\n // Priority: --docker-ro flag > profile-level > config-level > default\n const cwdPermission: MountPermission = ctx.options.dockerRo\n ? \"ro\"\n : (ctx.profileCwdPermission ?? ctx.config[\"cwd-permission\"] ?? DEFAULT_CWD_PERMISSION);\n args.push(\"-v\", `${ctx.cwd}:/workspace:${cwdPermission}`);\n args.push(\"-w\", \"/workspace\");\n\n // Mount ~/.llmist config directory (for config access inside container)\n const configPermission = ctx.config[\"config-permission\"] ?? DEFAULT_CONFIG_PERMISSION;\n const llmistDir = expandHome(\"~/.llmist\");\n args.push(\"-v\", `${llmistDir}:/root/.llmist:${configPermission}`);\n\n // Mount llmist source in dev mode (read-only to prevent accidental modifications)\n if (devMode.enabled && devMode.sourcePath) {\n const expandedSource = expandHome(devMode.sourcePath);\n args.push(\"-v\", `${expandedSource}:${DEV_SOURCE_MOUNT_TARGET}:ro`);\n }\n\n // Additional mounts from config\n if (ctx.config.mounts) {\n for (const mount of ctx.config.mounts) {\n const source = expandHome(mount.source);\n args.push(\"-v\", `${source}:${mount.target}:${mount.permission}`);\n }\n }\n\n // Forward API keys (if set in environment)\n for (const key of FORWARDED_API_KEYS) {\n if (process.env[key]) {\n args.push(\"-e\", key);\n }\n }\n\n // Forward additional env vars from config\n if (ctx.config[\"env-vars\"]) {\n for (const key of ctx.config[\"env-vars\"]) {\n if (process.env[key]) {\n args.push(\"-e\", key);\n }\n }\n }\n\n // Extra docker run arguments from config (e.g., port mappings, network mode)\n if (ctx.config[\"docker-args\"]) {\n args.push(...ctx.config[\"docker-args\"]);\n }\n\n // Image name\n args.push(imageName);\n\n // Forward the CLI arguments (these go to llmist inside the container)\n args.push(...ctx.forwardArgs);\n\n return args;\n}\n\n/**\n * Filters out Docker-related flags from CLI arguments.\n *\n * These flags are consumed by the wrapper and should not be\n * passed to the llmist instance inside the container.\n *\n * @param argv - Original CLI arguments\n * @returns Filtered arguments without Docker flags\n */\nexport function filterDockerArgs(argv: string[]): string[] {\n const dockerFlags = new Set([\"--docker\", \"--docker-ro\", \"--no-docker\", \"--docker-dev\"]);\n return argv.filter((arg) => !dockerFlags.has(arg));\n}\n\n/**\n * Resolves whether Docker mode should be enabled.\n *\n * Priority (highest to lowest):\n * 1. --no-docker flag (disables)\n * 2. --docker or --docker-ro flag (enables)\n * 3. Profile/command docker: true in config\n * 4. Global [docker].enabled in config\n *\n * @param config - Docker configuration\n * @param options - CLI options\n * @param profileDocker - docker: true/false from profile config\n * @returns Whether Docker mode is enabled\n */\nexport function resolveDockerEnabled(\n config: DockerConfig | undefined,\n options: DockerOptions,\n profileDocker?: boolean,\n): boolean {\n // CLI --no-docker overrides everything\n if (options.noDocker) {\n return false;\n }\n\n // CLI --docker or --docker-ro enables\n if (options.docker || options.dockerRo) {\n return true;\n }\n\n // Profile-level docker: true/false\n if (profileDocker !== undefined) {\n return profileDocker;\n }\n\n // Global [docker].enabled\n return config?.enabled ?? false;\n}\n\n/**\n * Executes llmist inside a Docker container.\n *\n * This function:\n * 1. Checks if already inside a container (prevents nesting)\n * 2. Verifies Docker is available\n * 3. Builds/caches the image (dev or production)\n * 4. Runs the container with appropriate mounts and env vars\n * 5. Exits with the container's exit code\n *\n * @param ctx - Docker execution context\n * @param devMode - Dev mode settings\n * @throws DockerUnavailableError if Docker is not available\n * @throws DockerBuildError if image building fails\n * @throws DockerRunError if container execution fails\n */\nexport async function executeInDocker(\n ctx: DockerExecutionContext,\n devMode: DevModeSettings,\n): Promise<never> {\n // Check if we're already inside a container\n if (isInsideContainer()) {\n console.error(\n \"Warning: Docker mode requested but already inside a container. \" +\n \"Proceeding without re-containerization.\",\n );\n // Signal to caller that Docker should be skipped\n throw new DockerSkipError();\n }\n\n // Check Docker availability\n const available = await checkDockerAvailable();\n if (!available) {\n throw new DockerUnavailableError();\n }\n\n // Resolve Dockerfile and image name based on dev mode\n const dockerfile = resolveDockerfile(ctx.config, devMode.enabled);\n const imageName = devMode.enabled\n ? DEV_IMAGE_NAME\n : (ctx.config[\"image-name\"] ?? DEFAULT_IMAGE_NAME);\n\n // Show dev mode feedback\n if (devMode.enabled) {\n console.error(`[dev mode] Mounting source from ${devMode.sourcePath}`);\n }\n\n try {\n await ensureImage(imageName, dockerfile);\n } catch (error) {\n if (error instanceof DockerBuildError) {\n console.error(\"Docker build failed:\");\n console.error(error.output);\n throw error;\n }\n throw error;\n }\n\n // Build docker run command\n const dockerArgs = buildDockerRunArgs(ctx, imageName, devMode);\n\n // Execute container\n const proc = Bun.spawn([\"docker\", ...dockerArgs], {\n stdin: \"inherit\",\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n process.exit(exitCode);\n}\n\n/**\n * Creates a Docker execution context from config and options.\n *\n * @param config - Docker configuration\n * @param options - CLI options\n * @param argv - Original CLI arguments (without 'node' and script name)\n * @param cwd - Current working directory\n * @param profileCwdPermission - Profile-level CWD permission override\n * @returns Docker execution context\n */\nexport function createDockerContext(\n config: DockerConfig | undefined,\n options: DockerOptions,\n argv: string[],\n cwd: string,\n profileCwdPermission?: \"ro\" | \"rw\",\n): DockerExecutionContext {\n return {\n config: config ?? {},\n options,\n forwardArgs: filterDockerArgs(argv),\n cwd,\n profileCwdPermission,\n };\n}\n\n// Re-export errors for consumers\nexport { DockerBuildError } from \"./image-manager.js\";\n","import type { Command } from \"commander\";\n\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 {\n createSessionDir,\n formatLlmRequest,\n resolveLogDir,\n writeLogFile,\n} from \"./llm-logging.js\";\nimport {\n addCompleteOptions,\n type CompleteCommandOptions,\n} 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: CompleteCommandOptions,\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 builder.addUser(prompt);\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 CompleteCommandOptions, env), env),\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 type { Command } from \"commander\";\nimport chalk from \"chalk\";\n\nimport type { BaseGadget } 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 { loadGadgets } from \"./gadgets.js\";\nimport { promptForParameters, readStdinJson } from \"./gadget-prompts.js\";\nimport { executeAction } from \"./utils.js\";\n\n/**\n * Result of selecting a gadget from a file.\n */\ninterface GadgetSelection {\n gadget: BaseGadget;\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` +\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: BaseGadget, 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) =>\n executeAction(() => executeGadgetValidate(file, env), env),\n );\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\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .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.split(\",\").map((s) => s.trim()).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(stdin: NodeJS.ReadableStream): 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 { type Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { executeAction } from \"./utils.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport { MODEL_ALIASES } from \"../core/model-shortcuts.js\";\n\ninterface ModelsCommandOptions {\n provider?: string;\n format?: \"table\" | \"json\";\n verbose?: boolean;\n}\n\nasync function handleModelsCommand(\n options: ModelsCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const client = env.createClient();\n\n // Get models, optionally filtered by provider\n const models = client.modelRegistry.listModels(options.provider);\n\n if (options.format === \"json\") {\n renderJSON(models, env.stdout);\n } else {\n renderTable(models, options.verbose || false, env.stdout);\n }\n}\n\nfunction renderTable(models: ModelSpec[], verbose: boolean, stream: NodeJS.WritableStream): 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 // Header\n stream.write(chalk.bold.cyan(\"\\nAvailable Models\\n\"));\n stream.write(chalk.cyan(\"=\".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} Models\\n`));\n\n if (verbose) {\n renderVerboseTable(providerModels, stream);\n } else {\n renderCompactTable(providerModels, stream);\n }\n\n stream.write(\"\\n\");\n }\n\n // Display shortcuts\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(chalk.cyan(` ${shortcut.padEnd(15)}`) + chalk.dim(\" â \") + chalk.white(fullName) + \"\\n\");\n }\n stream.write(\"\\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(chalk.dim(\"â\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\n\");\n stream.write(\n chalk.bold(\n \"Model ID\".padEnd(idWidth) +\n \" \" + \"Display Name\".padEnd(nameWidth) +\n \" \" + \"Context\".padEnd(contextWidth) +\n \" \" + \"Input\".padEnd(inputWidth) +\n \" \" + \"Output\".padEnd(outputWidth)\n ) + \"\\n\"\n );\n stream.write(chalk.dim(\"â\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\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 \" \" + chalk.white(model.displayName.padEnd(nameWidth)) +\n \" \" + chalk.yellow(contextFormatted.padEnd(contextWidth)) +\n \" \" + chalk.cyan(inputPrice.padEnd(inputWidth)) +\n \" \" + chalk.cyan(outputPrice.padEnd(outputWidth)) +\n \"\\n\"\n );\n }\n\n stream.write(chalk.dim(\"â\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\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(` ${chalk.dim(\"Context:\")} ${chalk.yellow(formatTokens(model.contextWindow))}\\n`);\n stream.write(` ${chalk.dim(\"Max Output:\")} ${chalk.yellow(formatTokens(model.maxOutputTokens))}\\n`);\n stream.write(` ${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 if (model.pricing.cachedInput !== undefined) {\n stream.write(` ${chalk.dim(\"Cached Input:\")} ${chalk.cyan(`$${model.pricing.cachedInput.toFixed(2)} per 1M tokens`)}\\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\nfunction renderJSON(models: ModelSpec[], stream: NodeJS.WritableStream): void {\n const output = {\n models: models.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 shortcuts: MODEL_ALIASES,\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 all available LLM 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 .action((options) =>\n executeAction(\n () => handleModelsCommand(options as ModelsCommandOptions, env),\n env,\n ),\n );\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\";\nimport type { DockerConfig } from \"./docker/types.js\";\n\n/**\n * Stream type that may have TTY capabilities.\n */\nexport type TTYStream = 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: TTYStream;\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 /** Docker sandboxing configuration from [docker] section */\n dockerConfig?: DockerConfig;\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 } from \"./config.js\";\nimport { createLoggerFactory, type CLIEnvironment, type CLILoggerConfig } from \"./environment.js\";\nimport {\n addAgentOptions,\n addCompleteOptions,\n type AgentCommandOptions,\n type CompleteCommandOptions,\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): 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: CompleteCommandOptions = {\n ...configDefaults,\n ...(cliOptions as Partial<CompleteCommandOptions>),\n } as CompleteCommandOptions;\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: AgentCommandOptions = {\n ...configDefaults,\n ...(cliOptions as Partial<AgentCommandOptions>),\n } as AgentCommandOptions;\n await executeAgent(prompt, options, cmdEnv);\n }, cmdEnv);\n });\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;AACV;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,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AACb;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,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,sBAAsB;AAAA,EACtB,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AACb;AAGO,IAAM,iBAAiB;;;ACjE9B,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,EACjB;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,EACF;AAAA,EACA,QAAU;AAAA,EACV,SAAW;AAAA,EACX,cAAgB;AAAA,IACd,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,OAAS;AAAA,IACT,WAAa;AAAA,IACb,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,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;;;AC/GA;AAHA,SAAS,mBAAAC,wBAAuB;AAChC,OAAOC,YAAW;;;ACmCX,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;;;ADhDA;AACA;;;AERA,SAAS,uBAAuB;AAChC,OAAOC,YAAW;;;ACDlB,SAAS,YAAY,oBAAoB;AACzC,SAAS,eAAe;AACxB,SAAS,mBAAmB;;;ACF5B,OAAO,WAAW;AAeX,SAAS,kBAAkB,MAAsB;AACtD,SAAO,KACJ,MAAM,IAAI,EACV,IAAI,CAAC,SAAS;AAEb,QAAI,KAAK,WAAW,KAAK,KAAK,KAAK,WAAW,KAAK,GAAG;AACpD,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB;AAEA,QAAI,KAAK,WAAW,GAAG,GAAG;AACxB,aAAO,MAAM,MAAM,IAAI;AAAA,IACzB;AAEA,QAAI,KAAK,WAAW,GAAG,GAAG;AACxB,aAAO,MAAM,IAAI,IAAI;AAAA,IACvB;AAEA,QAAI,KAAK,WAAW,IAAI,GAAG;AACzB,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB;AAEA,WAAO,MAAM,IAAI,IAAI;AAAA,EACvB,CAAC,EACA,KAAK,IAAI;AACd;AASO,SAAS,kBAAkB,UAAkB,SAAyB;AAC3E,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,SAAS,OAAO,QAAQ;AAC9B,QAAM,aAAa,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE,EAAE,KAAK,IAAI;AAC7D,SAAO,GAAG,MAAM;AAAA,EAAK,UAAU;AACjC;;;AD1CO,SAAS,oBAAoB,YAAoB,QAAyC;AAC/F,QAAM,eAAe,OAAO,QAAQ,MAAM;AAE1C,MAAI,aAAa,WAAW,GAAG;AAC7B,WAAO,GAAG,UAAU;AAAA,EACtB;AAEA,QAAM,WAAW,aAAa,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,EAAE,EAAE,KAAK,IAAI;AAEpF,SAAO,GAAG,UAAU,IAAI,QAAQ;AAClC;AAOO,IAAM,2BAAN,MAAkE;AAAA,EAC9D,aAAa;AAAA,EAEtB,MAAM,WAAW,QAA2D;AAC1E,UAAM,WAAW,OAAO,OAAO,YAAY,OAAO,QAAQ,EAAE;AAC5D,UAAM,aAAa,OAAO,OAAO,WAAW,EAAE;AAC9C,UAAM,eAAe,QAAQ,QAAQ,IAAI,GAAG,QAAQ;AAEpD,QAAI,CAAC,WAAW,YAAY,GAAG;AAC7B,aAAO;AAAA,QACL,SAAS,oBAAoB,KAAK,YAAY,MAAM;AAAA,QACpD,SAAS,kBAAkB,UAAU,UAAU;AAAA,MACjD;AAAA,IACF;AAEA,UAAM,aAAa,aAAa,cAAc,OAAO;AACrD,UAAM,OAAO,YAAY,UAAU,YAAY,YAAY,YAAY,UAAU;AAEjF,WAAO;AAAA,MACL,SAAS,oBAAoB,KAAK,YAAY,MAAM;AAAA,MACpD,SAAS;AAAA,IACX;AAAA,EACF;AACF;AAMO,IAAM,0BAAN,MAAiE;AAAA,EAC7D,aAAa;AAAA,EAEtB,MAAM,WAAW,QAA2D;AAC1E,UAAM,WAAW,OAAO,OAAO,YAAY,OAAO,QAAQ,EAAE;AAC5D,UAAM,eAAe,QAAQ,QAAQ,IAAI,GAAG,QAAQ;AAIpD,QAAI,aAAa,QAAQ;AACvB,YAAM,aAAa,OAAO,OAAO,OAAO;AAExC,UAAI,CAAC,WAAW,YAAY,GAAG;AAC7B,eAAO;AAAA,UACL,SAAS,oBAAoB,KAAK,YAAY,MAAM;AAAA,UACpD,SAAS,kBAAkB,UAAU,UAAU;AAAA,QACjD;AAAA,MACF;AAEA,YAAM,aAAa,aAAa,cAAc,OAAO;AACrD,YAAM,OAAO,YAAY,UAAU,YAAY,YAAY,YAAY,UAAU;AAEjF,aAAO;AAAA,QACL,SAAS,oBAAoB,KAAK,YAAY,MAAM;AAAA,QACpD,SAAS;AAAA,MACX;AAAA,IACF;AAGA,QAAI,cAAc,QAAQ;AACxB,YAAM,WAAW,OAAO,OAAO,QAAQ;AACvC,aAAO;AAAA,QACL,SAAS,oBAAoB,KAAK,YAAY,MAAM;AAAA,QACpD,SAAS;AAAA,EAAc,QAAQ;AAAA,MACjC;AAAA,IACF;AAGA,WAAO;AAAA,MACL,SAAS,oBAAoB,KAAK,YAAY,MAAM;AAAA,IACtD;AAAA,EACF;AACF;AAMO,IAAM,yBAAN,MAAgE;AAAA,EACrE,YAA4B,YAAoB;AAApB;AAAA,EAAqB;AAAA,EAEjD,MAAM,WAAW,QAA2D;AAC1E,WAAO;AAAA,MACL,SAAS,oBAAoB,KAAK,YAAY,MAAM;AAAA,IACtD;AAAA,EACF;AACF;AAMO,IAAM,0BAAqD;AAAA,EAChE,IAAI,yBAAyB;AAAA,EAC7B,IAAI,wBAAwB;AAAA;AAE9B;;;ADlGO,IAAM,kBAAN,MAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAW3B,YACmB,QACA,KACA,UACA,UACjB;AAJiB;AACA;AACA;AACA;AAGjB,eAAW,YAAY,yBAAyB;AAC9C,WAAK,iBAAiB,QAAQ;AAAA,IAChC;AAAA,EACF;AAAA,EApBQ,YAAY,oBAAI,IAAqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA2B7D,iBAAiB,UAAyC;AAExD,SAAK,UAAU,IAAI,SAAS,WAAW,YAAY,GAAG,QAAQ;AAAA,EAChE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,gBAAgB,YAAkC;AAChD,UAAM,iBAAiB,WAAW,YAAY;AAG9C,eAAW,CAAC,YAAY,IAAI,KAAK,OAAO,QAAQ,KAAK,OAAO,eAAe,GAAG;AAC5E,UAAI,WAAW,YAAY,MAAM,gBAAgB;AAC/C,eAAO;AAAA,MACT;AAAA,IACF;AAGA,QAAI,OAAO,KAAK,OAAO,iBAAiB;AACtC,aAAO,KAAK,OAAO,gBAAgB,GAAG;AAAA,IACxC;AAGA,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,gBACJ,YACA,QACyB;AACzB,UAAM,OAAO,KAAK,gBAAgB,UAAU;AAE5C,QAAI,SAAS,WAAW;AACtB,aAAO,EAAE,UAAU,KAAK;AAAA,IAC1B;AAEA,QAAI,SAAS,UAAU;AACrB,aAAO;AAAA,QACL,UAAU;AAAA,QACV,QAAQ,GAAG,UAAU;AAAA,MACvB;AAAA,IACF;AAGA,WAAO,KAAK,kBAAkB,YAAY,MAAM;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,kBACZ,YACA,QACyB;AAEzB,UAAM,WACJ,KAAK,UAAU,IAAI,WAAW,YAAY,CAAC,KAAK,IAAI,uBAAuB,UAAU;AAEvF,UAAM,UAAU,MAAM,SAAS,WAAW,MAAM;AAGhD,SAAK,UAAU,MAAM;AAIrB,QAAI,KAAK,UAAU,YAAY;AAC7B,WAAK,SAAS,WAAW;AACzB,WAAK,SAAS,aAAa;AAAA,IAC7B;AAEA,QAAI;AAEF,WAAK,IAAI,OAAO,MAAM;AAAA,EAAKC,OAAM,OAAO,8BAAuB,CAAC,IAAI,QAAQ,OAAO;AAAA,CAAI;AAEvF,UAAI,QAAQ,SAAS;AACnB,aAAK,IAAI,OAAO,MAAM;AAAA,EAAK,kBAAkB,QAAQ,OAAO,CAAC;AAAA,CAAI;AAAA,MACnE;AAGA,YAAM,WAAW,MAAM,KAAK,OAAO,wCAAmC;AAGtE,YAAM,aAAa,aAAa,MAAM,SAAS,YAAY,MAAM;AAEjE,UAAI,YAAY;AACd,aAAK,IAAI,OAAO,MAAM,MAAMA,OAAM,MAAM,iBAAY,CAAC;AAAA;AAAA,CAAM;AAC3D,eAAO,EAAE,UAAU,KAAK;AAAA,MAC1B;AAEA,WAAK,IAAI,OAAO,MAAM,MAAMA,OAAM,IAAI,eAAU,CAAC;AAAA;AAAA,CAAM;AACvD,aAAO,EAAE,UAAU,OAAO,QAAQ,YAAY,mBAAmB;AAAA,IACnE,UAAE;AAEA,WAAK,UAAU,QAAQ;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,OAAO,SAAkC;AACrD,UAAM,KAAK,gBAAgB;AAAA,MACzB,OAAO,KAAK,IAAI;AAAA,MAChB,QAAQ,KAAK,IAAI;AAAA,IACnB,CAAC;AACD,QAAI;AACF,YAAM,SAAS,MAAM,GAAG,SAAS,OAAO;AACxC,aAAO,OAAO,KAAK;AAAA,IACrB,UAAE;AACA,SAAG,MAAM;AAAA,IACX;AAAA,EACF;AACF;;;AGpLA;AACA;AAHA,SAAS,SAAS;AAaX,IAAM,UAAU,aAAa;AAAA,EAClC,MAAM;AAAA,EACN,aACE;AAAA,EACF,QAAQ,EAAE,OAAO;AAAA,IACf,UAAU,EACP,OAAO,EACP,SAAS,wDAAwD;AAAA,EACtE,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,oBAAoB,QAAQ;AAAA,EACxC;AACF,CAAC;AAQM,IAAM,WAAW,aAAa;AAAA,EACnC,MAAM;AAAA,EACN,aAAa;AAAA,EACb,QAAQ,EAAE,OAAO;AAAA,IACf,SAAS,EACN,OAAO,EACP,SAAS,EACT,SAAS,gDAAgD;AAAA,IAC5D,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,aACE;AAAA,EACF,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,mBAAmB,gBAAgB;AAAA,EAC/C;AACF,CAAC;AAKM,IAAM,iBAAiB,CAAC,SAAS,UAAU,MAAM;;;ACvHxD;AAJA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,qBAAqB;;;ACF9B,OAAOC,SAAQ;AACf,OAAOC,WAAU;AACjB,SAAS,KAAAC,UAAS;;;ACFlB,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;;;ADxBA,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;;;AE7MD,OAAOG,SAAQ;AACf,SAAS,KAAAC,UAAS;AAQX,IAAM,WAAW,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;AAQlB,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,YAAM,iBAAiB,IAAI,QAAe,CAAC,GAAG,WAAW;AACvD,mBAAW,MAAM;AACf,eAAK,KAAK;AACV,iBAAO,IAAI,MAAM,oCAAoC,CAAC;AAAA,QACxD,GAAG,GAAK;AAAA,MACV,CAAC;AAGD,YAAM,WAAW,MAAM,QAAQ,KAAK,CAAC,KAAK,QAAQ,cAAc,CAAC;AAGjE,YAAM,SAAS,MAAM,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AACpD,YAAM,SAAS,MAAM,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AACpD,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;;;AC5GD,SAAS,KAAAC,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,GACN,OAAO,EACP,QAAQ,GAAK,EACb,SAAS,0CAA0C;AAAA,EACxD,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,EAAE,MAAM,CAAC,MAAM,MAAM,UAAU,OAAO,aAAa,UAAU,sCAAsC,GAAG,SAAS,IAAM;AAAA,MAC7H,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,QACN,MAAM;AAAA,UACJ;AAAA,UAAM;AAAA,UAAM;AAAA,UAAU;AAAA,UAAO;AAAA,UAC7B;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;AAGD,YAAM,WAAW,MAAM,QAAQ,KAAK,CAAC,KAAK,QAAQ,cAAc,CAAC;AAGjE,UAAI,WAAW;AACb,qBAAa,SAAS;AAAA,MACxB;AAGA,YAAM,SAAS,MAAM,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AACpD,YAAM,SAAS,MAAM,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAGpD,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;;;ACxGM,IAAM,wBAAoD;AAAA,EAC/D,eAAe;AAAA,EACf,UAAU;AAAA,EACV,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AACd;AAQO,SAAS,iBAAiB,MAAsC;AACrE,SAAO,sBAAsB,IAAI;AACnC;AAQO,SAAS,oBAAoB,MAAuB;AACzD,SAAO,QAAQ;AACjB;;;AP/BA,IAAM,gBAAgB,CAAC,KAAK,KAAK,GAAG;AACpC,IAAM,iBAAiB;AAOvB,SAAS,aAAa,OAAqC;AACzD,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;AAQA,SAAS,oBAAoB,OAA+C;AAC1E,MAAI,OAAO,UAAU,YAAY;AAC/B,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,MAAM;AAExB,SAAO,QAAQ,SAAS,MAAM,qBAAqB,cAAc,aAAa,SAAS;AACzF;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,WAAsC;AAEtE,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,SAAO,cAAc,YAAY,EAAE;AACrC;AAUO,SAAS,yBAAyB,eAAsC;AAC7E,QAAM,UAAwB,CAAC;AAC/B,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,cAAc,aAAa,KAAK,GAAG;AACtD,cAAQ,KAAK,KAAmB;AAChC;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;AAkBA,eAAsB,YACpB,YACA,KACA,WAAiC,CAAC,cAAc,OAAO,YAChC;AACvB,QAAM,UAAwB,CAAC;AAE/B,aAAW,aAAa,YAAY;AAElC,UAAM,UAAU,kBAAkB,SAAS;AAC3C,QAAI,SAAS;AACX,cAAQ,KAAK,OAAO;AACpB;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;;;AQ7OA,SAAS,OAAO,aAAAC,kBAAiB;AACjC,SAAS,eAAe;AACxB,SAAS,YAAY;AAOd,IAAM,sBAAsB,KAAK,QAAQ,GAAG,WAAW,MAAM;AAQ7D,SAAS,cAAc,QAAsC,QAAoC;AACtG,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;AAC9C,UAAM,KAAK,IAAI,WAAW,EAAE;AAC5B,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;;;AChFA;AALA,OAAOC,YAAW;AAClB,SAAS,4BAA4B;;;ACcrC,OAAOC,YAAW;AAClB,SAAS,cAAoC;AAC7C,SAAS,sBAAsB;AAW/B,IAAI,mBAAmB;AAoBvB,SAAS,yBAA+B;AACtC,MAAI,CAAC,kBAAkB;AAErB,IAAAA,OAAM,QAAQ,QAAQ,IAAI,WAAW,IAAI;AAIzC,WAAO;AAAA,MACL,eAAe;AAAA;AAAA,QAEb,QAAQA,OAAM;AAAA,QACd,IAAIA,OAAM;AAAA,QACV,KAAKA,OAAM,IAAI,KAAK;AAAA;AAAA,QAGpB,MAAMA,OAAM;AAAA,QACZ,UAAUA,OAAM;AAAA;AAAA,QAGhB,SAASA,OAAM,MAAM;AAAA,QACrB,cAAcA,OAAM,QAAQ,UAAU;AAAA;AAAA,QAGtC,MAAMA,OAAM;AAAA,QACZ,MAAMA,OAAM,KAAK;AAAA;AAAA,QAGjB,YAAYA,OAAM,KAAK;AAAA;AAAA,QAGvB,KAAK;AAAA;AAAA,QACL,UAAUA,OAAM;AAAA;AAAA,MAClB,CAAC;AAAA,IACH;AACA,uBAAmB;AAAA,EACrB;AACF;AAqBO,SAAS,eAAe,MAAsB;AACnD,yBAAuB;AACvB,MAAI,WAAW,OAAO,MAAM,IAAI;AAKhC,aAAW,SACR,QAAQ,kBAAkB,CAAC,GAAG,YAAYA,OAAM,KAAK,OAAO,CAAC,EAE7D,QAAQ,+BAA+B,CAAC,GAAG,YAAYA,OAAM,OAAO,OAAO,CAAC;AAG/E,SAAO,SAAS,QAAQ;AAC1B;AASA,SAAS,yBAAiC;AACxC,QAAM,SAAS,CAACA,OAAM,KAAKA,OAAM,QAAQA,OAAM,OAAOA,OAAM,MAAMA,OAAM,MAAMA,OAAM,OAAO;AAC3F,QAAM,OAAO;AAEb,QAAM,QAAQ,QAAQ,OAAO,WAAW;AACxC,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,cAAU,OAAO,IAAI,OAAO,MAAM,EAAE,IAAI;AAAA,EAC1C;AACA,SAAO;AACT;AAeO,SAAS,6BAA6B,MAAsB;AACjE,QAAM,WAAW,eAAe,IAAI;AACpC,QAAM,YAAY,uBAAuB;AACzC,SAAO;AAAA,EAAK,SAAS;AAAA,EAAK,QAAQ;AAAA,EAAK,SAAS;AAAA;AAClD;AAkBO,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;AAgEO,SAAS,cAAc,UAA0C;AACtE,QAAM,QAAkB,CAAC;AAGzB,MAAI,SAAS,eAAe,QAAW;AACrC,UAAM,WAAWA,OAAM,KAAK,IAAI,SAAS,UAAU,EAAE;AACrD,QAAI,SAAS,OAAO;AAClB,YAAM,KAAK,GAAG,QAAQ,IAAIA,OAAM,QAAQ,SAAS,KAAK,CAAC,EAAE;AAAA,IAC3D,OAAO;AACL,YAAM,KAAK,QAAQ;AAAA,IACrB;AAAA,EACF,WAAW,SAAS,OAAO;AAEzB,UAAM,KAAKA,OAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,EAC1C;AAGA,MAAI,SAAS,OAAO;AAClB,UAAM,EAAE,aAAa,cAAc,mBAAmB,yBAAyB,IAC7E,SAAS;AACX,UAAM,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,OAAO,IAAI,aAAa,WAAW,CAAC,EAAE,CAAC;AAEzE,QAAI,qBAAqB,oBAAoB,GAAG;AAC9C,YAAM,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,KAAK,IAAI,aAAa,iBAAiB,CAAC,EAAE,CAAC;AAAA,IAC/E;AAEA,QAAI,4BAA4B,2BAA2B,GAAG;AAC5D,YAAM,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,QAAQ,IAAI,aAAa,wBAAwB,CAAC,EAAE,CAAC;AAAA,IACzF;AACA,UAAM,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,MAAM,IAAI,aAAa,YAAY,CAAC,EAAE,CAAC;AAAA,EAC3E;AAGA,MAAI,SAAS,mBAAmB,UAAa,SAAS,iBAAiB,GAAG;AACxE,UAAM,KAAKA,OAAM,IAAI,GAAG,SAAS,cAAc,GAAG,CAAC;AAAA,EACrD;AAGA,MAAI,SAAS,SAAS,UAAa,SAAS,OAAO,GAAG;AACpD,UAAM,KAAKA,OAAM,KAAK,IAAI,WAAW,SAAS,IAAI,CAAC,EAAE,CAAC;AAAA,EACxD;AAGA,MAAI,SAAS,cAAc;AACzB,UAAM,KAAKA,OAAM,IAAI,SAAS,YAAY,CAAC;AAAA,EAC7C;AAGA,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AAGA,SAAO,MAAM,KAAKA,OAAM,IAAI,KAAK,CAAC;AACpC;AA2CO,SAAS,qBAAqB,UAAiD;AACpF,QAAM,QAAkB,CAAC;AAGzB,MAAI,SAAS,gBAAgB,UAAa,SAAS,cAAc,GAAG;AAClE,UAAM,KAAKA,OAAM,IAAI,QAAQ,IAAIA,OAAM,QAAQ,IAAI,aAAa,SAAS,WAAW,CAAC,EAAE,CAAC;AAAA,EAC1F;AAGA,MAAI,SAAS,eAAe,UAAa,SAAS,aAAa,GAAG;AAChE,UAAM,KAAKA,OAAM,KAAK,IAAI,SAAS,UAAU,EAAE,CAAC;AAAA,EAClD;AAGA,MAAI,SAAS,mBAAmB,UAAa,SAAS,iBAAiB,GAAG;AACxE,UAAM,KAAKA,OAAM,IAAI,GAAG,SAAS,cAAc,GAAG,CAAC;AAAA,EACrD;AAGA,MAAI,SAAS,SAAS,UAAa,SAAS,OAAO,GAAG;AACpD,UAAM,KAAKA,OAAM,KAAK,IAAI,WAAW,SAAS,IAAI,CAAC,EAAE,CAAC;AAAA,EACxD;AAEA,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,KAAKA,OAAM,IAAI,KAAK,CAAC;AACpC;AA6EA,SAAS,uBAAuB,QAAqD;AACnF,MAAI,CAAC,UAAU,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;AAC/C,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,QAAQ,MAAM,EACzB,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AAErB,QAAI;AACJ,QAAI,OAAO,UAAU,UAAU;AAE7B,kBAAY,MAAM,SAAS,KAAK,GAAG,MAAM,MAAM,GAAG,EAAE,CAAC,WAAM;AAAA,IAC7D,WAAW,OAAO,UAAU,aAAa,OAAO,UAAU,UAAU;AAClE,kBAAY,OAAO,KAAK;AAAA,IAC1B,OAAO;AAEL,YAAM,OAAO,KAAK,UAAU,KAAK;AACjC,kBAAY,KAAK,SAAS,KAAK,GAAG,KAAK,MAAM,GAAG,EAAE,CAAC,WAAM;AAAA,IAC3D;AAEA,WAAO,GAAGA,OAAM,IAAI,GAAG,CAAC,GAAGA,OAAM,IAAI,GAAG,CAAC,GAAGA,OAAM,KAAK,SAAS,CAAC;AAAA,EACnE,CAAC,EACA,KAAKA,OAAM,IAAI,IAAI,CAAC;AACzB;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;AAEO,SAASC,qBAAoB,QAA8B;AAEhE,QAAM,cAAcD,OAAM,QAAQ,KAAK,OAAO,UAAU;AACxD,QAAM,YAAYA,OAAM,IAAI,GAAG,KAAK,MAAM,OAAO,eAAe,CAAC,IAAI;AAGrE,QAAM,YAAY,uBAAuB,OAAO,UAAU;AAC1D,QAAM,cAAc,YAAY,GAAGA,OAAM,IAAI,GAAG,CAAC,GAAG,SAAS,GAAGA,OAAM,IAAI,GAAG,CAAC,KAAK;AAGnF,MAAI,OAAO,OAAO;AAChB,UAAM,WAAW,OAAO,MAAM,SAAS,KAAK,GAAG,OAAO,MAAM,MAAM,GAAG,EAAE,CAAC,WAAM,OAAO;AACrF,WAAO,GAAGA,OAAM,IAAI,QAAG,CAAC,IAAI,WAAW,GAAG,WAAW,IAAIA,OAAM,IAAI,QAAQ,CAAC,IAAI,QAAQ,IAAI,SAAS;AAAA,EACvG;AAGA,MAAI;AACJ,MAAI,OAAO,eAAe,UAAa,OAAO,aAAa,GAAG;AAC5D,kBAAcA,OAAM,MAAM,GAAG,aAAa,OAAO,UAAU,CAAC,SAAS;AAAA,EACvE,WAAW,OAAO,QAAQ;AACxB,UAAM,cAAc,OAAO,WAAW,OAAO,QAAQ,OAAO;AAC5D,kBAAc,cAAc,IAAIA,OAAM,MAAM,YAAY,WAAW,CAAC,IAAIA,OAAM,IAAI,WAAW;AAAA,EAC/F,OAAO;AACL,kBAAcA,OAAM,IAAI,WAAW;AAAA,EACrC;AAGA,QAAM,OAAO,OAAO,aAAaA,OAAM,OAAO,QAAG,IAAIA,OAAM,MAAM,QAAG;AACpE,QAAM,cAAc,GAAG,IAAI,IAAI,WAAW,GAAG,WAAW,IAAIA,OAAM,IAAI,QAAG,CAAC,IAAI,WAAW,IAAI,SAAS;AAGtG,MAAI,OAAO,eAAe,cAAc,OAAO,YAAY,SAAS;AAClE,UAAM,UAAU,OAAO,OAAO,WAAW,OAAO;AAChD,UAAM,WAAW,6BAA6B,OAAO;AACrD,WAAO,GAAG,WAAW;AAAA,EAAK,QAAQ;AAAA,EACpC;AAEA,SAAO;AACT;;;ADjhBO,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,MAAM,MAAoB;AACxB,QAAI,CAAC,MAAM;AACT;AAAA,IACF;AACA,SAAK,OAAO,MAAM,IAAI;AACtB,SAAK,mBAAmB,KAAK,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,QAA4B;AACxD,SAAO,QAAQ,OAAO,KAAK;AAC7B;AAGA,IAAM,UAAU;AAgBhB,IAAM,iBAAiB;AACvB,IAAM,SAAS;AAiBR,SAAS,qBACd,OACA,OACA,SACqB;AAErB,MAAI,CAAC,MAAM,SAAS,OAAO,MAAM,eAAe,YAAY;AAC1D,WAAO;AAAA,EACT;AAEA,MAAI,aAAoC;AAExC,QAAM,aAAa,CAAC,SAAiB;AAEnC,QAAI,KAAK,CAAC,MAAM,UAAU,SAAS;AAEjC,UAAI,YAAY;AACd,qBAAa,UAAU;AACvB,qBAAa;AAAA,MACf;AACA,cAAQ;AACR;AAAA,IACF;AAEA,QAAI,KAAK,CAAC,MAAM,SAAS;AACvB,UAAI,KAAK,WAAW,GAAG;AAErB,qBAAa,WAAW,MAAM;AAC5B,gBAAM;AAAA,QACR,GAAG,cAAc;AAAA,MACnB,OAAO;AAEL,YAAI,YAAY;AACd,uBAAa,UAAU;AACvB,uBAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF,OAAO;AAEL,UAAI,YAAY;AACd,qBAAa,UAAU;AACvB,qBAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAGA,QAAM,WAAW,IAAI;AACrB,QAAM,OAAO;AACb,QAAM,GAAG,QAAQ,UAAU;AAG3B,SAAO,MAAM;AACX,QAAI,YAAY;AACd,mBAAa,UAAU;AAAA,IACzB;AACA,UAAM,eAAe,QAAQ,UAAU;AACvC,UAAM,WAAW,KAAK;AACtB,UAAM,MAAM;AAAA,EACd;AACF;AASA,IAAM,yBAAyB;AA4BxB,SAAS,qBACd,UACA,QACA,mBACA,SAAgC,QAAQ,QAC5B;AACZ,MAAI,iBAAiB;AAErB,QAAM,UAAU,MAAM;AACpB,UAAM,MAAM,KAAK,IAAI;AAErB,QAAI,kBAAkB,GAAG;AAEvB,eAAS;AAET,uBAAiB;AACjB;AAAA,IACF;AAGA,QAAI,MAAM,iBAAiB,wBAAwB;AACjD,aAAO;AACP;AAAA,IACF;AAGA,qBAAiB;AACjB,WAAO,MAAME,OAAM,IAAI,kCAAkC,CAAC;AAAA,EAC5D;AAEA,UAAQ,GAAG,UAAU,OAAO;AAE5B,SAAO,MAAM;AACX,YAAQ,eAAe,UAAU,OAAO;AAAA,EAC1C;AACF;AAEA,IAAM,iBAAiB,CAAC,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,QAAG;AACxE,IAAM,mBAAmB;AAelB,IAAM,iBAAN,MAAqB;AAAA,EA6B1B,YACmB,QACA,OACA,eACjB;AAHiB;AACA;AACA;AAAA,EAChB;AAAA;AAAA,EA/BK,aAAa;AAAA,EACb,WAAkD;AAAA,EAClD,eAAqD;AAAA,EACrD,YAAY;AAAA,EACZ,cAAc;AAAA;AAAA,EAGd,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgB3B,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,IACrC,KAAK,MAAM,MAAM,GAAG,EAAE,CAAC,IACvB,KAAK;AAET,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;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;AACrB,UAAM,UAAU,eAAe,KAAK,eAAe,eAAe,MAAM;AAExE,QAAI,KAAK,SAAS,aAAa;AAC7B,WAAK,oBAAoB,OAAO;AAAA,IAClC,OAAO;AACL,WAAK,qBAAqB,OAAO;AAAA,IACnC;AACA,SAAK,cAAc;AAAA,EACrB;AAAA,EAEQ,oBAAoB,SAAuB;AACjD,UAAM,YAAY,KAAK,IAAI,IAAI,KAAK,iBAAiB,KAAM,QAAQ,CAAC;AAGpE,UAAM,YAAY,KAAK,4BACnB,KAAK,MAAM,KAAK,kBAAkB,wBAAwB,IAC1D,KAAK;AAGT,UAAM,QAAkB,CAAC;AAGzB,UAAM,WAAWA,OAAM,KAAK,IAAI,KAAK,gBAAgB,EAAE;AACvD,QAAI,KAAK,OAAO;AACd,YAAM,KAAK,GAAG,QAAQ,IAAIA,OAAM,QAAQ,KAAK,KAAK,CAAC,EAAE;AAAA,IACvD,OAAO;AACL,YAAM,KAAK,QAAQ;AAAA,IACrB;AAGA,UAAM,eAAe,KAAK,uBAAuB;AACjD,QAAI,iBAAiB,MAAM;AACzB,YAAM,YAAY,GAAG,KAAK,MAAM,YAAY,CAAC;AAC7C,UAAI,gBAAgB,IAAI;AACtB,cAAM,KAAKA,OAAM,IAAI,SAAS,CAAC;AAAA,MACjC,WAAW,gBAAgB,IAAI;AAC7B,cAAM,KAAKA,OAAM,OAAO,SAAS,CAAC;AAAA,MACpC,OAAO;AACL,cAAM,KAAKA,OAAM,MAAM,SAAS,CAAC;AAAA,MACnC;AAAA,IACF;AAGA,QAAI,KAAK,kBAAkB,GAAG;AAC5B,YAAM,SAAS,KAAK,2BAA2B,MAAM;AACrD,YAAM,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,OAAO,IAAI,MAAM,GAAG,aAAa,KAAK,eAAe,CAAC,EAAE,CAAC;AAAA,IAC7F;AAGA,QAAI,KAAK,eAAe,YAAY,GAAG;AACrC,YAAM,SAAS,KAAK,4BAA4B,MAAM;AACtD,YAAM,KAAKA,OAAM,IAAI,QAAG,IAAIA,OAAM,MAAM,IAAI,MAAM,GAAG,aAAa,SAAS,CAAC,EAAE,CAAC;AAAA,IACjF;AAGA,UAAM,KAAKA,OAAM,IAAI,GAAG,OAAO,GAAG,CAAC;AAGnC,UAAM,WAAW,KAAK,yBAAyB,SAAS;AACxD,QAAI,WAAW,GAAG;AAChB,YAAM,KAAKA,OAAM,KAAK,IAAI,WAAW,QAAQ,CAAC,EAAE,CAAC;AAAA,IACnD;AAEA,SAAK,OAAO,MAAM,KAAK,MAAM,KAAKA,OAAM,IAAI,KAAK,CAAC,CAAC,IAAIA,OAAM,KAAK,OAAO,CAAC,EAAE;AAAA,EAC9E;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,EAEQ,qBAAqB,SAAuB;AAClD,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,SAAK,OAAO,MAAM,KAAK,MAAM,KAAKA,OAAM,IAAI,KAAK,CAAC,CAAC,IAAIA,OAAM,KAAK,OAAO,CAAC,EAAE;AAAA,EAC9E;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,QAAI,KAAK,aAAa;AAKpB,WAAK,OAAO,MAAM,iBAAiB;AACnC,WAAK,cAAc;AAAA,IACrB;AAAA,EACF;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;;;AEtuBO,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,OAAO,aAAa,gBAAgB,oBAAoB,gBAAgB,WAAW,kBAAkB,CAAC;AAC3G;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,OAAO,aAAa,gBAAgB,oBAAoB,gBAAgB,WAAW,kBAAkB,CAAC,EACtG,OAAO,aAAa,QAAQ,oBAAoB,MAAM,EACtD,OAAO,aAAa,UAAU,oBAAoB,QAAQ,EAC1D,OAAO,aAAa,UAAU,oBAAoB,QAAQ,EAC1D,OAAO,aAAa,WAAW,oBAAoB,SAAS;AACjE;AAKO,SAAS,wBAAwB,QAA8D;AACpG,QAAM,SAA0C,CAAC;AACjD,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,QAA2D;AAC9F,QAAM,SAAuC,CAAC;AAC9C,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;AAChC,WAAO,iBAAiB,OAAO,iBAAiB;AAClD,MAAI,OAAO,UAAU,OAAW,QAAO,QAAQ,OAAO;AACtD,MAAI,OAAO,kBAAkB,MAAM,OAAW,QAAO,iBAAiB,OAAO,kBAAkB;AAC/F,MAAI,OAAO,WAAW,OAAW,QAAO,SAAS,OAAO;AACxD,MAAI,OAAO,uBAAuB,MAAM;AACtC,WAAO,sBAAsB,OAAO,uBAAuB;AAC7D,SAAO;AACT;;;AClJO,IAAM,0BAA6C,CAAC,MAAM,IAAI;AAkE9D,IAAM,qBAAqB,oBAAI,IAAI;AAAA,EACxC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAmCM,IAAM,qBAAqB;AAK3B,IAAM,yBAA0C;AAChD,IAAM,4BAA6C;AAKnD,IAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,iBAAiB;AAKvB,IAAM,0BAA0B;;;AC1JvC,SAAS,cAAAC,aAAY,gBAAAC,qBAAoB;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,gBACd,UACA,YACA,YACM;AAEN,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;;;ADzHA,IAAM,uBAA6C,CAAC,WAAW,UAAU,mBAAmB;AAuG5F,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;AAAA,EACA;AAAA;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,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF,CAAC;AAGD,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;AAKA,SAAS,uBAAuB,OAAgB,SAAuC;AACrF,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACvE,UAAM,IAAI;AAAA,MACR,IAAI,OAAO;AAAA,IACb;AAAA,EACF;AAEA,QAAM,SAA+B,CAAC;AACtC,aAAW,CAAC,YAAY,IAAI,KAAK,OAAO,QAAQ,KAAgC,GAAG;AACjF,QAAI,OAAO,SAAS,UAAU;AAC5B,YAAM,IAAI;AAAA,QACR,IAAI,OAAO,qBAAqB,UAAU;AAAA,MAC5C;AAAA,IACF;AACA,QAAI,CAAC,qBAAqB,SAAS,IAA0B,GAAG;AAC9D,YAAM,IAAI;AAAA,QACR,IAAI,OAAO,qBAAqB,UAAU,oBAAoB,qBAAqB,KAAK,IAAI,CAAC;AAAA,MAC/F;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,SAC4B;AAC5B,QAAM,SAAqC,CAAC;AAE5C,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;AACA,MAAI,YAAY,KAAK;AACnB,WAAO,SAAS,gBAAgB,IAAI,QAAQ,UAAU,OAAO;AAAA,EAC/D;AACA,MAAI,2BAA2B,KAAK;AAClC,UAAM,OAAO,eAAe,IAAI,uBAAuB,GAAG,yBAAyB,OAAO;AAC1F,QAAI,SAAS,QAAQ,SAAS,MAAM;AAClC,YAAM,IAAI,YAAY,IAAI,OAAO,8CAA8C;AAAA,IACjF;AACA,WAAO,uBAAuB,IAAI;AAAA,EACpC;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,oBAAoB,OAAO,eAAe,GAAG,iBAAiB,OAAO;AAAA,EACjG;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,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,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,oBAAoB,OAAO,eAAe,GAAG,iBAAiB,OAAO;AAAA,EACjG;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;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,WAAW;AAC5B,eAAO,UAAU,sBAAsB,OAAO,GAAG;AAAA,MACnD,WAAW,QAAQ,UAAU;AAC3B,eAAO,SAAS,qBAAqB,OAAO,GAAG;AAAA,MACjD,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,CAACC,YAAW,UAAU,GAAG;AAC3B,WAAO,CAAC;AAAA,EACV;AAEA,MAAI;AACJ,MAAI;AACF,cAAUC,cAAa,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,CAAC,UAAU,YAAY,SAAS,WAAW,QAAQ,CAAC;AAC7E,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;;;AE7+BA,IAAM,oBAAoB,oBAAI,IAAI,CAAC,UAAU,UAAU,YAAY,CAAC;AAKpE,SAASC,gBAAe,OAAgB,KAAa,SAAyB;AAC5E,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,mBAAmB;AAAA,EAC9D;AACA,SAAO;AACT;AAKA,SAASC,iBAAgB,OAAgB,KAAa,SAA0B;AAC9E,MAAI,OAAO,UAAU,WAAW;AAC9B,UAAM,IAAI,YAAY,IAAI,OAAO,KAAK,GAAG,oBAAoB;AAAA,EAC/D;AACA,SAAO;AACT;AAKA,SAASC,qBAAoB,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,wBAAwB,OAAgB,KAAa,SAAkC;AAC9F,QAAM,MAAMF,gBAAe,OAAO,KAAK,OAAO;AAC9C,MAAI,CAAC,wBAAwB,SAAS,GAAsB,GAAG;AAC7D,UAAM,IAAI;AAAA,MACR,IAAI,OAAO,KAAK,GAAG,oBAAoB,wBAAwB,KAAK,IAAI,CAAC;AAAA,IAC3E;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,oBAAoB,OAAgB,OAAe,SAA8B;AACxF,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,MAAM,QAAQ,KAAK,GAAG;AACvE,UAAM,IAAI,YAAY,IAAI,OAAO,YAAY,KAAK,mBAAmB;AAAA,EACvE;AAEA,QAAM,SAAS;AACf,QAAM,eAAe,GAAG,OAAO,WAAW,KAAK;AAG/C,aAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AACrC,QAAI,CAAC,kBAAkB,IAAI,GAAG,GAAG;AAC/B,YAAM,IAAI,YAAY,IAAI,YAAY,KAAK,GAAG,8BAA8B;AAAA,IAC9E;AAAA,EACF;AAGA,MAAI,EAAE,YAAY,SAAS;AACzB,UAAM,IAAI,YAAY,IAAI,YAAY,mCAAmC;AAAA,EAC3E;AACA,MAAI,EAAE,YAAY,SAAS;AACzB,UAAM,IAAI,YAAY,IAAI,YAAY,mCAAmC;AAAA,EAC3E;AACA,MAAI,EAAE,gBAAgB,SAAS;AAC7B,UAAM,IAAI,YAAY,IAAI,YAAY,uCAAuC;AAAA,EAC/E;AAEA,SAAO;AAAA,IACL,QAAQA,gBAAe,OAAO,QAAQ,UAAU,YAAY;AAAA,IAC5D,QAAQA,gBAAe,OAAO,QAAQ,UAAU,YAAY;AAAA,IAC5D,YAAY,wBAAwB,OAAO,YAAY,cAAc,YAAY;AAAA,EACnF;AACF;AAKA,SAAS,oBAAoB,OAAgB,SAAgC;AAC3E,MAAI,CAAC,MAAM,QAAQ,KAAK,GAAG;AACzB,UAAM,IAAI,YAAY,IAAI,OAAO,qCAAqC;AAAA,EACxE;AAEA,QAAM,SAAwB,CAAC;AAC/B,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,WAAO,KAAK,oBAAoB,MAAM,CAAC,GAAG,GAAG,OAAO,CAAC;AAAA,EACvD;AACA,SAAO;AACT;AAUO,SAAS,qBAAqB,KAAc,SAA+B;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;AAEA,QAAM,SAAuB,CAAC;AAE9B,MAAI,aAAa,QAAQ;AACvB,WAAO,UAAUC,iBAAgB,OAAO,SAAS,WAAW,OAAO;AAAA,EACrE;AAEA,MAAI,gBAAgB,QAAQ;AAC1B,WAAO,aAAaD,gBAAe,OAAO,YAAY,cAAc,OAAO;AAAA,EAC7E;AAEA,MAAI,oBAAoB,QAAQ;AAC9B,WAAO,gBAAgB,IAAI;AAAA,MACzB,OAAO,gBAAgB;AAAA,MACvB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,uBAAuB,QAAQ;AACjC,WAAO,mBAAmB,IAAI;AAAA,MAC5B,OAAO,mBAAmB;AAAA,MAC1B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,YAAY,QAAQ;AACtB,WAAO,SAAS,oBAAoB,OAAO,QAAQ,OAAO;AAAA,EAC5D;AAEA,MAAI,cAAc,QAAQ;AACxB,WAAO,UAAU,IAAIE,qBAAoB,OAAO,UAAU,GAAG,YAAY,OAAO;AAAA,EAClF;AAEA,MAAI,gBAAgB,QAAQ;AAC1B,WAAO,YAAY,IAAIF,gBAAe,OAAO,YAAY,GAAG,cAAc,OAAO;AAAA,EACnF;AAEA,MAAI,cAAc,QAAQ;AACxB,WAAO,UAAU,IAAIC,iBAAgB,OAAO,UAAU,GAAG,YAAY,OAAO;AAAA,EAC9E;AAEA,MAAI,gBAAgB,QAAQ;AAC1B,WAAO,YAAY,IAAID,gBAAe,OAAO,YAAY,GAAG,cAAc,OAAO;AAAA,EACnF;AAMA,MAAI,iBAAiB,QAAQ;AAC3B,WAAO,aAAa,IAAIE,qBAAoB,OAAO,aAAa,GAAG,eAAe,OAAO;AAAA,EAC3F;AAEA,SAAO;AACT;;;AC1KO,IAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2C3B,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,yBAuBL,uBAAuB;AAAA,6BACnB,uBAAuB;AAAA;AAe7C,SAAS,kBAAkB,QAAsB,UAAU,OAAe;AAE/E,MAAI,OAAO,YAAY;AACrB,WAAO,OAAO;AAAA,EAChB;AACA,SAAO,UAAU,iBAAiB;AACpC;AAUO,SAAS,sBAAsB,YAA4B;AAChE,QAAM,UAAU,IAAI,YAAY;AAChC,QAAM,OAAO,QAAQ,OAAO,UAAU;AAEtC,SAAO,IAAI,KAAK,IAAI,EAAE,SAAS,EAAE;AACnC;;;ACxHA,SAAS,cAAAC,aAAY,WAAW,gBAAAC,eAAc,qBAAqB;AACnE,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,aAAY;AAOrB,IAAM,YAAYC,MAAKC,SAAQ,GAAG,WAAW,cAAc;AAK3D,IAAM,YAAY;AAclB,SAAS,iBAAuB;AAC9B,MAAI,CAACC,YAAW,SAAS,GAAG;AAC1B,cAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,EAC1C;AACF;AAQA,SAAS,cAAc,WAAuC;AAC5D,QAAM,WAAWF,MAAK,WAAW,SAAS;AAE1C,MAAI,CAACE,YAAW,QAAQ,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAUC,cAAa,UAAU,OAAO;AAC9C,UAAM,QAAQ,KAAK,MAAM,OAAO;AAChC,WAAO,MAAM,SAAS,GAAG;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQA,SAAS,cAAc,WAAmB,MAAoB;AAC5D,iBAAe;AACf,QAAM,WAAWH,MAAK,WAAW,SAAS;AAE1C,MAAI,QAAoC,CAAC;AAEzC,MAAIE,YAAW,QAAQ,GAAG;AACxB,QAAI;AACF,YAAM,UAAUC,cAAa,UAAU,OAAO;AAC9C,cAAQ,KAAK,MAAM,OAAO;AAAA,IAC5B,QAAQ;AAEN,cAAQ,CAAC;AAAA,IACX;AAAA,EACF;AAEA,QAAM,SAAS,IAAI;AAAA,IACjB;AAAA,IACA,gBAAgB;AAAA,IAChB,UAAS,oBAAI,KAAK,GAAE,YAAY;AAAA,EAClC;AAEA,gBAAc,UAAU,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;AACxD;AAKO,IAAM,mBAAN,cAA+B,MAAM;AAAA,EAC1C,YACE,SACgB,QAChB;AACA,UAAM,OAAO;AAFG;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AASA,eAAe,WAAW,WAAmB,YAAmC;AAE9E,iBAAe;AACf,QAAM,iBAAiBH,MAAK,WAAW,YAAY;AACnD,gBAAc,gBAAgB,UAAU;AAGxC,QAAM,OAAO,IAAI;AAAA,IACf,CAAC,UAAU,SAAS,MAAM,WAAW,MAAM,gBAAgB,SAAS;AAAA,IACpE;AAAA,MACE,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,KAAK;AAC5B,QAAM,SAAS,MAAM,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AACpD,QAAM,SAAS,MAAM,IAAI,SAAS,KAAK,MAAM,EAAE,KAAK;AAEpD,MAAI,aAAa,GAAG;AAClB,UAAM,SAAS,CAAC,QAAQ,MAAM,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AACzD,UAAM,IAAI;AAAA,MACR,sCAAsC,QAAQ;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AACF;AAaA,eAAsB,YACpB,YAAoB,oBACpB,YACiB;AACjB,QAAM,OAAO,sBAAsB,UAAU;AAC7C,QAAM,aAAa,cAAc,SAAS;AAE1C,MAAI,eAAe,MAAM;AAEvB,WAAO;AAAA,EACT;AAGA,UAAQ,MAAM,0BAA0B,SAAS,MAAM;AACvD,QAAM,WAAW,WAAW,UAAU;AAGtC,gBAAc,WAAW,IAAI;AAE7B,UAAQ,MAAM,iBAAiB,SAAS,uBAAuB;AAC/D,SAAO;AACT;;;ACtKA,SAAS,cAAAI,aAAY,gBAAAC,qBAAoB;AACzC,SAAS,SAAS,QAAAC,aAAY;AAC9B,SAAS,WAAAC,gBAAe;AAoBjB,IAAM,yBAAN,cAAqC,MAAM;AAAA,EAChD,cAAc;AACZ;AAAA,MACE;AAAA,IAEF;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAmBO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,cAAc;AACZ,UAAM,qDAAqD;AAC3D,SAAK,OAAO;AAAA,EACd;AACF;AAOA,eAAsB,uBAAyC;AAC7D,MAAI;AACF,UAAM,OAAO,IAAI,MAAM,CAAC,UAAU,MAAM,GAAG;AAAA,MACzC,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV,CAAC;AACD,UAAM,KAAK;AACX,WAAO,KAAK,aAAa;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAWO,SAAS,oBAA6B;AAE3C,MAAIC,YAAW,aAAa,GAAG;AAC7B,WAAO;AAAA,EACT;AAGA,MAAI;AACF,UAAM,SAASC,cAAa,kBAAkB,OAAO;AACrD,QAAI,OAAO,SAAS,QAAQ,KAAK,OAAO,SAAS,YAAY,GAAG;AAC9D,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAUO,SAAS,sBAA0C;AAExD,QAAM,aAAa,QAAQ,KAAK,CAAC;AACjC,MAAI,CAAC,cAAc,CAAC,WAAW,SAAS,YAAY,GAAG;AACrD,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,aAAa,QAAQ,MAAM;AAGjC,QAAM,kBAAkBC,MAAK,YAAY,cAAc;AACvD,MAAI,CAACF,YAAW,eAAe,GAAG;AAChC,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,MAAM,KAAK,MAAMC,cAAa,iBAAiB,OAAO,CAAC;AAC7D,QAAI,IAAI,SAAS,UAAU;AACzB,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAoBO,SAAS,eACd,QACA,YACiB;AAEjB,QAAM,UAAU,cAAc,SAAS,UAAU,KAAK,QAAQ,IAAI,oBAAoB;AAEtF,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,SAAS,OAAO,YAAY,OAAU;AAAA,EACjD;AAGA,QAAM,aACJ,SAAS,YAAY,KAAK,QAAQ,IAAI,qBAAqB,oBAAoB;AAEjF,MAAI,CAAC,YAAY;AACf,UAAM,IAAI;AAAA,MACR;AAAA,IAGF;AAAA,EACF;AAEA,SAAO,EAAE,SAAS,MAAM,WAAW;AACrC;AAKA,SAAS,WAAWE,OAAsB;AACxC,MAAIA,MAAK,WAAW,GAAG,GAAG;AACxB,WAAOA,MAAK,QAAQ,MAAMC,SAAQ,CAAC;AAAA,EACrC;AACA,SAAOD;AACT;AAUA,SAAS,mBACP,KACA,WACA,SACU;AACV,QAAM,OAAiB,CAAC,OAAO,MAAM;AAGrC,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,SAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC;AACpD,QAAM,gBAAgB,UAAU,SAAS,IAAI,MAAM;AACnD,OAAK,KAAK,UAAU,aAAa;AAGjC,MAAI,QAAQ,MAAM,OAAO;AACvB,SAAK,KAAK,KAAK;AAAA,EACjB;AAIA,QAAM,gBAAiC,IAAI,QAAQ,WAC/C,OACC,IAAI,wBAAwB,IAAI,OAAO,gBAAgB,KAAK;AACjE,OAAK,KAAK,MAAM,GAAG,IAAI,GAAG,eAAe,aAAa,EAAE;AACxD,OAAK,KAAK,MAAM,YAAY;AAG5B,QAAM,mBAAmB,IAAI,OAAO,mBAAmB,KAAK;AAC5D,QAAM,YAAY,WAAW,WAAW;AACxC,OAAK,KAAK,MAAM,GAAG,SAAS,kBAAkB,gBAAgB,EAAE;AAGhE,MAAI,QAAQ,WAAW,QAAQ,YAAY;AACzC,UAAM,iBAAiB,WAAW,QAAQ,UAAU;AACpD,SAAK,KAAK,MAAM,GAAG,cAAc,IAAI,uBAAuB,KAAK;AAAA,EACnE;AAGA,MAAI,IAAI,OAAO,QAAQ;AACrB,eAAW,SAAS,IAAI,OAAO,QAAQ;AACrC,YAAM,SAAS,WAAW,MAAM,MAAM;AACtC,WAAK,KAAK,MAAM,GAAG,MAAM,IAAI,MAAM,MAAM,IAAI,MAAM,UAAU,EAAE;AAAA,IACjE;AAAA,EACF;AAGA,aAAW,OAAO,oBAAoB;AACpC,QAAI,QAAQ,IAAI,GAAG,GAAG;AACpB,WAAK,KAAK,MAAM,GAAG;AAAA,IACrB;AAAA,EACF;AAGA,MAAI,IAAI,OAAO,UAAU,GAAG;AAC1B,eAAW,OAAO,IAAI,OAAO,UAAU,GAAG;AACxC,UAAI,QAAQ,IAAI,GAAG,GAAG;AACpB,aAAK,KAAK,MAAM,GAAG;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,IAAI,OAAO,aAAa,GAAG;AAC7B,SAAK,KAAK,GAAG,IAAI,OAAO,aAAa,CAAC;AAAA,EACxC;AAGA,OAAK,KAAK,SAAS;AAGnB,OAAK,KAAK,GAAG,IAAI,WAAW;AAE5B,SAAO;AACT;AAWO,SAAS,iBAAiB,MAA0B;AACzD,QAAM,cAAc,oBAAI,IAAI,CAAC,YAAY,eAAe,eAAe,cAAc,CAAC;AACtF,SAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,YAAY,IAAI,GAAG,CAAC;AACnD;AAgBO,SAAS,qBACd,QACA,SACA,eACS;AAET,MAAI,QAAQ,UAAU;AACpB,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,UAAU,QAAQ,UAAU;AACtC,WAAO;AAAA,EACT;AAGA,MAAI,kBAAkB,QAAW;AAC/B,WAAO;AAAA,EACT;AAGA,SAAO,QAAQ,WAAW;AAC5B;AAkBA,eAAsB,gBACpB,KACA,SACgB;AAEhB,MAAI,kBAAkB,GAAG;AACvB,YAAQ;AAAA,MACN;AAAA,IAEF;AAEA,UAAM,IAAI,gBAAgB;AAAA,EAC5B;AAGA,QAAM,YAAY,MAAM,qBAAqB;AAC7C,MAAI,CAAC,WAAW;AACd,UAAM,IAAI,uBAAuB;AAAA,EACnC;AAGA,QAAM,aAAa,kBAAkB,IAAI,QAAQ,QAAQ,OAAO;AAChE,QAAM,YAAY,QAAQ,UACtB,iBACC,IAAI,OAAO,YAAY,KAAK;AAGjC,MAAI,QAAQ,SAAS;AACnB,YAAQ,MAAM,mCAAmC,QAAQ,UAAU,EAAE;AAAA,EACvE;AAEA,MAAI;AACF,UAAM,YAAY,WAAW,UAAU;AAAA,EACzC,SAAS,OAAO;AACd,QAAI,iBAAiB,kBAAkB;AACrC,cAAQ,MAAM,sBAAsB;AACpC,cAAQ,MAAM,MAAM,MAAM;AAC1B,YAAM;AAAA,IACR;AACA,UAAM;AAAA,EACR;AAGA,QAAM,aAAa,mBAAmB,KAAK,WAAW,OAAO;AAG7D,QAAM,OAAO,IAAI,MAAM,CAAC,UAAU,GAAG,UAAU,GAAG;AAAA,IAChD,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AAED,QAAM,WAAW,MAAM,KAAK;AAC5B,UAAQ,KAAK,QAAQ;AACvB;AAYO,SAAS,oBACd,QACA,SACA,MACA,KACA,sBACwB;AACxB,SAAO;AAAA,IACL,QAAQ,UAAU,CAAC;AAAA,IACnB;AAAA,IACA,aAAa,iBAAiB,IAAI;AAAA,IAClC;AAAA,IACA;AAAA,EACF;AACF;;;AxB/WA,SAAS,wBACP,KACA,UACA,UACqD;AACrD,QAAM,SAAS,IAAI;AACnB,MAAI,CAAC,cAAc,IAAI,KAAK,KAAK,OAAO,OAAO,UAAU,aAAa,CAAC,OAAO,OAAO;AACnF,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,aAAsC;AAClD,aAAS,MAAM;AAGf,QAAI,SAAS,YAAY;AACvB,eAAS,WAAW;AACpB,eAAS,aAAa;AAAA,IACxB;AAEA,UAAM,KAAKE,iBAAgB,EAAE,OAAO,IAAI,OAAO,QAAQ,IAAI,OAAO,CAAC;AACnE,QAAI;AAEF,YAAM,eAAe,SAAS,KAAK,IAAI;AAAA,EAAK,6BAA6B,SAAS,KAAK,CAAC,CAAC,KAAK;AAC9F,UAAI,UAAU;AAGd,aAAO,MAAM;AACX,cAAM,cAAc,SAAS,aAAa;AAC1C,cAAM,SAAS,UAAU,GAAG,YAAY;AAAA,EAAK,WAAW,KAAK;AAC7D,kBAAU;AAEV,cAAM,SAAS,MAAM,GAAG,SAAS,MAAM;AACvC,cAAM,UAAU,OAAO,KAAK;AAC5B,YAAI,SAAS;AACX,iBAAO;AAAA,QACT;AAAA,MAEF;AAAA,IACF,UAAE;AACA,SAAG,MAAM;AAET,eAAS,QAAQ;AAAA,IACnB;AAAA,EACF;AACF;AA0BA,eAAsB,aACpB,WACA,SACA,KACe;AAEf,QAAM,gBAA+B;AAAA,IACnC,QAAQ,QAAQ,UAAU;AAAA,IAC1B,UAAU,QAAQ,YAAY;AAAA,IAC9B,UAAU,QAAQ,YAAY;AAAA,IAC9B,WAAW,QAAQ,aAAa;AAAA,EAClC;AAEA,QAAM,gBAAgB;AAAA,IACpB,IAAI;AAAA,IACJ;AAAA,IACA,QAAQ;AAAA;AAAA,EACV;AAEA,MAAI,eAAe;AAEjB,UAAM,UAAU,eAAe,IAAI,cAAc,cAAc,SAAS;AAGxE,UAAM,MAAM;AAAA,MACV,IAAI;AAAA,MACJ;AAAA,MACA,IAAI,KAAK,MAAM,CAAC;AAAA;AAAA,MAChB,QAAQ,IAAI;AAAA,MACZ,QAAQ;AAAA;AAAA,IACV;AAEA,QAAI;AACF,YAAM,gBAAgB,KAAK,OAAO;AAAA,IAEpC,SAAS,OAAO;AAEd,UAAI,iBAAiB,iBAAiB;AAAA,MAEtC,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,MAAM,cAAc,WAAW,GAAG;AACjD,QAAM,SAAS,IAAI,aAAa;AAIhC,QAAM,WAAW,IAAI,eAAe;AAapC,QAAM,qBAAqB,cAAc,IAAI,KAAK;AAClD,MAAI,QAAQ,aAAa,OAAO;AAC9B,eAAW,UAAU,gBAAgB;AAInC,UAAI,OAAO,SAAS,cAAc,QAAQ,uBAAuB,SAAS,CAAC,qBAAqB;AAC9F;AAAA,MACF;AACA,eAAS,gBAAgB,MAAM;AAAA,IACjC;AAAA,EACF;AAKA,QAAM,mBAAmB,QAAQ,UAAU,CAAC;AAC5C,MAAI,iBAAiB,SAAS,GAAG;AAC/B,UAAMC,WAAU,MAAM,YAAY,kBAAkB,QAAQ,IAAI,CAAC;AACjE,eAAW,UAAUA,UAAS;AAG5B,eAAS,gBAAgB,MAAM;AAAA,IACjC;AAAA,EACF;AAEA,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,kBAAkB,IAAI,gBAAgB;AAC5C,MAAI,eAAe;AACnB,MAAI,cAAc;AAClB,QAAM,cAAc,IAAI;AAGxB,QAAM,eAAe,MAAM;AACzB,QAAI,CAAC,gBAAgB,OAAO,SAAS;AACnC,qBAAe;AACf,sBAAgB,MAAM;AACtB,eAAS,MAAM;AACf,UAAI,OAAO,MAAMC,OAAM,OAAO;AAAA,cAAiB,SAAS,YAAY,CAAC;AAAA,CAAI,CAAC;AAAA,IAC5E,OAAO;AAGL,iBAAW;AAAA,IACb;AAAA,EACF;AAGA,QAAM,WAA4B;AAAA,IAChC,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,SAAS,MAAM;AAIb,UAAI,sBAAsB,YAAY,SAAS,CAAC,cAAc;AAC5D,iBAAS,aAAa,qBAAqB,aAAa,cAAc,YAAY;AAAA,MACpF;AAAA,IACF;AAAA,EACF;AAGA,QAAM,aAAa,MAAM;AAEvB,aAAS,aAAa;AACtB,aAAS,gBAAgB;AAEzB,aAAS,SAAS;AAClB,YAAQ,cAAc;AAGtB,UAAM,UAAU,qBAAqB;AAAA,MACnC,aAAa,OAAO;AAAA,MACpB;AAAA,MACA,gBAAgB,SAAS,uBAAuB;AAAA,MAChD,MAAM,SAAS,aAAa;AAAA,IAC9B,CAAC;AAED,QAAI,SAAS;AACX,UAAI,OAAO,MAAM,GAAGA,OAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC;AAAA,CAAI;AACjD,UAAI,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AAAA,IACjC;AAEA,QAAI,OAAO,MAAMA,OAAM,IAAI,UAAU,CAAC;AACtC,YAAQ,KAAK,GAAG;AAAA,EAClB;AAIA,MAAI,sBAAsB,YAAY,OAAO;AAC3C,aAAS,aAAa,qBAAqB,aAAa,cAAc,YAAY;AAAA,EACpF;AAGA,WAAS,gBAAgB;AAAA,IACvB;AAAA,IACA;AAAA,IACA,MAAM,eAAe,CAAC,gBAAgB,OAAO;AAAA,IAC7C,IAAI;AAAA,EACN;AAIA,QAAM,4BAA4B,CAAC,cAAc,aAAa,UAAU;AACxE,QAAM,gBAAgB,QAAQ,kBAAkB,CAAC;AAGjD,QAAM,kBAA8E;AAAA,IAClF,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;AACA,QAAM,kBAAkB,IAAI,gBAAgB,gBAAgB,KAAK,UAAU,QAAQ;AAEnF,MAAI;AACJ,MAAI,aAAa;AAGjB,QAAM,iBAAiB,cAAc,QAAQ,gBAAgB,UAAU;AACvE,MAAI;AACJ,MAAI,iBAAiB;AAGrB,QAAM,sBAAsB,OAAO,OAAe,aAA4C;AAC5F,QAAI;AACF,aAAO,MAAM,OAAO,YAAY,OAAO,QAAQ;AAAA,IACjD,QAAQ;AAEN,YAAM,aAAa,SAAS,OAAO,CAAC,KAAK,MAAM,OAAO,EAAE,SAAS,UAAU,IAAI,CAAC;AAChF,aAAO,KAAK,MAAM,aAAa,wBAAwB;AAAA,IACzD;AAAA,EACF;AAGA,QAAM,0BAA0B,OAAO,WAA4D;AACjG,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;AAaA,QAAM,UAAU,IAAI,aAAa,MAAM,EACpC,UAAU,QAAQ,KAAK,EACvB,WAAW,IAAI,aAAa,kBAAkB,CAAC,EAC/C,UAAU;AAAA,IACT,WAAW;AAAA;AAAA;AAAA,MAGT,gBAAgB,OAAO,YAAY;AACjC,sBAAc;AACd;AAIA,cAAM,cAAc,MAAM;AAAA,UACxB,QAAQ,QAAQ;AAAA,UAChB,QAAQ,QAAQ;AAAA,QAClB;AACA,iBAAS,UAAU,QAAQ,QAAQ,OAAO,WAAW;AAErD,iBAAS,eAAe,aAAa,KAAK;AAAA,MAC5C;AAAA;AAAA;AAAA,MAIA,gBAAgB,OAAO,YAAY;AACjC,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;AAAA,MAGA,eAAe,OAAO,YAAY;AAEhC,iBAAS,OAAO,QAAQ,gBAAgB,MAAM;AAI9C,YAAI,QAAQ,OAAO;AACjB,cAAI,QAAQ,MAAM,aAAa;AAC7B,qBAAS,eAAe,QAAQ,MAAM,aAAa,KAAK;AAAA,UAC1D;AACA,cAAI,QAAQ,MAAM,cAAc;AAC9B,qBAAS,gBAAgB,QAAQ,MAAM,cAAc,KAAK;AAAA,UAC5D;AAEA,mBAAS;AAAA,YACP,QAAQ,MAAM,qBAAqB;AAAA,YACnC,QAAQ,MAAM,4BAA4B;AAAA,UAC5C;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA,MAIA,mBAAmB,OAAO,YAAY;AACpC,sBAAc;AAGd,gBAAQ,QAAQ;AAChB,qBAAa,KAAK,IAAI,YAAY,QAAQ,YAAY,CAAC;AAIvD,YAAI,QAAQ,OAAO;AACjB,cAAI,QAAQ,MAAM,aAAa;AAC7B,qBAAS,eAAe,QAAQ,MAAM,aAAa,KAAK;AAAA,UAC1D;AACA,cAAI,QAAQ,MAAM,cAAc;AAC9B,qBAAS,gBAAgB,QAAQ,MAAM,cAAc,KAAK;AAAA,UAC5D;AAAA,QACF;AAKA,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;AAGA,cAAM,cAAc,SAAS,sBAAsB;AAGnD,iBAAS,QAAQ,QAAQ,KAAK;AAK9B,YAAI,CAAC,QAAQ,OAAO;AAClB,gBAAM,UAAU,cAAc;AAAA,YAC5B,YAAY,QAAQ,YAAY;AAAA,YAChC,OAAO,QAAQ;AAAA,YACf,OAAO,QAAQ;AAAA,YACf,gBAAgB;AAAA,YAChB,MAAM;AAAA,YACN,cAAc,QAAQ;AAAA,UACxB,CAAC;AACD,cAAI,SAAS;AACX,gBAAI,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AAAA,UACjC;AAAA,QACF;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;AACpC,cAAM,OAAO,gBAAgB,gBAAgB,IAAI,UAAU;AAG3D,YAAI,SAAS,WAAW;AACtB,iBAAO,EAAE,QAAQ,UAAU;AAAA,QAC7B;AAGA,cAAM,WAAW,cAAc,IAAI,KAAK;AACxC,cAAMC,aAAa,IAAI,OAA8B,UAAU;AAC/D,cAAM,YAAY,YAAYA;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,cAAM,SAAS,MAAM,gBAAgB,gBAAgB,IAAI,YAAY,IAAI,UAAU;AAEnF,YAAI,CAAC,OAAO,UAAU;AACpB,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,iBAAiB;AAAA;AAAA,UAA4B,OAAO,UAAU,SAAS;AAAA,UACzE;AAAA,QACF;AAEA,eAAO,EAAE,QAAQ,UAAU;AAAA,MAC7B;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;AAEA,QAAM,oBAAoB,wBAAwB,KAAK,UAAU,QAAQ;AACzE,MAAI,mBAAmB;AACrB,YAAQ,aAAa,iBAAiB;AAAA,EACxC;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,EACF;AAIA,UAAQ,oBAAoB,aAAa;AAIzC,UAAQ,2BAA2B;AAAA,IACjC,YAAY;AAAA,IACZ,kBAAkB,CAAC,UAAU,EAAE,SAAS,MAAM,MAAM,OAAO,MAAM,OAAO;AAAA,IACxE,eAAe,CAAC,SAAS,iBAAO,IAAI;AAAA,EACtC,CAAC;AAID,UAAQ;AAAA,IAAoB,CAAC,QAC3B;AAAA,MACE,cAAc,IAAI,YAAY,CAAC,IAAI,IAAI,aAAa;AAAA,MACpD;AAAA,MACA;AAAA,IACF,EAAE,KAAK,GAAG;AAAA,EACZ;AAGA,QAAM,QAAQ,QAAQ,IAAI,MAAM;AAgBhC,MAAI,aAAa;AACjB,QAAM,kBAAkB,MAAM;AAC5B,QAAI,YAAY;AAEd,YAAM,SAAS,QAAQ,QAAQ,aAAa,6BAA6B,UAAU;AACnF,cAAQ,MAAM,MAAM;AACpB,mBAAa;AAAA,IACf;AAAA,EACF;AAEA,MAAI;AACF,qBAAiB,SAAS,MAAM,IAAI,GAAG;AACrC,UAAI,MAAM,SAAS,QAAQ;AAEzB,iBAAS,MAAM;AACf,sBAAc,MAAM;AAAA,MACtB,WAAW,MAAM,SAAS,iBAAiB;AAEzC,wBAAgB;AAEhB,iBAAS,MAAM;AAEf,YAAI,QAAQ,OAAO;AAEjB,cAAI,MAAM,OAAO,eAAe,cAAc,MAAM,OAAO,YAAY,SAAS;AAC9E,kBAAM,UAAU,OAAO,MAAM,OAAO,WAAW,OAAO;AACtD,gBAAI,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AAAA,UACjC;AAAA,QACF,OAAO;AAEL,gBAAM,aAAa,MAAM,wBAAwB,MAAM,OAAO,MAAM;AACpE,cAAI,OAAO,MAAM,GAAGC,qBAAoB,EAAE,GAAG,MAAM,QAAQ,WAAW,CAAC,CAAC;AAAA,CAAI;AAAA,QAC9E;AAAA,MAEF;AAAA,IAEF;AAAA,EACF,SAAS,OAAO;AAEd,QAAI,CAAC,aAAa,KAAK,GAAG;AACxB,YAAM;AAAA,IACR;AAAA,EAEF,UAAE;AAEA,kBAAc;AACd,aAAS,aAAa;AAItB,QAAI,SAAS,eAAe;AAC1B,eAAS,cAAc;AACvB,cAAQ,KAAK,UAAU,MAAM,QAAQ,KAAK,GAAG,CAAC;AAAA,IAChD;AAAA,EACF;AAGA,kBAAgB;AAEhB,WAAS,SAAS;AAClB,UAAQ,cAAc;AAKtB,MAAI,CAAC,QAAQ,SAAS,aAAa,GAAG;AAEpC,QAAI,OAAO,MAAM,GAAGF,OAAM,IAAI,SAAI,OAAO,EAAE,CAAC,CAAC;AAAA,CAAI;AAEjD,UAAM,UAAU,qBAAqB;AAAA,MACnC,aAAa,OAAO;AAAA,MACpB;AAAA,MACA,gBAAgB,SAAS,uBAAuB;AAAA,MAChD,MAAM,SAAS,aAAa;AAAA,IAC9B,CAAC;AACD,QAAI,SAAS;AACX,UAAI,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AAAA,IACjC;AAAA,EACF;AACF;AAUO,SAAS,qBACd,SACA,KACA,QACM;AACN,QAAM,MAAM,QACT,QAAQ,SAAS,KAAK,EACtB,YAAY,kDAAkD,EAC9D,SAAS,YAAY,gEAAgE;AAExF,kBAAgB,KAAK,MAAM;AAE3B,MAAI;AAAA,IAAO,CAAC,QAAQ,YAClB,cAAc,MAAM;AAElB,YAAM,gBAAqC;AAAA,QACzC,GAAI;AAAA,QACJ,gBAAgB,SAAS,iBAAiB;AAAA,MAC5C;AACA,aAAO,aAAa,QAAQ,eAAe,GAAG;AAAA,IAChD,GAAG,GAAG;AAAA,EACR;AACF;;;AyBrvBA;AACA;AAEA;AA8BA,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;AACA,UAAQ,QAAQ,MAAM;AAEtB,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,SAAmC,GAAG,GAAG,GAAG;AAAA,EAC1F;AACF;;;AC1IA;AACA;AAJA,OAAOG,YAAW;;;ACIlB;AAJA,SAAS,mBAAAC,wBAAuB;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,KAAKD,iBAAgB,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,OACzB,IAAI,CAAC,MAAM,KAAK,EAAE,KAAK,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAChD,KAAK,IAAI;AACZ,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,SAAYC,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,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,OAAO;AAClE,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,cAAc,OAAgE;AAClG,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;;;ADtMA,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,IAE9B;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,QAAoB,MAAuC;AAClF,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;AAAA,IAAO,CAAC,SACP,cAAc,MAAM,sBAAsB,MAAM,GAAG,GAAG,GAAG;AAAA,EAC3D;AACJ;;;AE9dA,OAAOE,YAAW;AAKlB;AAQA,eAAe,oBACb,SACA,KACe;AACf,QAAM,SAAS,IAAI,aAAa;AAGhC,QAAM,SAAS,OAAO,cAAc,WAAW,QAAQ,QAAQ;AAE/D,MAAI,QAAQ,WAAW,QAAQ;AAC7B,eAAW,QAAQ,IAAI,MAAM;AAAA,EAC/B,OAAO;AACL,gBAAY,QAAQ,QAAQ,WAAW,OAAO,IAAI,MAAM;AAAA,EAC1D;AACF;AAEA,SAAS,YAAY,QAAqB,SAAkB,QAAqC;AAE/F,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;AAGA,SAAO,MAAMC,OAAM,KAAK,KAAK,sBAAsB,CAAC;AACpD,SAAO,MAAMA,OAAM,KAAK,IAAI,OAAO,EAAE,CAAC,IAAI,MAAM;AAGhD,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,CAAW,CAAC;AAE1D,QAAI,SAAS;AACX,yBAAmB,gBAAgB,MAAM;AAAA,IAC3C,OAAO;AACL,yBAAmB,gBAAgB,MAAM;AAAA,IAC3C;AAEA,WAAO,MAAM,IAAI;AAAA,EACnB;AAGA,SAAO,MAAMA,OAAM,KAAK,QAAQ,mBAAmB,CAAC;AACpD,SAAO,MAAMA,OAAM,IAAI,SAAI,OAAO,EAAE,CAAC,IAAI,IAAI;AAE7C,QAAM,YAAY,OAAO,QAAQ,aAAa,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,CAAC;AACvF,aAAW,CAAC,UAAU,QAAQ,KAAK,WAAW;AAC5C,WAAO,MAAMA,OAAM,KAAK,KAAK,SAAS,OAAO,EAAE,CAAC,EAAE,IAAIA,OAAM,IAAI,UAAK,IAAIA,OAAM,MAAM,QAAQ,IAAI,IAAI;AAAA,EACvG;AACA,SAAO,MAAM,IAAI;AACnB;AAEA,SAAS,mBAAmB,QAAqB,QAAqC;AAEpF,QAAM,UAAU;AAChB,QAAM,YAAY;AAClB,QAAM,eAAe;AACrB,QAAM,aAAa;AACnB,QAAM,cAAc;AAGpB,SAAO,MAAMA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,eAAe,aAAa,cAAc,CAAC,CAAC,IAAI,IAAI;AAC5G,SAAO;AAAA,IACLA,OAAM;AAAA,MACJ,WAAW,OAAO,OAAO,IACzB,OAAO,eAAe,OAAO,SAAS,IACtC,OAAO,UAAU,OAAO,YAAY,IACpC,OAAO,QAAQ,OAAO,UAAU,IAChC,OAAO,SAAS,OAAO,WAAW;AAAA,IACpC,IAAI;AAAA,EACN;AACA,SAAO,MAAMA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,eAAe,aAAa,cAAc,CAAC,CAAC,IAAI,IAAI;AAG5G,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,IACzC,OAAOA,OAAM,MAAM,MAAM,YAAY,OAAO,SAAS,CAAC,IACtD,OAAOA,OAAM,OAAO,iBAAiB,OAAO,YAAY,CAAC,IACzD,OAAOA,OAAM,KAAK,WAAW,OAAO,UAAU,CAAC,IAC/C,OAAOA,OAAM,KAAK,YAAY,OAAO,WAAW,CAAC,IACjD;AAAA,IACF;AAAA,EACF;AAEA,SAAO,MAAMA,OAAM,IAAI,SAAI,OAAO,UAAU,YAAY,eAAe,aAAa,cAAc,CAAC,CAAC,IAAI,IAAI;AAC5G,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,MAAM,KAAKA,OAAM,IAAI,UAAU,CAAC,SAASA,OAAM,OAAOC,cAAa,MAAM,aAAa,CAAC,CAAC;AAAA,CAAI;AACnG,WAAO,MAAM,KAAKD,OAAM,IAAI,aAAa,CAAC,MAAMA,OAAM,OAAOC,cAAa,MAAM,eAAe,CAAC,CAAC;AAAA,CAAI;AACrG,WAAO,MAAM,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,CAAI;AAExN,QAAI,MAAM,QAAQ,gBAAgB,QAAW;AAC3C,aAAO,MAAM,KAAKA,OAAM,IAAI,eAAe,CAAC,IAAIA,OAAM,KAAK,IAAI,MAAM,QAAQ,YAAY,QAAQ,CAAC,CAAC,gBAAgB,CAAC;AAAA,CAAI;AAAA,IAC1H;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;AAEA,SAAS,WAAW,QAAqB,QAAqC;AAC5E,QAAM,SAAS;AAAA,IACb,QAAQ,OAAO,IAAI,YAAU;AAAA,MAC3B,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;AAAA,IACF,WAAW;AAAA,EACb;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,8DAA8D,EAC1E,OAAO,qBAAqB,gDAAgD,EAC5E,OAAO,qBAAqB,gCAAgC,OAAO,EACnE,OAAO,aAAa,mCAAmC,KAAK,EAC5D;AAAA,IAAO,CAAC,YACP;AAAA,MACE,MAAM,oBAAoB,SAAiC,GAAG;AAAA,MAC9D;AAAA,IACF;AAAA,EACF;AACJ;;;AC7MA;AAEA;AALA,OAAO,cAAc;AACrB,OAAOC,YAAW;AA0ClB,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;;;ACvIA,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,KACM;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,UAAkC;AAAA,UACtC,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,UAA+B;AAAA,UACnC,GAAG;AAAA,UACH,GAAI;AAAA,QACN;AACA,cAAM,aAAa,QAAQ,SAAS,MAAM;AAAA,MAC5C,GAAG,MAAM;AAAA,IACX,CAAC;AAAA,EACH;AACF;;;AhChFA,SAAS,cAAc,OAA6B;AAClD,QAAM,aAAa,MAAM,YAAY;AACrC,MAAI,CAAC,WAAW,SAAS,UAAU,GAAG;AACpC,UAAM,IAAIC,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,KAAK;AAChD,wBAAsB,SAAS,GAAG;AAClC,wBAAsB,SAAS,GAAG;AAGlC,MAAI,QAAQ;AACV,UAAM,cAAc,sBAAsB,MAAM;AAChD,eAAW,QAAQ,aAAa;AAC9B,YAAM,YAAY,OAAO,IAAI;AAC7B,4BAAsB,SAAS,MAAM,WAAW,GAAG;AAAA,IACrD;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;AAAA,IAEH,cAAc,OAAO;AAAA,EACvB;AACA,QAAM,UAAU,cAAc,KAAK,MAAM;AACzC,QAAM,QAAQ,WAAW,IAAI,IAAI;AACnC;;;AiC9IA,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","createInterface","chalk","chalk","chalk","fs","path","fs","path","z","fs","path","z","fs","z","z","fs","fs","path","z","z","path","fs","z","z","z","z","path","fs","writeFile","chalk","chalk","formatGadgetSummary","chalk","existsSync","readFileSync","homedir","join","join","homedir","path","existsSync","readFileSync","validateString","validateBoolean","validateStringArray","existsSync","readFileSync","homedir","join","join","homedir","existsSync","readFileSync","existsSync","readFileSync","join","homedir","existsSync","readFileSync","join","path","homedir","createInterface","gadgets","chalk","stderrTTY","formatGadgetSummary","chalk","createInterface","chalk","chalk","result","chalk","chalk","formatTokens","chalk","resolve","InvalidArgumentError"]}
|
|
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/approval/manager.ts","../src/cli/approval/context-providers.ts","../src/cli/approval/diff-renderer.ts","../src/cli/builtin-gadgets.ts","../src/cli/gadgets.ts","../src/cli/builtins/filesystem/list-directory.ts","../src/cli/builtins/filesystem/utils.ts","../src/cli/builtins/filesystem/read-file.ts","../src/cli/builtins/filesystem/write-file.ts","../src/cli/builtins/filesystem/edit-file.ts","../src/cli/builtins/run-command.ts","../src/cli/builtins/index.ts","../src/cli/llm-logging.ts","../src/cli/utils.ts","../src/cli/ui/formatters.ts","../src/cli/option-helpers.ts","../src/cli/docker/types.ts","../src/cli/config.ts","../src/cli/templates.ts","../src/cli/docker/docker-config.ts","../src/cli/docker/dockerfile.ts","../src/cli/docker/image-manager.ts","../src/cli/docker/docker-wrapper.ts","../src/cli/complete-command.ts","../src/cli/gadget-command.ts","../src/cli/gadget-prompts.ts","../src/cli/models-command.ts","../src/cli/environment.ts","../src/cli/custom-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} as const;\n\n/** Valid log level names */\nexport const LOG_LEVELS = [\"silly\", \"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"] as const;\nexport type LogLevelName = (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 docker: \"--docker\",\n dockerRo: \"--docker-ro\",\n noDocker: \"--no-docker\",\n dockerDev: \"--docker-dev\",\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: \"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 docker: \"Run agent in a Docker sandbox container for security isolation.\",\n dockerRo: \"Run in Docker with current directory mounted read-only.\",\n noDocker: \"Disable Docker sandboxing (override config).\",\n dockerDev: \"Run in Docker dev mode (mount local source instead of npm install).\",\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 {\n type CLIConfig,\n type CustomCommandConfig,\n getCustomCommandNames,\n loadConfig,\n} from \"./config.js\";\nimport { registerGadgetCommand } from \"./gadget-command.js\";\nimport { registerModelsCommand } from \"./models-command.js\";\nimport { registerCustomCommand } from \"./custom-command.js\";\nimport {\n CLI_DESCRIPTION,\n CLI_NAME,\n LOG_LEVELS,\n type LogLevelName,\n OPTION_DESCRIPTIONS,\n OPTION_FLAGS,\n} from \"./constants.js\";\nimport type { CLIEnvironment, CLILoggerConfig } from \"./environment.js\";\nimport { createDefaultEnvironment } from \"./environment.js\";\n\n/**\n * Parses and validates the log level option value.\n */\nfunction parseLogLevel(value: string): LogLevelName {\n const normalized = value.toLowerCase() as LogLevelName;\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?: LogLevelName;\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);\n registerModelsCommand(program, env);\n registerGadgetCommand(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);\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 // Pass Docker config from [docker] section\n dockerConfig: config.docker,\n };\n const program = createProgram(env, config);\n await program.parseAsync(env.argv);\n}\n","{\n \"name\": \"llmist\",\n \"version\": \"2.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 },\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 \"chalk\": \"^5.6.2\",\n \"commander\": \"^12.1.0\",\n \"diff\": \"^8.0.2\",\n \"eta\": \"^4.4.1\",\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 { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport type { Command } from \"commander\";\nimport { AgentBuilder } from \"../agent/builder.js\";\nimport { isAbortError } from \"../core/errors.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 { ApprovalManager, type ApprovalConfig } from \"./approval/index.js\";\nimport { builtinGadgets } from \"./builtin-gadgets.js\";\nimport type { AgentConfig } from \"./config.js\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { loadGadgets } from \"./gadgets.js\";\nimport {\n createSessionDir,\n formatCallNumber,\n formatLlmRequest,\n resolveLogDir,\n writeLogFile,\n} from \"./llm-logging.js\";\nimport { addAgentOptions, type AgentCommandOptions } from \"./option-helpers.js\";\nimport {\n createEscKeyListener,\n createSigintListener,\n executeAction,\n isInteractive,\n renderSummary,\n resolvePrompt,\n StreamPrinter,\n StreamProgress,\n} from \"./utils.js\";\nimport {\n formatGadgetSummary,\n renderMarkdownWithSeparators,\n renderOverallSummary,\n} from \"./ui/formatters.js\";\nimport {\n createDockerContext,\n DockerSkipError,\n executeInDocker,\n resolveDevMode,\n resolveDockerEnabled,\n type DockerOptions,\n} from \"./docker/index.js\";\n\n/**\n * Keyboard/signal listener management for ESC key and Ctrl+C (SIGINT) handling.\n * Allows pausing and restoring the ESC listener during readline operations.\n */\ninterface KeyboardManager {\n cleanupEsc: (() => void) | null;\n cleanupSigint: (() => void) | null;\n restore: () => void;\n}\n\n/**\n * Creates a human input handler for interactive mode.\n * Only returns a handler if stdin is a TTY (terminal), not a pipe.\n *\n * @param env - CLI environment\n * @param progress - Progress indicator to pause during input\n * @param keyboard - Keyboard listener manager for ESC handling\n * @returns Human input handler function or undefined if not interactive\n */\nfunction createHumanInputHandler(\n env: CLIEnvironment,\n progress: StreamProgress,\n keyboard: KeyboardManager,\n): ((question: string) => Promise<string>) | undefined {\n const stdout = env.stdout as NodeJS.WriteStream;\n if (!isInteractive(env.stdin) || typeof stdout.isTTY !== \"boolean\" || !stdout.isTTY) {\n return undefined;\n }\n\n return async (question: string): Promise<string> => {\n progress.pause(); // Pause progress indicator during human input\n\n // Temporarily disable ESC listener for readline (raw mode conflict)\n if (keyboard.cleanupEsc) {\n keyboard.cleanupEsc();\n keyboard.cleanupEsc = null;\n }\n\n const rl = createInterface({ input: env.stdin, output: env.stdout });\n try {\n // Display question on first prompt only (with markdown rendering and separators)\n const questionLine = question.trim() ? `\\n${renderMarkdownWithSeparators(question.trim())}` : \"\";\n let isFirst = true;\n\n // Loop until non-empty input (like a REPL)\n while (true) {\n const statsPrompt = progress.formatPrompt();\n const prompt = isFirst ? `${questionLine}\\n${statsPrompt}` : statsPrompt;\n isFirst = false;\n\n const answer = await rl.question(prompt);\n const trimmed = answer.trim();\n if (trimmed) {\n return trimmed;\n }\n // Empty input - show prompt again (no question repeat)\n }\n } finally {\n rl.close();\n // Restore ESC listener after readline closes\n keyboard.restore();\n }\n };\n}\n\n// formatGadgetSummary is now imported from ./ui/formatters.js\n// This demonstrates clean code organization and reusability\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: AgentCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n // Check if Docker sandboxing is enabled\n const dockerOptions: DockerOptions = {\n docker: options.docker ?? false,\n dockerRo: options.dockerRo ?? false,\n noDocker: options.noDocker ?? false,\n dockerDev: options.dockerDev ?? false,\n };\n\n const dockerEnabled = resolveDockerEnabled(\n env.dockerConfig,\n dockerOptions,\n options.docker, // Profile-level docker: true/false\n );\n\n if (dockerEnabled) {\n // Resolve dev mode settings (for mounting local source)\n const devMode = resolveDevMode(env.dockerConfig, dockerOptions.dockerDev);\n\n // Execute inside Docker container\n const ctx = createDockerContext(\n env.dockerConfig,\n dockerOptions,\n env.argv.slice(2), // Remove 'node' and script path\n process.cwd(),\n options.dockerCwdPermission, // Profile-level CWD permission override\n );\n\n try {\n await executeInDocker(ctx, devMode);\n // executeInDocker calls process.exit(), so we won't reach here\n } catch (error) {\n // DockerSkipError means we're already inside a container, continue normally\n if (error instanceof DockerSkipError) {\n // Continue with normal execution\n } else {\n throw error;\n }\n }\n }\n\n const prompt = await resolvePrompt(promptArg, env);\n const client = env.createClient();\n\n // SHOWCASE: llmist's GadgetRegistry for dynamic tool loading\n // This demonstrates how to build extensible CLIs with plugin-like functionality\n const registry = new GadgetRegistry();\n\n // Register built-in gadgets for basic agent interaction\n // SHOWCASE: Built-in gadgets enable conversation without any custom tools\n //\n // AskUser: Prompts user for input during agent execution\n // TellUser: Displays formatted messages and optionally ends the loop\n //\n // Flags control built-in behavior:\n // --no-builtins: Exclude all built-in gadgets\n // --no-builtin-interaction: Exclude only AskUser (keeps TellUser for output)\n //\n // AskUser is also auto-excluded when stdin is not interactive (piped input)\n const stdinIsInteractive = isInteractive(env.stdin);\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 (gadget.name === \"AskUser\" && (options.builtinInteraction === false || !stdinIsInteractive)) {\n continue;\n }\n registry.registerByClass(gadget);\n }\n }\n\n // Load user-provided gadgets from file paths\n // SHOWCASE: Dynamic gadget loading enables custom tools without recompiling\n // Users can provide gadgets via -g/--gadget flag, supporting any TypeScript class\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 // Later registrations can override earlier ones\n // This allows users to customize built-in behavior\n registry.registerByClass(gadget);\n }\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 // Set up cancellation support for ESC key and Ctrl+C (SIGINT) handling\n const abortController = new AbortController();\n let wasCancelled = false;\n let isStreaming = false; // Track if LLM call is in progress\n const stdinStream = env.stdin as NodeJS.ReadStream;\n\n // Shared cancel handler for both ESC and Ctrl+C\n const handleCancel = () => {\n if (!abortController.signal.aborted) {\n wasCancelled = true;\n abortController.abort();\n progress.pause();\n env.stderr.write(chalk.yellow(`\\n[Cancelled] ${progress.formatStats()}\\n`));\n } else {\n // Already cancelled - treat as quit request (like double Ctrl+C)\n // This ensures the user can always exit even if the abort didn't fully propagate\n handleQuit();\n }\n };\n\n // Create keyboard manager for ESC/SIGINT listener coordination with readline\n const keyboard: KeyboardManager = {\n cleanupEsc: null,\n cleanupSigint: null,\n restore: () => {\n // Only restore ESC listener if not cancelled - when wasCancelled is true,\n // the executeAgent function is terminating and we don't need the listener.\n // This is called after readline closes to re-enable ESC key detection.\n if (stdinIsInteractive && stdinStream.isTTY && !wasCancelled) {\n keyboard.cleanupEsc = createEscKeyListener(stdinStream, handleCancel, handleCancel);\n }\n },\n };\n\n // Quit handler for double Ctrl+C - shows summary and exits\n const handleQuit = () => {\n // Clean up listeners\n keyboard.cleanupEsc?.();\n keyboard.cleanupSigint?.();\n\n progress.complete();\n printer.ensureNewline();\n\n // Show final summary\n const summary = renderOverallSummary({\n totalTokens: usage?.totalTokens,\n iterations,\n elapsedSeconds: progress.getTotalElapsedSeconds(),\n cost: progress.getTotalCost(),\n });\n\n if (summary) {\n env.stderr.write(`${chalk.dim(\"â\".repeat(40))}\\n`);\n env.stderr.write(`${summary}\\n`);\n }\n\n env.stderr.write(chalk.dim(\"[Quit]\\n\"));\n process.exit(130); // SIGINT convention: 128 + signal number (2)\n };\n\n // Set up ESC key and Ctrl+C listener if in interactive TTY mode\n // Both ESC and Ctrl+C trigger handleCancel during streaming\n if (stdinIsInteractive && stdinStream.isTTY) {\n keyboard.cleanupEsc = createEscKeyListener(stdinStream, handleCancel, handleCancel);\n }\n\n // Set up SIGINT (Ctrl+C) listener - always active for graceful cancellation\n keyboard.cleanupSigint = createSigintListener(\n handleCancel,\n handleQuit,\n () => isStreaming && !abortController.signal.aborted,\n env.stderr,\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<string, \"allowed\" | \"denied\" | \"approval-required\"> = {\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 const approvalManager = new ApprovalManager(approvalConfig, env, progress, keyboard);\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 (model: string, messages: LLMMessage[]): 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((sum, m) => sum + (m.content?.length ?? 0), 0);\n return Math.round(totalChars / FALLBACK_CHARS_PER_TOKEN);\n }\n };\n\n // Count tokens for gadget output text\n const countGadgetOutputTokens = async (output: string | undefined): 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 const builder = new AgentBuilder(client)\n .withModel(options.model)\n .withLogger(env.createLogger(\"llmist:cli:agent\"))\n .withHooks({\n observers: {\n // onLLMCallStart: Start progress indicator for each LLM call\n // This showcases how to react to agent lifecycle events\n onLLMCallStart: async (context) => {\n isStreaming = true; // Mark that we're actively streaming (for SIGINT handling)\n llmCallCounter++;\n\n // Count input tokens accurately using provider-specific methods\n // This ensures we never show ~ for input tokens\n const inputTokens = await countMessagesTokens(\n context.options.model,\n context.options.messages,\n );\n progress.startCall(context.options.model, inputTokens);\n // Mark input tokens as accurate (not estimated)\n progress.setInputTokens(inputTokens, false);\n },\n\n // onLLMCallReady: Log the exact request being sent to the LLM\n // This fires AFTER controller modifications (e.g., trailing messages)\n onLLMCallReady: async (context) => {\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 // onStreamChunk: Real-time updates as LLM generates tokens\n // This enables responsive UIs that show progress during generation\n onStreamChunk: async (context) => {\n // Update estimated output tokens from accumulated text length\n progress.update(context.accumulatedText.length);\n\n // Use exact token counts when available from streaming response\n // SHOWCASE: Provider responses include token usage for accurate tracking\n if (context.usage) {\n if (context.usage.inputTokens) {\n progress.setInputTokens(context.usage.inputTokens, false);\n }\n if (context.usage.outputTokens) {\n progress.setOutputTokens(context.usage.outputTokens, false);\n }\n // Update cached token counts for live cost estimation\n progress.setCachedTokens(\n context.usage.cachedInputTokens ?? 0,\n context.usage.cacheCreationInputTokens ?? 0,\n );\n }\n },\n\n // onLLMCallComplete: Finalize metrics after each LLM call\n // This is where you'd typically log metrics or update dashboards\n onLLMCallComplete: async (context) => {\n isStreaming = false; // Mark that streaming is complete (for SIGINT handling)\n\n // Capture completion metadata for final summary\n usage = context.usage;\n iterations = Math.max(iterations, context.iteration + 1);\n\n // Update with final exact token counts from provider\n // SHOWCASE: llmist normalizes token usage across all providers\n if (context.usage) {\n if (context.usage.inputTokens) {\n progress.setInputTokens(context.usage.inputTokens, false);\n }\n if (context.usage.outputTokens) {\n progress.setOutputTokens(context.usage.outputTokens, false);\n }\n }\n\n // Calculate per-call cost for the summary (accounting for cached tokens)\n // Use context.options.model (resolved) instead of options.model (raw CLI input)\n // This ensures aliases like \"sonnet\" are resolved to \"claude-sonnet-4-5\"\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 // Get per-call elapsed time before endCall resets it\n const callElapsed = progress.getCallElapsedSeconds();\n\n // End this call's progress tracking and switch to cumulative mode\n progress.endCall(context.usage);\n\n // SHOWCASE: Print per-call summary after each LLM call\n // This gives users visibility into each iteration's metrics\n // Skip summaries in quiet mode\n if (!options.quiet) {\n const summary = renderSummary({\n iterations: context.iteration + 1,\n model: options.model,\n usage: context.usage,\n elapsedSeconds: callElapsed,\n cost: callCost,\n finishReason: context.finishReason,\n });\n if (summary) {\n env.stderr.write(`${summary}\\n`);\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 const mode = approvalManager.getApprovalMode(ctx.gadgetName);\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 // Interactive mode: use approval manager\n const result = await approvalManager.requestApproval(ctx.gadgetName, ctx.parameters);\n\n if (!result.approved) {\n return {\n action: \"skip\",\n syntheticResult: `status=denied\\n\\nDenied: ${result.reason ?? \"by user\"}`,\n };\n }\n\n return { action: \"proceed\" };\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 const humanInputHandler = createHumanInputHandler(env, progress, keyboard);\n if (humanInputHandler) {\n builder.onHumanInput(humanInputHandler);\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\\nHere's what I can do:\\n- Analyze your codebase\\n- Execute commands\\n- Answer questions\\n\\nWhat would you like me to work on?\",\n done: false,\n type: \"info\",\n },\n \"âšī¸ đ Hello! I'm ready to help.\\n\\nHere's what I can do:\\n- Analyze your codebase\\n- Execute commands\\n- Answer questions\\n\\nWhat would you like me to work on?\",\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: what gadget invocations can you make in parallel right now?\",\n \"Maximize efficiency by batching independent operations in a single response.\",\n ].join(\" \"),\n );\n\n // Build and start the agent\n const agent = builder.ask(prompt);\n\n // SHOWCASE: llmist's event-driven agent execution\n // The agent emits events as it runs, enabling reactive UIs\n //\n // Event types:\n // - \"text\": LLM-generated text chunks (streaming or complete)\n // - \"gadget_result\": Results from gadget/tool executions\n // - \"human_input_required\": Agent needs user input (handled via callback)\n //\n // This pattern allows building:\n // - Real-time streaming UIs\n // - Progress indicators during tool execution\n // - Separation of business logic (agent) from presentation (UI)\n\n // Buffer for accumulating text chunks - markdown rendering requires complete content\n let textBuffer = \"\";\n const flushTextBuffer = () => {\n if (textBuffer) {\n // Use separators in normal mode, plain text in quiet mode\n const output = options.quiet ? textBuffer : renderMarkdownWithSeparators(textBuffer);\n printer.write(output);\n textBuffer = \"\";\n }\n };\n\n try {\n for await (const event of agent.run()) {\n if (event.type === \"text\") {\n // Accumulate text chunks - we'll render markdown when complete\n progress.pause();\n textBuffer += event.content;\n } else if (event.type === \"gadget_result\") {\n // Flush any accumulated text before showing gadget result\n flushTextBuffer();\n // Show gadget execution feedback on stderr\n progress.pause();\n\n if (options.quiet) {\n // In quiet mode, only output TellUser messages (to stdout, plain unrendered text)\n if (event.result.gadgetName === \"TellUser\" && event.result.parameters?.message) {\n const message = String(event.result.parameters.message);\n env.stdout.write(`${message}\\n`);\n }\n } else {\n // Normal mode: show full gadget summary on stderr\n const tokenCount = await countGadgetOutputTokens(event.result.result);\n env.stderr.write(`${formatGadgetSummary({ ...event.result, tokenCount })}\\n`);\n }\n // Progress automatically resumes on next LLM call (via onLLMCallStart hook)\n }\n // Note: human_input_required handled by callback (see createHumanInputHandler)\n }\n } catch (error) {\n // Handle abort gracefully - message already shown in ESC handler\n if (!isAbortError(error)) {\n throw error;\n }\n // Keep partial response in buffer for flushing below\n } finally {\n // Always cleanup keyboard and signal listeners\n isStreaming = false;\n keyboard.cleanupEsc?.();\n\n // Replace the complex SIGINT handler with a simple exit handler\n // This ensures Ctrl+C always works even if something keeps the event loop alive\n if (keyboard.cleanupSigint) {\n keyboard.cleanupSigint();\n process.once(\"SIGINT\", () => process.exit(130)); // 130 = 128 + SIGINT (2)\n }\n }\n\n // Flush any remaining buffered text with markdown rendering (includes partial on cancel)\n flushTextBuffer();\n\n progress.complete();\n printer.ensureNewline();\n\n // SHOWCASE: Show overall summary only if there were multiple iterations\n // Single-iteration runs already showed per-call summary, no need to repeat\n // Skip summaries in quiet mode\n if (!options.quiet && iterations > 1) {\n // Separator line to distinguish from per-call summaries\n env.stderr.write(`${chalk.dim(\"â\".repeat(40))}\\n`);\n\n const summary = renderOverallSummary({\n totalTokens: usage?.totalTokens,\n iterations,\n elapsedSeconds: progress.getTotalElapsedSeconds(),\n cost: progress.getTotalCost(),\n });\n if (summary) {\n env.stderr.write(`${summary}\\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): void {\n const cmd = program\n .command(COMMANDS.agent)\n .description(\"Run the llmist agent loop with optional gadgets.\")\n .argument(\"[prompt]\", \"Prompt for the agent loop. Falls back to stdin when available.\");\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: AgentCommandOptions = {\n ...(options as AgentCommandOptions),\n gadgetApproval: config?.[\"gadget-approval\"],\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","import { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport type { CLIEnvironment } from \"../environment.js\";\nimport type { StreamProgress } from \"../utils.js\";\nimport { builtinContextProviders, DefaultContextProvider } from \"./context-providers.js\";\nimport { renderColoredDiff } from \"./diff-renderer.js\";\nimport type {\n ApprovalConfig,\n ApprovalContextProvider,\n ApprovalMode,\n ApprovalResult,\n KeyboardCoordinator,\n} from \"./types.js\";\n\n/**\n * Manages gadget approval flows.\n *\n * The ApprovalManager determines whether a gadget execution should:\n * - Proceed automatically (\"allowed\")\n * - Be rejected automatically (\"denied\")\n * - Require user approval (\"approval-required\")\n *\n * For approval-required gadgets, it displays relevant context (like diffs for\n * file operations) and prompts the user interactively.\n */\nexport class ApprovalManager {\n private providers = new Map<string, ApprovalContextProvider>();\n\n /**\n * Creates a new ApprovalManager.\n *\n * @param config - Approval configuration with per-gadget modes\n * @param env - CLI environment for I/O operations\n * @param progress - Optional progress indicator to pause during prompts\n * @param keyboard - Optional keyboard coordinator to disable ESC listener during prompts\n */\n constructor(\n private readonly config: ApprovalConfig,\n private readonly env: CLIEnvironment,\n private readonly progress?: StreamProgress,\n private readonly keyboard?: KeyboardCoordinator,\n ) {\n // Register built-in context providers\n for (const provider of builtinContextProviders) {\n this.registerProvider(provider);\n }\n }\n\n /**\n * Registers a custom context provider for a gadget.\n *\n * @param provider - The context provider to register\n */\n registerProvider(provider: ApprovalContextProvider): void {\n // Case-insensitive registration\n this.providers.set(provider.gadgetName.toLowerCase(), provider);\n }\n\n /**\n * Gets the approval mode for a gadget.\n *\n * Resolution order:\n * 1. Explicit configuration for the gadget name\n * 2. Wildcard \"*\" configuration\n * 3. Default mode from config\n *\n * @param gadgetName - Name of the gadget\n * @returns The approval mode to use\n */\n getApprovalMode(gadgetName: string): ApprovalMode {\n const normalizedName = gadgetName.toLowerCase();\n\n // Check explicit configuration (case-insensitive)\n for (const [configName, mode] of Object.entries(this.config.gadgetApprovals)) {\n if (configName.toLowerCase() === normalizedName) {\n return mode;\n }\n }\n\n // Check wildcard\n if (\"*\" in this.config.gadgetApprovals) {\n return this.config.gadgetApprovals[\"*\"];\n }\n\n // Return default\n return this.config.defaultMode;\n }\n\n /**\n * Requests approval for a gadget execution.\n *\n * Behavior depends on the gadget's approval mode:\n * - \"allowed\": Returns approved immediately\n * - \"denied\": Returns denied with configuration message\n * - \"approval-required\": Prompts user interactively\n *\n * @param gadgetName - Name of the gadget\n * @param params - The gadget's execution parameters\n * @returns Approval result indicating whether to proceed\n */\n async requestApproval(\n gadgetName: string,\n params: Record<string, unknown>,\n ): Promise<ApprovalResult> {\n const mode = this.getApprovalMode(gadgetName);\n\n if (mode === \"allowed\") {\n return { approved: true };\n }\n\n if (mode === \"denied\") {\n return {\n approved: false,\n reason: `${gadgetName} is denied by configuration`,\n };\n }\n\n // mode === \"approval-required\"\n return this.promptForApproval(gadgetName, params);\n }\n\n /**\n * Prompts the user for approval interactively.\n */\n private async promptForApproval(\n gadgetName: string,\n params: Record<string, unknown>,\n ): Promise<ApprovalResult> {\n // Get context provider (case-insensitive lookup, or default)\n const provider =\n this.providers.get(gadgetName.toLowerCase()) ?? new DefaultContextProvider(gadgetName);\n\n const context = await provider.getContext(params);\n\n // Pause progress indicator if available\n this.progress?.pause();\n\n // Temporarily disable ESC listener for readline (raw mode conflict)\n // This prevents interference between ESC key detection and readline input\n if (this.keyboard?.cleanupEsc) {\n this.keyboard.cleanupEsc();\n this.keyboard.cleanupEsc = null;\n }\n\n try {\n // Render approval UI\n this.env.stderr.write(`\\n${chalk.yellow(\"đ Approval required:\")} ${context.summary}\\n`);\n\n if (context.details) {\n this.env.stderr.write(`\\n${renderColoredDiff(context.details)}\\n`);\n }\n\n // Prompt user\n const response = await this.prompt(\" â approve, or type to reject: \");\n\n // Empty input or \"y\"/\"Y\" = approved\n const isApproved = response === \"\" || response.toLowerCase() === \"y\";\n\n if (isApproved) {\n this.env.stderr.write(` ${chalk.green(\"â Approved\")}\\n\\n`);\n return { approved: true };\n }\n\n this.env.stderr.write(` ${chalk.red(\"â Denied\")}\\n\\n`);\n return { approved: false, reason: response || \"Rejected by user\" };\n } finally {\n // Restore ESC listener after readline closes\n this.keyboard?.restore();\n }\n }\n\n /**\n * Prompts for user input.\n */\n private async prompt(message: string): Promise<string> {\n const rl = createInterface({\n input: this.env.stdin,\n output: this.env.stderr,\n });\n try {\n const answer = await rl.question(message);\n return answer.trim();\n } finally {\n rl.close();\n }\n }\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { createPatch } from \"diff\";\nimport type { ApprovalContext, ApprovalContextProvider } from \"./types.js\";\nimport { formatNewFileDiff } from \"./diff-renderer.js\";\n\n/**\n * Formats a universal gadget summary: GadgetName(param1=value1, param2=value2)\n * Used by all context providers for consistent approval prompts.\n * Shows full parameter values so users know exactly what they're approving.\n */\nexport function formatGadgetSummary(gadgetName: string, params: Record<string, unknown>): string {\n const paramEntries = Object.entries(params);\n\n if (paramEntries.length === 0) {\n return `${gadgetName}()`;\n }\n\n const paramStr = paramEntries.map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(\", \");\n\n return `${gadgetName}(${paramStr})`;\n}\n\n/**\n * Context provider for WriteFile gadget.\n * Generates a unified diff when modifying existing files,\n * or shows \"new file\" content for file creation.\n */\nexport class WriteFileContextProvider implements ApprovalContextProvider {\n readonly gadgetName = \"WriteFile\";\n\n async getContext(params: Record<string, unknown>): Promise<ApprovalContext> {\n const filePath = String(params.filePath ?? params.path ?? \"\");\n const newContent = String(params.content ?? \"\");\n const resolvedPath = resolve(process.cwd(), filePath);\n\n if (!existsSync(resolvedPath)) {\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n details: formatNewFileDiff(filePath, newContent),\n };\n }\n\n const oldContent = readFileSync(resolvedPath, \"utf-8\");\n const diff = createPatch(filePath, oldContent, newContent, \"original\", \"modified\");\n\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n details: diff,\n };\n }\n}\n\n/**\n * Context provider for EditFile gadget.\n * Similar to WriteFile but handles edit-specific parameters.\n */\nexport class EditFileContextProvider implements ApprovalContextProvider {\n readonly gadgetName = \"EditFile\";\n\n async getContext(params: Record<string, unknown>): Promise<ApprovalContext> {\n const filePath = String(params.filePath ?? params.path ?? \"\");\n const resolvedPath = resolve(process.cwd(), filePath);\n\n // EditFile typically receives the full new content or edits\n // Handle both content-based and patch-based edits\n if (\"content\" in params) {\n const newContent = String(params.content);\n\n if (!existsSync(resolvedPath)) {\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n details: formatNewFileDiff(filePath, newContent),\n };\n }\n\n const oldContent = readFileSync(resolvedPath, \"utf-8\");\n const diff = createPatch(filePath, oldContent, newContent, \"original\", \"modified\");\n\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n details: diff,\n };\n }\n\n // For ed-style commands, show the commands themselves\n if (\"commands\" in params) {\n const commands = String(params.commands);\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n details: `Commands:\\n${commands}`,\n };\n }\n\n // Fallback\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n };\n }\n}\n\n/**\n * Default context provider for any gadget without a specific provider.\n * Shows gadget name and parameters.\n */\nexport class DefaultContextProvider implements ApprovalContextProvider {\n constructor(public readonly gadgetName: string) {}\n\n async getContext(params: Record<string, unknown>): Promise<ApprovalContext> {\n return {\n summary: formatGadgetSummary(this.gadgetName, params),\n };\n }\n}\n\n/**\n * Built-in context providers for common gadgets.\n * These provide custom details (diffs) while using universal summary format.\n */\nexport const builtinContextProviders: ApprovalContextProvider[] = [\n new WriteFileContextProvider(),\n new EditFileContextProvider(),\n // Note: RunCommand uses DefaultContextProvider - no custom details needed\n];\n","import chalk from \"chalk\";\n\n/**\n * Renders a unified diff with ANSI colors.\n *\n * Color scheme:\n * - Added lines (+): green\n * - Removed lines (-): red\n * - Hunk headers (@@): cyan\n * - File headers (---/+++): bold\n * - Context lines: dim\n *\n * @param diff - Unified diff string\n * @returns Colorized diff string\n */\nexport function renderColoredDiff(diff: string): string {\n return diff\n .split(\"\\n\")\n .map((line) => {\n // File headers\n if (line.startsWith(\"---\") || line.startsWith(\"+++\")) {\n return chalk.bold(line);\n }\n // Added lines (but not +++ header)\n if (line.startsWith(\"+\")) {\n return chalk.green(line);\n }\n // Removed lines (but not --- header)\n if (line.startsWith(\"-\")) {\n return chalk.red(line);\n }\n // Hunk headers\n if (line.startsWith(\"@@\")) {\n return chalk.cyan(line);\n }\n // Context lines and everything else\n return chalk.dim(line);\n })\n .join(\"\\n\");\n}\n\n/**\n * Formats a new file as a pseudo-diff showing all lines as additions.\n *\n * @param filePath - Path to the new file\n * @param content - Content of the new file\n * @returns Formatted pseudo-diff string\n */\nexport function formatNewFileDiff(filePath: string, content: string): string {\n const lines = content.split(\"\\n\");\n const header = `+++ ${filePath} (new file)`;\n const addedLines = lines.map((line) => `+ ${line}`).join(\"\\n\");\n return `${header}\\n${addedLines}`;\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 {\n BreakLoopException,\n HumanInputException,\n} 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\n .string()\n .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 HumanInputException(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\n .string()\n .optional()\n .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:\n \"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 BreakLoopException(\"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","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { BaseGadget } from \"../gadgets/gadget.js\";\nimport { getBuiltinGadget, isBuiltinGadgetName } from \"./builtins/index.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 BaseGadget {\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 *\n * @param value - Value to check\n * @returns True if value is a Gadget constructor\n */\nfunction isGadgetConstructor(value: unknown): value is new () => BaseGadget {\n if (typeof value !== \"function\") {\n return false;\n }\n\n const prototype = value.prototype as unknown;\n // Use duck typing for prototype check too\n return Boolean(prototype) && (prototype instanceof BaseGadget || 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): BaseGadget | 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): BaseGadget[] {\n const results: BaseGadget[] = [];\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 BaseGadget || isGadgetLike(value)) {\n results.push(value as BaseGadget);\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 (by name or \"builtin:\" prefix), file paths, and npm module names.\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. File paths (starting with ., /, ~) - resolve and import\n * 4. npm module names - dynamic import\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<BaseGadget[]> {\n const gadgets: BaseGadget[] = [];\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 // 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: BaseGadget[];\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 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 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 { 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\";\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)\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n proc.kill();\n reject(new Error(\"ed command timed out after 30000ms\"));\n }, 30000);\n });\n\n // Wait for process to complete or timeout\n const exitCode = await Promise.race([proc.exited, timeoutPromise]);\n\n // Collect output\n const stdout = await new Response(proc.stdout).text();\n const stderr = await new Response(proc.stderr).text();\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 { 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\n .number()\n .default(30000)\n .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: { argv: [\"gh\", \"pr\", \"review\", \"123\", \"--comment\", \"--body\", \"Review with `backticks` and 'quotes'\"], timeout: 30000 },\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\", \"pr\", \"review\", \"123\", \"--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 to complete or timeout\n const exitCode = await Promise.race([proc.exited, timeoutPromise]);\n\n // Clear timeout on normal exit to prevent dangling timer\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n\n // Collect output\n const stdout = await new Response(proc.stdout).text();\n const stderr = await new Response(proc.stderr).text();\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 { BaseGadget } from \"../../gadgets/gadget.js\";\nimport { listDirectory } from \"./filesystem/list-directory.js\";\nimport { readFile } from \"./filesystem/read-file.js\";\nimport { writeFile } from \"./filesystem/write-file.js\";\nimport { editFile } from \"./filesystem/edit-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, BaseGadget> = {\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): BaseGadget | 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","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport 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(option: string | boolean | undefined, subdir: string): 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 lines.push(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, TTYStream } 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: TTYStream): 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 { formatTokens, formatCost } 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\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 constructor(\n private readonly target: NodeJS.WritableStream,\n private readonly isTTY: boolean,\n private readonly modelRegistry?: ModelRegistry,\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(\":\")\n ? this.model.split(\":\")[1]\n : 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 * 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 const spinner = SPINNER_FRAMES[this.frameIndex++ % SPINNER_FRAMES.length];\n\n if (this.mode === \"streaming\") {\n this.renderStreamingMode(spinner);\n } else {\n this.renderCumulativeMode(spinner);\n }\n this.hasRendered = true;\n }\n\n private renderStreamingMode(spinner: string): void {\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 // Build status parts: #N model | â in â â out â time | cost\n const parts: string[] = [];\n\n // #N model (iteration number + model name)\n const iterPart = chalk.cyan(`#${this.currentIteration}`);\n if (this.model) {\n parts.push(`${iterPart} ${chalk.magenta(this.model)}`);\n } else {\n parts.push(iterPart);\n }\n\n // Context usage percentage (color-coded by usage level)\n const usagePercent = this.getContextUsagePercent();\n if (usagePercent !== null) {\n const formatted = `${Math.round(usagePercent)}%`;\n if (usagePercent >= 80) {\n parts.push(chalk.red(formatted)); // Danger zone - compaction threshold\n } else if (usagePercent >= 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 (this.callInputTokens > 0) {\n const prefix = this.callInputTokensEstimated ? \"~\" : \"\";\n parts.push(chalk.dim(\"â\") + chalk.yellow(` ${prefix}${formatTokens(this.callInputTokens)}`));\n }\n\n // â output tokens\n if (this.isStreaming || outTokens > 0) {\n const prefix = this.callOutputTokensEstimated ? \"~\" : \"\";\n parts.push(chalk.dim(\"â\") + chalk.green(` ${prefix}${formatTokens(outTokens)}`));\n }\n\n // Time\n parts.push(chalk.dim(`${elapsed}s`));\n\n // Live cost estimate for current call (updates as tokens stream in)\n const callCost = this.calculateCurrentCallCost(outTokens);\n if (callCost > 0) {\n parts.push(chalk.cyan(`$${formatCost(callCost)}`));\n }\n\n this.target.write(`\\r${parts.join(chalk.dim(\" | \"))} ${chalk.cyan(spinner)}`);\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 private renderCumulativeMode(spinner: string): void {\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 this.target.write(`\\r${parts.join(chalk.dim(\" | \"))} ${chalk.cyan(spinner)}`);\n }\n\n /**\n * Pauses the progress indicator and clears the line.\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 // Only clear the line if we actually rendered something\n if (this.hasRendered) {\n // Clear spinner line and ensure cursor is at column 0\n // \\r = carriage return (go to column 0)\n // \\x1b[K = clear from cursor to end of line\n // \\x1b[0G = move cursor to column 0 (ensures we're at start even after clear)\n this.target.write(\"\\r\\x1b[K\\x1b[0G\");\n this.hasRendered = false;\n }\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 { marked, type MarkedExtension } from \"marked\";\nimport { markedTerminal } from \"marked-terminal\";\nimport type { TokenUsage } from \"../../core/options.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 * 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 * 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\n/**\n * Formats a gadget execution result as a compact one-liner for stderr output.\n *\n * Provides visual feedback for gadget execution during agent runs. Different\n * icons and colors indicate success, error, or completion states.\n *\n * **Format:**\n * - Success: `â GadgetName(param=value, ...) â 248 tokens 123ms`\n * - Error: `â GadgetName(param=value) error: message 123ms`\n * - Completion: `âš GadgetName(param=value) â 2.5k tokens 123ms`\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 one-liner 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) â 248 tokens 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) error: File not found 2ms\"\n * ```\n */\n/**\n * Formats parameters as a compact inline string with color-coded keys and values.\n *\n * @param params - Parameter key-value pairs\n * @returns Formatted string with dim keys and cyan values, e.g., \"path=., recursive=true\"\n */\nfunction formatParametersInline(params: Record<string, unknown> | undefined): string {\n if (!params || Object.keys(params).length === 0) {\n return \"\";\n }\n\n return Object.entries(params)\n .map(([key, value]) => {\n // Format value compactly\n let formatted: string;\n if (typeof value === \"string\") {\n // Truncate long strings\n formatted = value.length > 30 ? `${value.slice(0, 30)}âĻ` : value;\n } else if (typeof value === \"boolean\" || typeof value === \"number\") {\n formatted = String(value);\n } else {\n // For arrays/objects, show compact JSON\n const json = JSON.stringify(value);\n formatted = json.length > 30 ? `${json.slice(0, 30)}âĻ` : json;\n }\n // Color: dim key, = sign, cyan value\n return `${chalk.dim(key)}${chalk.dim(\"=\")}${chalk.cyan(formatted)}`;\n })\n .join(chalk.dim(\", \"));\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\nexport function formatGadgetSummary(result: GadgetResult): string {\n // Format gadget name and execution time\n const gadgetLabel = chalk.magenta.bold(result.gadgetName);\n const timeLabel = chalk.dim(`${Math.round(result.executionTimeMs)}ms`);\n\n // Format parameters inline (parentheses are dim, content is color-coded)\n const paramsStr = formatParametersInline(result.parameters);\n const paramsLabel = paramsStr ? `${chalk.dim(\"(\")}${paramsStr}${chalk.dim(\")\")}` : \"\";\n\n // Error case - show error message in red (one-liner)\n if (result.error) {\n const errorMsg = result.error.length > 50 ? `${result.error.slice(0, 50)}âĻ` : result.error;\n return `${chalk.red(\"â\")} ${gadgetLabel}${paramsLabel} ${chalk.red(\"error:\")} ${errorMsg} ${timeLabel}`;\n }\n\n // Format output size: prefer token count if available, fallback to bytes\n let outputLabel: string;\n if (result.tokenCount !== undefined && result.tokenCount > 0) {\n outputLabel = chalk.green(`${formatTokens(result.tokenCount)} tokens`);\n } else if (result.result) {\n const outputBytes = Buffer.byteLength(result.result, \"utf-8\");\n outputLabel = outputBytes > 0 ? chalk.green(formatBytes(outputBytes)) : chalk.dim(\"no output\");\n } else {\n outputLabel = chalk.dim(\"no output\");\n }\n\n // Build the summary line\n const icon = result.breaksLoop ? chalk.yellow(\"âš\") : chalk.green(\"â\");\n const summaryLine = `${icon} ${gadgetLabel}${paramsLabel} ${chalk.dim(\"â\")} ${outputLabel} ${timeLabel}`;\n\n // TellUser gadget: display full message content below the summary (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 `${summaryLine}\\n${rendered}`;\n }\n\n return summaryLine;\n}\n","import type { Command } from \"commander\";\nimport type { AgentConfig, CompleteConfig, CustomCommandConfig, GadgetApprovalConfig } from \"./config.js\";\nimport { DEFAULT_MODEL, OPTION_DESCRIPTIONS, OPTION_FLAGS } from \"./constants.js\";\nimport { createNumericParser } from \"./utils.js\";\n\n/**\n * Options for the complete command (camelCase, matching Commander output).\n */\nexport interface CompleteCommandOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxTokens?: number;\n quiet?: boolean;\n logLlmRequests?: string | boolean;\n}\n\n/**\n * Options for the agent command (camelCase, matching Commander output).\n */\nexport interface AgentCommandOptions {\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?: GadgetApprovalConfig;\n quiet?: boolean;\n logLlmRequests?: string | boolean;\n /** Enable Docker sandboxing */\n docker?: boolean;\n /** Enable Docker with read-only CWD mount */\n dockerRo?: boolean;\n /** Disable Docker (override config) */\n noDocker?: boolean;\n /** Enable Docker dev mode (mount local source) */\n dockerDev?: boolean;\n /** Per-profile CWD mount permission override */\n dockerCwdPermission?: \"ro\" | \"rw\";\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(OPTION_FLAGS.logLlmRequests, OPTION_DESCRIPTIONS.logLlmRequests, defaults?.[\"log-llm-requests\"]);\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(OPTION_FLAGS.logLlmRequests, OPTION_DESCRIPTIONS.logLlmRequests, defaults?.[\"log-llm-requests\"])\n .option(OPTION_FLAGS.docker, OPTION_DESCRIPTIONS.docker)\n .option(OPTION_FLAGS.dockerRo, OPTION_DESCRIPTIONS.dockerRo)\n .option(OPTION_FLAGS.noDocker, OPTION_DESCRIPTIONS.noDocker)\n .option(OPTION_FLAGS.dockerDev, OPTION_DESCRIPTIONS.dockerDev);\n}\n\n/**\n * Converts kebab-case config to camelCase command options for complete command.\n */\nexport function configToCompleteOptions(config: CustomCommandConfig): Partial<CompleteCommandOptions> {\n const result: Partial<CompleteCommandOptions> = {};\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<AgentCommandOptions> {\n const result: Partial<AgentCommandOptions> = {};\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)\n 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.docker !== undefined) result.docker = config.docker;\n if (config[\"docker-cwd-permission\"] !== undefined)\n result.dockerCwdPermission = config[\"docker-cwd-permission\"];\n return result;\n}\n","/**\n * Docker sandboxing type definitions.\n *\n * These types define the configuration schema for running llmist agent\n * commands inside Docker containers for security isolation.\n */\n\n/**\n * Mount permission for Docker volume mounts.\n * - \"ro\": Read-only mount (safer, prevents modifications)\n * - \"rw\": Read-write mount (allows modifications)\n */\nexport type MountPermission = \"ro\" | \"rw\";\n\n/**\n * Valid mount permissions for validation.\n */\nexport const VALID_MOUNT_PERMISSIONS: MountPermission[] = [\"ro\", \"rw\"];\n\n/**\n * Configuration for an additional mount point.\n */\nexport interface MountConfig {\n /** Host path to mount (supports ~ for home directory) */\n source: string;\n /** Path inside the container */\n target: string;\n /** Mount permission mode */\n permission: MountPermission;\n}\n\n/**\n * Docker configuration section in cli.toml.\n *\n * @example\n * ```toml\n * [docker]\n * enabled = true\n * cwd-permission = \"rw\"\n * config-permission = \"ro\"\n * image-name = \"llmist-sandbox\"\n *\n * [[docker.mounts]]\n * source = \"~/data\"\n * target = \"/data\"\n * permission = \"ro\"\n * ```\n */\nexport interface DockerConfig {\n /** Enable Docker sandboxing globally (default: false) */\n enabled?: boolean;\n\n /** Custom Dockerfile contents (overrides default template) */\n dockerfile?: string;\n\n /** Permission for current working directory mount (default: \"rw\") */\n \"cwd-permission\"?: MountPermission;\n\n /** Permission for ~/.llmist config directory mount (default: \"ro\") */\n \"config-permission\"?: MountPermission;\n\n /** Additional mount points */\n mounts?: MountConfig[];\n\n /** Extra environment variables to forward to container */\n \"env-vars\"?: string[];\n\n /** Custom Docker image name (default: \"llmist-sandbox\") */\n \"image-name\"?: string;\n\n /** Enable dev mode - mount local source instead of npm install */\n \"dev-mode\"?: boolean;\n\n /** Path to llmist source for dev mode (supports ~ for home directory) */\n \"dev-source\"?: string;\n\n /** Extra arguments to pass to docker run (e.g., [\"-p\", \"3000:3000\"]) */\n \"docker-args\"?: string[];\n}\n\n/**\n * Valid keys for docker config validation.\n */\nexport const DOCKER_CONFIG_KEYS = new Set([\n \"enabled\",\n \"dockerfile\",\n \"cwd-permission\",\n \"config-permission\",\n \"mounts\",\n \"env-vars\",\n \"image-name\",\n \"dev-mode\",\n \"dev-source\",\n \"docker-args\",\n]);\n\n/**\n * Docker CLI options (resolved from config and CLI flags).\n */\nexport interface DockerOptions {\n /** Docker mode enabled via --docker flag */\n docker: boolean;\n /** Read-only CWD mount via --docker-ro flag */\n dockerRo: boolean;\n /** Explicitly disabled via --no-docker flag */\n noDocker: boolean;\n /** Dev mode - mount local source instead of npm install */\n dockerDev: boolean;\n}\n\n/**\n * Resolved Docker execution context.\n */\nexport interface DockerExecutionContext {\n /** Merged Docker configuration */\n config: DockerConfig;\n /** CLI options */\n options: DockerOptions;\n /** Original CLI arguments to forward (minus docker flags) */\n forwardArgs: string[];\n /** Current working directory on host */\n cwd: string;\n /** Profile-level CWD permission override (takes precedence over config) */\n profileCwdPermission?: MountPermission;\n}\n\n/**\n * Default Docker image name.\n */\nexport const DEFAULT_IMAGE_NAME = \"llmist-sandbox\";\n\n/**\n * Default mount permissions.\n */\nexport const DEFAULT_CWD_PERMISSION: MountPermission = \"rw\";\nexport const DEFAULT_CONFIG_PERMISSION: MountPermission = \"ro\";\n\n/**\n * API keys that are always forwarded to the container.\n */\nexport const FORWARDED_API_KEYS = [\n \"ANTHROPIC_API_KEY\",\n \"OPENAI_API_KEY\",\n \"GEMINI_API_KEY\",\n] as const;\n\n/**\n * Dev mode Docker image name (separate from production).\n */\nexport const DEV_IMAGE_NAME = \"llmist-dev-sandbox\";\n\n/**\n * Mount target for llmist source in dev mode.\n */\nexport const DEV_SOURCE_MOUNT_TARGET = \"/llmist-src\";\n\n/**\n * Resolved dev mode settings.\n */\nexport interface DevModeSettings {\n /** Whether dev mode is enabled */\n enabled: boolean;\n /** Path to llmist source directory (undefined if not enabled) */\n sourcePath: string | undefined;\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 {\n type PromptsConfig,\n TemplateError,\n createTemplateEngine,\n hasTemplateSyntax,\n resolveTemplate,\n validateEnvVars,\n validatePrompts,\n} from \"./templates.js\";\nimport type { DockerConfig } from \"./docker/types.js\";\nimport { validateDockerConfig } from \"./docker/docker-config.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 approval mode 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 GadgetApprovalMode = \"allowed\" | \"denied\" | \"approval-required\";\n\n/**\n * Valid gadget approval modes.\n */\nconst VALID_APPROVAL_MODES: GadgetApprovalMode[] = [\"allowed\", \"denied\", \"approval-required\"];\n\n/**\n * Configuration for per-gadget approval behavior.\n * Keys are gadget names (case-insensitive), values are approval modes.\n * Special key \"*\" sets the default for unconfigured gadgets.\n */\nexport type GadgetApprovalConfig = Record<string, GadgetApprovalMode>;\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 * Base options shared by both complete and agent command configurations.\n */\nexport interface BaseCommandConfig {\n model?: string;\n system?: string;\n temperature?: number;\n inherits?: string | string[];\n /** Enable Docker sandboxing for this profile/command */\n docker?: boolean;\n /** Override CWD mount permission for this profile (\"ro\" or \"rw\") */\n \"docker-cwd-permission\"?: \"ro\" | \"rw\";\n}\n\n/**\n * Configuration for the complete command.\n */\nexport interface CompleteConfig extends BaseCommandConfig {\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 agent command.\n */\nexport interface AgentConfig extends BaseCommandConfig {\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\"?: GadgetApprovalConfig;\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 prompts?: PromptsConfig;\n docker?: DockerConfig;\n [customCommand: string]:\n | CustomCommandConfig\n | CompleteConfig\n | AgentConfig\n | GlobalConfig\n | PromptsConfig\n | DockerConfig\n | undefined;\n}\n\n// Re-export DockerConfig for consumers\nexport type { DockerConfig } from \"./docker/types.js\";\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 \"docker\", // Enable Docker sandboxing (only effective for agent type)\n \"docker-cwd-permission\", // Override CWD mount permission for this profile\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 \"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 \"docker\", // Enable Docker sandboxing for this profile\n \"docker-cwd-permission\", // Override CWD mount permission for this profile\n]);\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 that a value is a gadget approval config (object mapping gadget names to modes).\n */\nfunction validateGadgetApproval(value: unknown, section: string): GadgetApprovalConfig {\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: GadgetApprovalConfig = {};\n for (const [gadgetName, mode] of Object.entries(value as Record<string, unknown>)) {\n if (typeof mode !== \"string\") {\n throw new ConfigError(\n `[${section}].gadget-approval.${gadgetName} must be a string`,\n );\n }\n if (!VALID_APPROVAL_MODES.includes(mode as GadgetApprovalMode)) {\n throw new ConfigError(\n `[${section}].gadget-approval.${gadgetName} must be one of: ${VALID_APPROVAL_MODES.join(\", \")}`,\n );\n }\n result[gadgetName] = mode as GadgetApprovalMode;\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<BaseCommandConfig> {\n const result: Partial<BaseCommandConfig> = {};\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 if (\"docker\" in raw) {\n result.docker = validateBoolean(raw.docker, \"docker\", section);\n }\n if (\"docker-cwd-permission\" in raw) {\n const perm = validateString(raw[\"docker-cwd-permission\"], \"docker-cwd-permission\", section);\n if (perm !== \"ro\" && perm !== \"rw\") {\n throw new ConfigError(`[${section}].docker-cwd-permission must be \"ro\" or \"rw\"`);\n }\n result[\"docker-cwd-permission\"] = perm as \"ro\" | \"rw\";\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(rawObj[\"gadget-remove\"], \"gadget-remove\", section);\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 (\"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 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(rawObj[\"gadget-remove\"], \"gadget-remove\", section);\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\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 === \"prompts\") {\n result.prompts = validatePromptsConfig(value, key);\n } else if (key === \"docker\") {\n result.docker = validateDockerConfig(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([\"global\", \"complete\", \"agent\", \"prompts\", \"docker\"]);\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(\n template: string,\n promptName?: string,\n configPath?: string,\n): 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","/**\n * Docker configuration validation.\n *\n * Follows the same validation patterns as the main config.ts module.\n */\n\nimport { ConfigError } from \"../config.js\";\nimport {\n type DockerConfig,\n type MountConfig,\n type MountPermission,\n DOCKER_CONFIG_KEYS,\n VALID_MOUNT_PERMISSIONS,\n} from \"./types.js\";\n\n/**\n * Valid keys for mount config objects.\n */\nconst MOUNT_CONFIG_KEYS = new Set([\"source\", \"target\", \"permission\"]);\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 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 a mount permission value.\n */\nfunction validateMountPermission(value: unknown, key: string, section: string): MountPermission {\n const str = validateString(value, key, section);\n if (!VALID_MOUNT_PERMISSIONS.includes(str as MountPermission)) {\n throw new ConfigError(\n `[${section}].${key} must be one of: ${VALID_MOUNT_PERMISSIONS.join(\", \")}`,\n );\n }\n return str as MountPermission;\n}\n\n/**\n * Validates a single mount configuration object.\n */\nfunction validateMountConfig(value: unknown, index: number, section: string): MountConfig {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new ConfigError(`[${section}].mounts[${index}] must be a table`);\n }\n\n const rawObj = value as Record<string, unknown>;\n const mountSection = `${section}.mounts[${index}]`;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!MOUNT_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${mountSection}].${key} is not a valid mount option`);\n }\n }\n\n // Required fields\n if (!(\"source\" in rawObj)) {\n throw new ConfigError(`[${mountSection}] missing required field 'source'`);\n }\n if (!(\"target\" in rawObj)) {\n throw new ConfigError(`[${mountSection}] missing required field 'target'`);\n }\n if (!(\"permission\" in rawObj)) {\n throw new ConfigError(`[${mountSection}] missing required field 'permission'`);\n }\n\n return {\n source: validateString(rawObj.source, \"source\", mountSection),\n target: validateString(rawObj.target, \"target\", mountSection),\n permission: validateMountPermission(rawObj.permission, \"permission\", mountSection),\n };\n}\n\n/**\n * Validates an array of mount configurations.\n */\nfunction validateMountsArray(value: unknown, section: string): MountConfig[] {\n if (!Array.isArray(value)) {\n throw new ConfigError(`[${section}].mounts must be an array of tables`);\n }\n\n const result: MountConfig[] = [];\n for (let i = 0; i < value.length; i++) {\n result.push(validateMountConfig(value[i], i, section));\n }\n return result;\n}\n\n/**\n * Validates the docker configuration section.\n *\n * @param raw - Raw config object from TOML parser\n * @param section - Section name for error messages (usually \"docker\")\n * @returns Validated DockerConfig\n * @throws ConfigError if validation fails\n */\nexport function validateDockerConfig(raw: unknown, section: string): DockerConfig {\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 (!DOCKER_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n const result: DockerConfig = {};\n\n if (\"enabled\" in rawObj) {\n result.enabled = validateBoolean(rawObj.enabled, \"enabled\", section);\n }\n\n if (\"dockerfile\" in rawObj) {\n result.dockerfile = validateString(rawObj.dockerfile, \"dockerfile\", section);\n }\n\n if (\"cwd-permission\" in rawObj) {\n result[\"cwd-permission\"] = validateMountPermission(\n rawObj[\"cwd-permission\"],\n \"cwd-permission\",\n section,\n );\n }\n\n if (\"config-permission\" in rawObj) {\n result[\"config-permission\"] = validateMountPermission(\n rawObj[\"config-permission\"],\n \"config-permission\",\n section,\n );\n }\n\n if (\"mounts\" in rawObj) {\n result.mounts = validateMountsArray(rawObj.mounts, section);\n }\n\n if (\"env-vars\" in rawObj) {\n result[\"env-vars\"] = validateStringArray(rawObj[\"env-vars\"], \"env-vars\", section);\n }\n\n if (\"image-name\" in rawObj) {\n result[\"image-name\"] = validateString(rawObj[\"image-name\"], \"image-name\", section);\n }\n\n if (\"dev-mode\" in rawObj) {\n result[\"dev-mode\"] = validateBoolean(rawObj[\"dev-mode\"], \"dev-mode\", section);\n }\n\n if (\"dev-source\" in rawObj) {\n result[\"dev-source\"] = validateString(rawObj[\"dev-source\"], \"dev-source\", section);\n }\n\n // Note: docker-args is intentionally only configurable in the global ~/.llmist/cli.toml.\n // Since llmist only loads config from the user's home directory (not project-level configs),\n // this is inherently safe from supply-chain attacks where a malicious project could inject\n // dangerous Docker arguments like \"--privileged\" or \"-v /:/host\".\n if (\"docker-args\" in rawObj) {\n result[\"docker-args\"] = validateStringArray(rawObj[\"docker-args\"], \"docker-args\", section);\n }\n\n return result;\n}\n","/**\n * Dockerfile templates for llmist sandboxing.\n *\n * Two templates are provided:\n * - DEFAULT_DOCKERFILE: Production mode - installs llmist from npm\n * - DEV_DOCKERFILE: Dev mode - runs from mounted source code\n *\n * Both include:\n * - Bun runtime\n * - ed (line editor for EditFile gadget)\n * - ripgrep (fast search tool)\n * - ast-grep (code search/refactoring)\n * - git (version control)\n */\n\nimport type { DockerConfig } from \"./types.js\";\nimport { DEV_SOURCE_MOUNT_TARGET } from \"./types.js\";\n\n/**\n * Default Dockerfile template.\n *\n * Uses oven/bun:1-debian as base for:\n * - Modern Bun runtime\n * - Debian's extensive package ecosystem\n * - Good compatibility with common tools\n */\nexport const DEFAULT_DOCKERFILE = `# llmist sandbox image\n# Auto-generated - customize via [docker].dockerfile in cli.toml\n\nFROM oven/bun:1-debian\n\n# Install essential tools\nRUN apt-get update && apt-get install -y --no-install-recommends \\\\\n # ed for EditFile gadget (line-oriented editor)\n ed \\\\\n # ripgrep for fast file searching\n ripgrep \\\\\n # git for version control operations\n git \\\\\n # curl for downloads and API calls\n curl \\\\\n # ca-certificates for HTTPS\n ca-certificates \\\\\n && rm -rf /var/lib/apt/lists/*\n\n# Install ast-grep for code search/refactoring\n# Using the official install script\nRUN curl -fsSL https://raw.githubusercontent.com/ast-grep/ast-grep/main/install.sh | bash \\\\\n && mv /root/.local/bin/ast-grep /usr/local/bin/ 2>/dev/null || true \\\\\n && mv /root/.local/bin/sg /usr/local/bin/ 2>/dev/null || true\n\n# Install llmist globally via bun\nRUN bun add -g llmist\n\n# Working directory (host CWD will be mounted here)\nWORKDIR /workspace\n\n# Entry point - llmist with all arguments forwarded\nENTRYPOINT [\"llmist\"]\n`;\n\n/**\n * Dev mode Dockerfile template.\n *\n * Key differences from production:\n * - Does NOT install llmist from npm\n * - Expects llmist source to be mounted at ${DEV_SOURCE_MOUNT_TARGET}\n * - Runs directly from source via bun\n */\nexport const DEV_DOCKERFILE = `# llmist DEV sandbox image\n# For development/testing with local source code\n\nFROM oven/bun:1-debian\n\n# Install essential tools (same as production)\nRUN apt-get update && apt-get install -y --no-install-recommends \\\\\n ed \\\\\n ripgrep \\\\\n git \\\\\n curl \\\\\n ca-certificates \\\\\n && rm -rf /var/lib/apt/lists/*\n\n# Install ast-grep for code search/refactoring\nRUN curl -fsSL https://raw.githubusercontent.com/ast-grep/ast-grep/main/install.sh | bash \\\\\n && mv /root/.local/bin/ast-grep /usr/local/bin/ 2>/dev/null || true \\\\\n && mv /root/.local/bin/sg /usr/local/bin/ 2>/dev/null || true\n\n# Working directory (host CWD will be mounted here)\nWORKDIR /workspace\n\n# Entry point - run llmist from mounted source\n# Source is mounted at ${DEV_SOURCE_MOUNT_TARGET}\nENTRYPOINT [\"bun\", \"run\", \"${DEV_SOURCE_MOUNT_TARGET}/src/cli.ts\"]\n`;\n\n/**\n * Resolves the Dockerfile content to use.\n *\n * Priority:\n * 1. Custom dockerfile from config (always takes precedence)\n * 2. DEV_DOCKERFILE if dev mode is enabled\n * 3. DEFAULT_DOCKERFILE (production)\n *\n * @param config - Docker configuration\n * @param devMode - Whether dev mode is enabled\n * @returns Dockerfile content\n */\nexport function resolveDockerfile(config: DockerConfig, devMode = false): string {\n // Custom Dockerfile always takes precedence\n if (config.dockerfile) {\n return config.dockerfile;\n }\n return devMode ? DEV_DOCKERFILE : DEFAULT_DOCKERFILE;\n}\n\n/**\n * Computes a hash of the Dockerfile content for cache invalidation.\n *\n * Uses Bun's fast native hash function.\n *\n * @param dockerfile - Dockerfile content\n * @returns Hex string hash\n */\nexport function computeDockerfileHash(dockerfile: string): string {\n const encoder = new TextEncoder();\n const data = encoder.encode(dockerfile);\n // Bun.hash returns a 64-bit hash as BigInt, convert to hex string\n return Bun.hash(data).toString(16);\n}\n","/**\n * Docker image building and caching.\n *\n * Handles:\n * - Building Docker images from Dockerfile content\n * - Caching image hashes to avoid unnecessary rebuilds\n * - Checking if an image needs to be rebuilt\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { computeDockerfileHash } from \"./dockerfile.js\";\nimport { DEFAULT_IMAGE_NAME } from \"./types.js\";\n\n/**\n * Cache directory for Docker-related files.\n */\nconst CACHE_DIR = join(homedir(), \".llmist\", \"docker-cache\");\n\n/**\n * File storing the current image hash.\n */\nconst HASH_FILE = \"image-hash.json\";\n\n/**\n * Cache entry structure.\n */\ninterface CacheEntry {\n imageName: string;\n dockerfileHash: string;\n builtAt: string;\n}\n\n/**\n * Ensures the cache directory exists.\n */\nfunction ensureCacheDir(): void {\n if (!existsSync(CACHE_DIR)) {\n mkdirSync(CACHE_DIR, { recursive: true });\n }\n}\n\n/**\n * Gets the cached hash for an image name.\n *\n * @param imageName - Docker image name\n * @returns Cached dockerfile hash, or undefined if not cached\n */\nfunction getCachedHash(imageName: string): string | undefined {\n const hashPath = join(CACHE_DIR, HASH_FILE);\n\n if (!existsSync(hashPath)) {\n return undefined;\n }\n\n try {\n const content = readFileSync(hashPath, \"utf-8\");\n const cache = JSON.parse(content) as Record<string, CacheEntry>;\n return cache[imageName]?.dockerfileHash;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Saves the hash for an image name to cache.\n *\n * @param imageName - Docker image name\n * @param hash - Dockerfile hash\n */\nfunction setCachedHash(imageName: string, hash: string): void {\n ensureCacheDir();\n const hashPath = join(CACHE_DIR, HASH_FILE);\n\n let cache: Record<string, CacheEntry> = {};\n\n if (existsSync(hashPath)) {\n try {\n const content = readFileSync(hashPath, \"utf-8\");\n cache = JSON.parse(content) as Record<string, CacheEntry>;\n } catch {\n // Start fresh on parse error\n cache = {};\n }\n }\n\n cache[imageName] = {\n imageName,\n dockerfileHash: hash,\n builtAt: new Date().toISOString(),\n };\n\n writeFileSync(hashPath, JSON.stringify(cache, null, 2));\n}\n\n/**\n * Error thrown when Docker image building fails.\n */\nexport class DockerBuildError extends Error {\n constructor(\n message: string,\n public readonly output: string,\n ) {\n super(message);\n this.name = \"DockerBuildError\";\n }\n}\n\n/**\n * Builds a Docker image from Dockerfile content.\n *\n * @param imageName - Name/tag for the built image\n * @param dockerfile - Dockerfile content\n * @throws DockerBuildError if build fails\n */\nasync function buildImage(imageName: string, dockerfile: string): Promise<void> {\n // Write Dockerfile to temp location\n ensureCacheDir();\n const dockerfilePath = join(CACHE_DIR, \"Dockerfile\");\n writeFileSync(dockerfilePath, dockerfile);\n\n // Build the image\n const proc = Bun.spawn(\n [\"docker\", \"build\", \"-t\", imageName, \"-f\", dockerfilePath, CACHE_DIR],\n {\n stdout: \"pipe\",\n stderr: \"pipe\",\n },\n );\n\n const exitCode = await proc.exited;\n const stdout = await new Response(proc.stdout).text();\n const stderr = await new Response(proc.stderr).text();\n\n if (exitCode !== 0) {\n const output = [stdout, stderr].filter(Boolean).join(\"\\n\");\n throw new DockerBuildError(\n `Docker build failed with exit code ${exitCode}`,\n output,\n );\n }\n}\n\n/**\n * Ensures the Docker image is built and up-to-date.\n *\n * Checks if the cached Dockerfile hash matches the current content.\n * If not, rebuilds the image.\n *\n * @param imageName - Docker image name (defaults to DEFAULT_IMAGE_NAME)\n * @param dockerfile - Dockerfile content\n * @returns The image name (for chaining)\n * @throws DockerBuildError if build fails\n */\nexport async function ensureImage(\n imageName: string = DEFAULT_IMAGE_NAME,\n dockerfile: string,\n): Promise<string> {\n const hash = computeDockerfileHash(dockerfile);\n const cachedHash = getCachedHash(imageName);\n\n if (cachedHash === hash) {\n // Image is up-to-date\n return imageName;\n }\n\n // Need to build/rebuild\n console.error(`Building Docker image '${imageName}'...`);\n await buildImage(imageName, dockerfile);\n\n // Update cache\n setCachedHash(imageName, hash);\n\n console.error(`Docker image '${imageName}' built successfully.`);\n return imageName;\n}\n\n/**\n * Checks if an image needs to be rebuilt.\n *\n * @param imageName - Docker image name\n * @param dockerfile - Dockerfile content\n * @returns true if rebuild is needed\n */\nexport function needsRebuild(imageName: string, dockerfile: string): boolean {\n const hash = computeDockerfileHash(dockerfile);\n const cachedHash = getCachedHash(imageName);\n return cachedHash !== hash;\n}\n\n/**\n * Clears the image cache for a specific image or all images.\n *\n * @param imageName - Image name to clear, or undefined to clear all\n */\nexport function clearImageCache(imageName?: string): void {\n const hashPath = join(CACHE_DIR, HASH_FILE);\n\n if (!existsSync(hashPath)) {\n return;\n }\n\n if (imageName) {\n try {\n const content = readFileSync(hashPath, \"utf-8\");\n const cache = JSON.parse(content) as Record<string, CacheEntry>;\n delete cache[imageName];\n writeFileSync(hashPath, JSON.stringify(cache, null, 2));\n } catch {\n // Ignore errors\n }\n } else {\n // Clear all\n writeFileSync(hashPath, \"{}\");\n }\n}\n","/**\n * Docker execution wrapper.\n *\n * Handles:\n * - Checking if Docker is available\n * - Building/caching the Docker image\n * - Running llmist inside the container\n * - Forwarding environment variables and mounts\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { resolveDockerfile } from \"./dockerfile.js\";\nimport { ensureImage, DockerBuildError } from \"./image-manager.js\";\nimport {\n type DevModeSettings,\n type DockerConfig,\n type DockerExecutionContext,\n type DockerOptions,\n type MountPermission,\n DEFAULT_IMAGE_NAME,\n DEFAULT_CWD_PERMISSION,\n DEFAULT_CONFIG_PERMISSION,\n DEV_IMAGE_NAME,\n DEV_SOURCE_MOUNT_TARGET,\n FORWARDED_API_KEYS,\n} from \"./types.js\";\n\n/**\n * Error thrown when Docker is not available.\n */\nexport class DockerUnavailableError extends Error {\n constructor() {\n super(\n \"Docker is required but not available. \" +\n \"Install Docker or disable Docker sandboxing in your configuration.\",\n );\n this.name = \"DockerUnavailableError\";\n }\n}\n\n/**\n * Error thrown when Docker container execution fails.\n */\nexport class DockerRunError extends Error {\n constructor(\n public readonly exitCode: number,\n public readonly stderr: string,\n ) {\n super(`Docker container exited with code ${exitCode}`);\n this.name = \"DockerRunError\";\n }\n}\n\n/**\n * Error thrown when Docker execution should be skipped.\n * This occurs when already running inside a container.\n */\nexport class DockerSkipError extends Error {\n constructor() {\n super(\"Docker execution skipped - already inside container\");\n this.name = \"DockerSkipError\";\n }\n}\n\n/**\n * Checks if Docker is available and running.\n *\n * @returns true if Docker is available\n */\nexport async function checkDockerAvailable(): Promise<boolean> {\n try {\n const proc = Bun.spawn([\"docker\", \"info\"], {\n stdout: \"pipe\",\n stderr: \"pipe\",\n });\n await proc.exited;\n return proc.exitCode === 0;\n } catch {\n return false;\n }\n}\n\n/**\n * Checks if we're already running inside a Docker container.\n *\n * Detection methods:\n * 1. /.dockerenv file - Docker creates this in all containers\n * 2. /proc/1/cgroup contains \"docker\" or \"containerd\" - Linux cgroup detection\n *\n * @returns true if running inside a container\n */\nexport function isInsideContainer(): boolean {\n // Method 1: Check for /.dockerenv (most reliable)\n if (existsSync(\"/.dockerenv\")) {\n return true;\n }\n\n // Method 2: Check cgroup for docker/containerd (Linux)\n try {\n const cgroup = readFileSync(\"/proc/1/cgroup\", \"utf-8\");\n if (cgroup.includes(\"docker\") || cgroup.includes(\"containerd\")) {\n return true;\n }\n } catch {\n // Not on Linux or no access to /proc\n }\n\n return false;\n}\n\n/**\n * Attempts to auto-detect the llmist source directory.\n *\n * Checks if the current script is being run from an llmist source tree\n * by examining the script path and verifying package.json.\n *\n * @returns Path to llmist source directory, or undefined if not detectable\n */\nexport function autoDetectDevSource(): string | undefined {\n // Check if running from source via bun (e.g., `bun src/cli.ts`)\n const scriptPath = process.argv[1];\n if (!scriptPath || !scriptPath.endsWith(\"src/cli.ts\")) {\n return undefined;\n }\n\n const srcDir = dirname(scriptPath);\n const projectDir = dirname(srcDir);\n\n // Verify it's the llmist project by checking package.json\n const packageJsonPath = join(projectDir, \"package.json\");\n if (!existsSync(packageJsonPath)) {\n return undefined;\n }\n\n try {\n const pkg = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"));\n if (pkg.name === \"llmist\") {\n return projectDir;\n }\n } catch {\n // Ignore parse errors\n }\n\n return undefined;\n}\n\n/**\n * Resolves dev mode settings.\n *\n * Priority for enablement:\n * 1. CLI --docker-dev flag\n * 2. Config [docker].dev-mode\n * 3. LLMIST_DEV_MODE environment variable\n *\n * Priority for source path:\n * 1. Config [docker].dev-source\n * 2. LLMIST_DEV_SOURCE environment variable\n * 3. Auto-detect from script path\n *\n * @param config - Docker configuration\n * @param cliDevMode - Whether --docker-dev flag was used\n * @returns Resolved dev mode settings\n * @throws Error if dev mode is enabled but source path cannot be found\n */\nexport function resolveDevMode(\n config: DockerConfig | undefined,\n cliDevMode: boolean,\n): DevModeSettings {\n // Check if dev mode is enabled\n const enabled = cliDevMode || config?.[\"dev-mode\"] || process.env.LLMIST_DEV_MODE === \"1\";\n\n if (!enabled) {\n return { enabled: false, sourcePath: undefined };\n }\n\n // Resolve source path\n const sourcePath =\n config?.[\"dev-source\"] || process.env.LLMIST_DEV_SOURCE || autoDetectDevSource();\n\n if (!sourcePath) {\n throw new Error(\n \"Docker dev mode enabled but llmist source path not found. \" +\n \"Set [docker].dev-source in config, LLMIST_DEV_SOURCE env var, \" +\n \"or run from the llmist source directory (bun src/cli.ts).\",\n );\n }\n\n return { enabled: true, sourcePath };\n}\n\n/**\n * Expands ~ to home directory in a path.\n */\nfunction expandHome(path: string): string {\n if (path.startsWith(\"~\")) {\n return path.replace(/^~/, homedir());\n }\n return path;\n}\n\n/**\n * Builds the docker run command arguments.\n *\n * @param ctx - Docker execution context\n * @param imageName - Docker image name to run\n * @param devMode - Dev mode settings (for source mounting)\n * @returns Array of arguments for docker run\n */\nfunction buildDockerRunArgs(\n ctx: DockerExecutionContext,\n imageName: string,\n devMode: DevModeSettings,\n): string[] {\n const args: string[] = [\"run\", \"--rm\"];\n\n // Generate unique container name to avoid collisions\n const timestamp = Date.now();\n const random = Math.random().toString(36).slice(2, 8);\n const containerName = `llmist-${timestamp}-${random}`;\n args.push(\"--name\", containerName);\n\n // TTY handling - only add -it if stdin is a TTY\n if (process.stdin.isTTY) {\n args.push(\"-it\");\n }\n\n // Mount current working directory\n // Priority: --docker-ro flag > profile-level > config-level > default\n const cwdPermission: MountPermission = ctx.options.dockerRo\n ? \"ro\"\n : (ctx.profileCwdPermission ?? ctx.config[\"cwd-permission\"] ?? DEFAULT_CWD_PERMISSION);\n args.push(\"-v\", `${ctx.cwd}:/workspace:${cwdPermission}`);\n args.push(\"-w\", \"/workspace\");\n\n // Mount ~/.llmist config directory (for config access inside container)\n const configPermission = ctx.config[\"config-permission\"] ?? DEFAULT_CONFIG_PERMISSION;\n const llmistDir = expandHome(\"~/.llmist\");\n args.push(\"-v\", `${llmistDir}:/root/.llmist:${configPermission}`);\n\n // Mount llmist source in dev mode (read-only to prevent accidental modifications)\n if (devMode.enabled && devMode.sourcePath) {\n const expandedSource = expandHome(devMode.sourcePath);\n args.push(\"-v\", `${expandedSource}:${DEV_SOURCE_MOUNT_TARGET}:ro`);\n }\n\n // Additional mounts from config\n if (ctx.config.mounts) {\n for (const mount of ctx.config.mounts) {\n const source = expandHome(mount.source);\n args.push(\"-v\", `${source}:${mount.target}:${mount.permission}`);\n }\n }\n\n // Forward API keys (if set in environment)\n for (const key of FORWARDED_API_KEYS) {\n if (process.env[key]) {\n args.push(\"-e\", key);\n }\n }\n\n // Forward additional env vars from config\n if (ctx.config[\"env-vars\"]) {\n for (const key of ctx.config[\"env-vars\"]) {\n if (process.env[key]) {\n args.push(\"-e\", key);\n }\n }\n }\n\n // Extra docker run arguments from config (e.g., port mappings, network mode)\n if (ctx.config[\"docker-args\"]) {\n args.push(...ctx.config[\"docker-args\"]);\n }\n\n // Image name\n args.push(imageName);\n\n // Forward the CLI arguments (these go to llmist inside the container)\n args.push(...ctx.forwardArgs);\n\n return args;\n}\n\n/**\n * Filters out Docker-related flags from CLI arguments.\n *\n * These flags are consumed by the wrapper and should not be\n * passed to the llmist instance inside the container.\n *\n * @param argv - Original CLI arguments\n * @returns Filtered arguments without Docker flags\n */\nexport function filterDockerArgs(argv: string[]): string[] {\n const dockerFlags = new Set([\"--docker\", \"--docker-ro\", \"--no-docker\", \"--docker-dev\"]);\n return argv.filter((arg) => !dockerFlags.has(arg));\n}\n\n/**\n * Resolves whether Docker mode should be enabled.\n *\n * Priority (highest to lowest):\n * 1. --no-docker flag (disables)\n * 2. --docker or --docker-ro flag (enables)\n * 3. Profile/command docker: true in config\n * 4. Global [docker].enabled in config\n *\n * @param config - Docker configuration\n * @param options - CLI options\n * @param profileDocker - docker: true/false from profile config\n * @returns Whether Docker mode is enabled\n */\nexport function resolveDockerEnabled(\n config: DockerConfig | undefined,\n options: DockerOptions,\n profileDocker?: boolean,\n): boolean {\n // CLI --no-docker overrides everything\n if (options.noDocker) {\n return false;\n }\n\n // CLI --docker or --docker-ro enables\n if (options.docker || options.dockerRo) {\n return true;\n }\n\n // Profile-level docker: true/false\n if (profileDocker !== undefined) {\n return profileDocker;\n }\n\n // Global [docker].enabled\n return config?.enabled ?? false;\n}\n\n/**\n * Executes llmist inside a Docker container.\n *\n * This function:\n * 1. Checks if already inside a container (prevents nesting)\n * 2. Verifies Docker is available\n * 3. Builds/caches the image (dev or production)\n * 4. Runs the container with appropriate mounts and env vars\n * 5. Exits with the container's exit code\n *\n * @param ctx - Docker execution context\n * @param devMode - Dev mode settings\n * @throws DockerUnavailableError if Docker is not available\n * @throws DockerBuildError if image building fails\n * @throws DockerRunError if container execution fails\n */\nexport async function executeInDocker(\n ctx: DockerExecutionContext,\n devMode: DevModeSettings,\n): Promise<never> {\n // Check if we're already inside a container\n if (isInsideContainer()) {\n console.error(\n \"Warning: Docker mode requested but already inside a container. \" +\n \"Proceeding without re-containerization.\",\n );\n // Signal to caller that Docker should be skipped\n throw new DockerSkipError();\n }\n\n // Check Docker availability\n const available = await checkDockerAvailable();\n if (!available) {\n throw new DockerUnavailableError();\n }\n\n // Resolve Dockerfile and image name based on dev mode\n const dockerfile = resolveDockerfile(ctx.config, devMode.enabled);\n const imageName = devMode.enabled\n ? DEV_IMAGE_NAME\n : (ctx.config[\"image-name\"] ?? DEFAULT_IMAGE_NAME);\n\n // Show dev mode feedback\n if (devMode.enabled) {\n console.error(`[dev mode] Mounting source from ${devMode.sourcePath}`);\n }\n\n try {\n await ensureImage(imageName, dockerfile);\n } catch (error) {\n if (error instanceof DockerBuildError) {\n console.error(\"Docker build failed:\");\n console.error(error.output);\n throw error;\n }\n throw error;\n }\n\n // Build docker run command\n const dockerArgs = buildDockerRunArgs(ctx, imageName, devMode);\n\n // Execute container\n const proc = Bun.spawn([\"docker\", ...dockerArgs], {\n stdin: \"inherit\",\n stdout: \"inherit\",\n stderr: \"inherit\",\n });\n\n const exitCode = await proc.exited;\n process.exit(exitCode);\n}\n\n/**\n * Creates a Docker execution context from config and options.\n *\n * @param config - Docker configuration\n * @param options - CLI options\n * @param argv - Original CLI arguments (without 'node' and script name)\n * @param cwd - Current working directory\n * @param profileCwdPermission - Profile-level CWD permission override\n * @returns Docker execution context\n */\nexport function createDockerContext(\n config: DockerConfig | undefined,\n options: DockerOptions,\n argv: string[],\n cwd: string,\n profileCwdPermission?: \"ro\" | \"rw\",\n): DockerExecutionContext {\n return {\n config: config ?? {},\n options,\n forwardArgs: filterDockerArgs(argv),\n cwd,\n profileCwdPermission,\n };\n}\n\n// Re-export errors for consumers\nexport { DockerBuildError } from \"./image-manager.js\";\n","import type { Command } from \"commander\";\n\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 {\n createSessionDir,\n formatLlmRequest,\n resolveLogDir,\n writeLogFile,\n} from \"./llm-logging.js\";\nimport {\n addCompleteOptions,\n type CompleteCommandOptions,\n} 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: CompleteCommandOptions,\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 builder.addUser(prompt);\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 CompleteCommandOptions, env), env),\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 type { Command } from \"commander\";\nimport chalk from \"chalk\";\n\nimport type { BaseGadget } 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 { loadGadgets } from \"./gadgets.js\";\nimport { promptForParameters, readStdinJson } from \"./gadget-prompts.js\";\nimport { executeAction } from \"./utils.js\";\n\n/**\n * Result of selecting a gadget from a file.\n */\ninterface GadgetSelection {\n gadget: BaseGadget;\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` +\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: BaseGadget, 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) =>\n executeAction(() => executeGadgetValidate(file, env), env),\n );\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\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .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.split(\",\").map((s) => s.trim()).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(stdin: NodeJS.ReadableStream): 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 { type Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { executeAction } from \"./utils.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport { MODEL_ALIASES } from \"../core/model-shortcuts.js\";\n\ninterface ModelsCommandOptions {\n provider?: string;\n format?: \"table\" | \"json\";\n verbose?: boolean;\n}\n\nasync function handleModelsCommand(\n options: ModelsCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const client = env.createClient();\n\n // Get models, optionally filtered by provider\n const models = client.modelRegistry.listModels(options.provider);\n\n if (options.format === \"json\") {\n renderJSON(models, env.stdout);\n } else {\n renderTable(models, options.verbose || false, env.stdout);\n }\n}\n\nfunction renderTable(models: ModelSpec[], verbose: boolean, stream: NodeJS.WritableStream): 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 // Header\n stream.write(chalk.bold.cyan(\"\\nAvailable Models\\n\"));\n stream.write(chalk.cyan(\"=\".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} Models\\n`));\n\n if (verbose) {\n renderVerboseTable(providerModels, stream);\n } else {\n renderCompactTable(providerModels, stream);\n }\n\n stream.write(\"\\n\");\n }\n\n // Display shortcuts\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(chalk.cyan(` ${shortcut.padEnd(15)}`) + chalk.dim(\" â \") + chalk.white(fullName) + \"\\n\");\n }\n stream.write(\"\\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(chalk.dim(\"â\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\n\");\n stream.write(\n chalk.bold(\n \"Model ID\".padEnd(idWidth) +\n \" \" + \"Display Name\".padEnd(nameWidth) +\n \" \" + \"Context\".padEnd(contextWidth) +\n \" \" + \"Input\".padEnd(inputWidth) +\n \" \" + \"Output\".padEnd(outputWidth)\n ) + \"\\n\"\n );\n stream.write(chalk.dim(\"â\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\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 \" \" + chalk.white(model.displayName.padEnd(nameWidth)) +\n \" \" + chalk.yellow(contextFormatted.padEnd(contextWidth)) +\n \" \" + chalk.cyan(inputPrice.padEnd(inputWidth)) +\n \" \" + chalk.cyan(outputPrice.padEnd(outputWidth)) +\n \"\\n\"\n );\n }\n\n stream.write(chalk.dim(\"â\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\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(` ${chalk.dim(\"Context:\")} ${chalk.yellow(formatTokens(model.contextWindow))}\\n`);\n stream.write(` ${chalk.dim(\"Max Output:\")} ${chalk.yellow(formatTokens(model.maxOutputTokens))}\\n`);\n stream.write(` ${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 if (model.pricing.cachedInput !== undefined) {\n stream.write(` ${chalk.dim(\"Cached Input:\")} ${chalk.cyan(`$${model.pricing.cachedInput.toFixed(2)} per 1M tokens`)}\\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\nfunction renderJSON(models: ModelSpec[], stream: NodeJS.WritableStream): void {\n const output = {\n models: models.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 shortcuts: MODEL_ALIASES,\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 all available LLM 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 .action((options) =>\n executeAction(\n () => handleModelsCommand(options as ModelsCommandOptions, env),\n env,\n ),\n );\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\";\nimport type { DockerConfig } from \"./docker/types.js\";\n\n/**\n * Stream type that may have TTY capabilities.\n */\nexport type TTYStream = 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: TTYStream;\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 /** Docker sandboxing configuration from [docker] section */\n dockerConfig?: DockerConfig;\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 } from \"./config.js\";\nimport { createLoggerFactory, type CLIEnvironment, type CLILoggerConfig } from \"./environment.js\";\nimport {\n addAgentOptions,\n addCompleteOptions,\n type AgentCommandOptions,\n type CompleteCommandOptions,\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): 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: CompleteCommandOptions = {\n ...configDefaults,\n ...(cliOptions as Partial<CompleteCommandOptions>),\n } as CompleteCommandOptions;\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: AgentCommandOptions = {\n ...configDefaults,\n ...(cliOptions as Partial<AgentCommandOptions>),\n } as AgentCommandOptions;\n await executeAgent(prompt, options, cmdEnv);\n }, cmdEnv);\n });\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":"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","names":["InvalidArgumentError","createInterface","chalk","chalk","chalk","fs","path","fs","path","z","fs","path","z","fs","z","z","fs","fs","path","z","z","path","fs","z","z","z","z","path","fs","writeFile","chalk","chalk","formatGadgetSummary","chalk","existsSync","readFileSync","homedir","join","join","homedir","path","existsSync","readFileSync","validateString","validateBoolean","validateStringArray","existsSync","readFileSync","homedir","join","join","homedir","existsSync","readFileSync","existsSync","readFileSync","join","homedir","existsSync","readFileSync","join","path","homedir","createInterface","gadgets","chalk","stderrTTY","formatGadgetSummary","chalk","createInterface","chalk","chalk","result","chalk","chalk","formatTokens","chalk","resolve","InvalidArgumentError"]}
|