llmist 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -75
- package/dist/{chunk-KORMY3CD.js → chunk-RZTAKIDE.js} +605 -4
- package/dist/chunk-RZTAKIDE.js.map +1 -0
- package/dist/{chunk-LELPPETT.js → chunk-TFIKR2RK.js} +459 -3
- package/dist/chunk-TFIKR2RK.js.map +1 -0
- package/dist/cli.cjs +628 -23
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +49 -22
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +769 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +354 -32
- package/dist/index.d.ts +354 -32
- package/dist/index.js +177 -2
- package/dist/index.js.map +1 -1
- package/dist/{mock-stream-DKF5yatf.d.cts → mock-stream-DNt-HBTn.d.cts} +525 -79
- package/dist/{mock-stream-DKF5yatf.d.ts → mock-stream-DNt-HBTn.d.ts} +525 -79
- package/dist/testing/index.cjs +1063 -4
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +437 -3
- package/dist/testing/index.d.ts +437 -3
- package/dist/testing/index.js +54 -4
- package/package.json +1 -1
- package/dist/chunk-KORMY3CD.js.map +0 -1
- package/dist/chunk-LELPPETT.js.map +0 -1
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/cli/builtin-gadgets.ts","../src/cli/gadgets.ts","../src/cli/llm-logging.ts","../src/cli/utils.ts","../src/cli/ui/formatters.ts","../src/cli/option-helpers.ts","../src/cli/complete-command.ts","../src/cli/config.ts","../src/cli/templates.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 logLlmResponses: \"--log-llm-responses [dir]\",\n noBuiltins: \"--no-builtins\",\n noBuiltinInteraction: \"--no-builtin-interaction\",\n quiet: \"-q, --quiet\",\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 raw LLM requests as plain text. Optional dir, defaults to ~/.llmist/logs/requests/\",\n logLlmResponses: \"Save raw LLM responses as plain text. Optional dir, defaults to ~/.llmist/logs/responses/\",\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} 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 = { ...defaultEnv, ...envOverrides };\n const program = createProgram(env, config);\n await program.parseAsync(env.argv);\n}\n","{\n \"name\": \"llmist\",\n \"version\": \"1.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 \"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/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 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 { 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 { formatLlmRequest, resolveLogDir, writeLogFile } from \"./llm-logging.js\";\nimport { addAgentOptions, type AgentCommandOptions } from \"./option-helpers.js\";\nimport {\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\";\n\n/**\n * Prompts the user for approval with optional rejection feedback.\n * Used by the gating controller to approve dangerous gadget executions.\n *\n * SHOWCASE: This demonstrates how to build approval workflows using llmist's\n * controller hooks. The CLI gates RunCommand executions, but the pattern\n * can be applied to any gadget that needs user approval.\n *\n * @param env - CLI environment for I/O operations\n * @param prompt - The prompt to display to the user\n * @returns The user's input (empty string or \"y\" = approved, anything else = rejection reason)\n */\nasync function promptApproval(env: CLIEnvironment, prompt: string): Promise<string> {\n const rl = createInterface({ input: env.stdin, output: env.stderr });\n try {\n const answer = await rl.question(prompt);\n return answer.trim();\n } finally {\n rl.close();\n }\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 * @returns Human input handler function or undefined if not interactive\n */\nfunction createHumanInputHandler(\n env: CLIEnvironment,\n progress: StreamProgress,\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 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 }\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 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 let usage: TokenUsage | undefined;\n let iterations = 0;\n\n // Resolve LLM debug log directories (if enabled)\n const llmRequestsDir = resolveLogDir(options.logLlmRequests, \"requests\");\n const llmResponsesDir = resolveLogDir(options.logLlmResponses, \"responses\");\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 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 // Write LLM request to debug log if enabled\n if (llmRequestsDir) {\n const filename = `${Date.now()}_call_${llmCallCounter}.request.txt`;\n const content = formatLlmRequest(context.options.messages);\n await writeLogFile(llmRequestsDir, filename, content);\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 // 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 (llmResponsesDir) {\n const filename = `${Date.now()}_call_${llmCallCounter}.response.txt`;\n await writeLogFile(llmResponsesDir, filename, context.rawResponse);\n }\n },\n },\n\n // SHOWCASE: Controller-based approval gating for dangerous gadgets\n //\n // This demonstrates how to add safety layers WITHOUT modifying gadgets.\n // The RunCommand gadget is simple - it just executes commands. The CLI\n // adds the approval flow externally via beforeGadgetExecution controller.\n //\n // This pattern is composable: you can apply the same gating logic to\n // any gadget (DeleteFile, SendEmail, etc.) without changing the gadgets.\n controllers: {\n beforeGadgetExecution: async (ctx) => {\n // Only gate RunCommand - let other gadgets through\n if (ctx.gadgetName !== \"RunCommand\") {\n return { action: \"proceed\" };\n }\n\n // Only prompt for approval in interactive mode\n const stdinTTY = isInteractive(env.stdin);\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n if (!stdinTTY || !stderrTTY) {\n // Non-interactive mode: deny by default for safety\n return {\n action: \"skip\",\n syntheticResult:\n \"status=denied\\n\\nRunCommand requires interactive approval. Run in a terminal to approve commands.\",\n };\n }\n\n const command = ctx.parameters.command as string;\n\n // Pause progress indicator and prompt for approval\n progress.pause();\n env.stderr.write(`\\n🔒 Execute: ${chalk.cyan(command)}\\n`);\n\n const response = await promptApproval(env, \" ⏎ 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 env.stderr.write(` ${chalk.red(\"✗ Denied\")}\\n\\n`);\n return {\n action: \"skip\",\n syntheticResult: `status=denied\\n\\nCommand rejected by user with message: \"${response}\"`,\n };\n }\n\n env.stderr.write(` ${chalk.green(\"✓ Approved\")}\\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);\n if (humanInputHandler) {\n builder.onHumanInput(humanInputHandler);\n }\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 // 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 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\n // Flush any remaining buffered text with markdown rendering\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(() => executeAgent(prompt, options as AgentCommandOptions, env), env),\n );\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 and optionally ends the conversation.\n *\n * Use this for key results, warnings, or structured output that should stand out\n * from regular streamed text. Set done=true when the task is complete.\n */\nexport const tellUser = createGadget({\n name: \"TellUser\",\n description:\n \"Tell the user something important. Set done=true when your work is complete and you want to end the conversation.\",\n schema: z.object({\n message: z\n .string()\n .optional()\n .describe(\"The message to display to the user in Markdown\"),\n done: z\n .boolean()\n .default(false)\n .describe(\"Set to true to end the conversation, false to continue\"),\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: \"Report successful completion and end the conversation\",\n params: {\n message: \"I've completed the refactoring. All tests pass.\",\n done: true,\n type: \"success\",\n },\n },\n {\n comment: \"Warn the user about something without ending\",\n params: {\n message: \"Found 3 files with potential issues. Continuing analysis...\",\n done: false,\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 done: false,\n type: \"info\",\n },\n },\n ],\n execute: ({ message, done, 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 const plainResult = prefixes[type] + message;\n\n if (done) {\n throw new BreakLoopException(plainResult);\n }\n return plainResult;\n },\n});\n\n/**\n * All built-in gadgets as an array for easy registration.\n */\nexport const builtinGadgets = [askUser, tellUser];\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { BaseGadget } from \"../gadgets/gadget.js\";\n\n/**\n * Function type for importing modules dynamically.\n */\nexport type GadgetImportFunction = (specifier: string) => Promise<unknown>;\n\nconst PATH_PREFIXES = [\".\", \"/\", \"~\"];\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 * 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 file paths or npm module names.\n * Resolves paths, imports modules, and extracts gadgets.\n *\n * @param specifiers - Array of gadget specifiers (file paths or module names)\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 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 { 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","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\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 // ↑ 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 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 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 } 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 logLlmResponses?: 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 quiet?: boolean;\n logLlmRequests?: string | boolean;\n logLlmResponses?: string | boolean;\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 .option(OPTION_FLAGS.logLlmResponses, OPTION_DESCRIPTIONS.logLlmResponses, defaults?.[\"log-llm-responses\"]);\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?.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.logLlmResponses, OPTION_DESCRIPTIONS.logLlmResponses, defaults?.[\"log-llm-responses\"]);\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 if (config[\"log-llm-responses\"] !== undefined) result.logLlmResponses = config[\"log-llm-responses\"];\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 if (config.gadget !== undefined) result.gadget = config.gadget;\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.quiet !== undefined) result.quiet = config.quiet;\n if (config[\"log-llm-requests\"] !== undefined) result.logLlmRequests = config[\"log-llm-requests\"];\n if (config[\"log-llm-responses\"] !== undefined) result.logLlmResponses = config[\"log-llm-responses\"];\n return result;\n}\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 { formatLlmRequest, resolveLogDir, writeLogFile } 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 directories (if enabled)\n const llmRequestsDir = resolveLogDir(options.logLlmRequests, \"requests\");\n const llmResponsesDir = resolveLogDir(options.logLlmResponses, \"responses\");\n const timestamp = Date.now();\n\n // Log request before streaming\n if (llmRequestsDir) {\n const filename = `${timestamp}_complete.request.txt`;\n const content = formatLlmRequest(messages);\n await writeLogFile(llmRequestsDir, filename, content);\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 (llmResponsesDir) {\n const filename = `${timestamp}_complete.response.txt`;\n await writeLogFile(llmResponsesDir, 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","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\";\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 * 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}\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 \"log-llm-responses\"?: string | boolean;\n}\n\n/**\n * Configuration for the agent command.\n */\nexport interface AgentConfig extends BaseCommandConfig {\n \"max-iterations\"?: number;\n gadget?: string[];\n builtins?: boolean;\n \"builtin-interaction\"?: boolean;\n \"gadget-start-prefix\"?: string;\n \"gadget-end-prefix\"?: string;\n \"gadget-arg-prefix\"?: string;\n quiet?: boolean;\n \"log-level\"?: LogLevel;\n \"log-file\"?: string;\n \"log-reset\"?: boolean;\n \"log-llm-requests\"?: string | boolean;\n \"log-llm-responses\"?: 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 [customCommand: string]:\n | CustomCommandConfig\n | CompleteConfig\n | AgentConfig\n | GlobalConfig\n | PromptsConfig\n | undefined;\n}\n\n/** Valid keys for global config */\nconst GLOBAL_CONFIG_KEYS = new Set([\"log-level\", \"log-file\", \"log-reset\"]);\n\n/** Valid log levels */\nconst VALID_LOG_LEVELS: LogLevel[] = [\"silly\", \"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"];\n\n/** Valid keys for complete command config */\nconst COMPLETE_CONFIG_KEYS = new Set([\n \"model\",\n \"system\",\n \"temperature\",\n \"max-tokens\",\n \"quiet\",\n \"inherits\",\n \"log-level\",\n \"log-file\",\n \"log-reset\",\n \"log-llm-requests\",\n \"log-llm-responses\",\n \"type\", // Allowed for inheritance compatibility, ignored for built-in commands\n]);\n\n/** Valid keys for agent command config */\nconst AGENT_CONFIG_KEYS = new Set([\n \"model\",\n \"system\",\n \"temperature\",\n \"max-iterations\",\n \"gadget\",\n \"builtins\",\n \"builtin-interaction\",\n \"gadget-start-prefix\",\n \"gadget-end-prefix\",\n \"gadget-arg-prefix\",\n \"quiet\",\n \"inherits\",\n \"log-level\",\n \"log-file\",\n \"log-reset\",\n \"log-llm-requests\",\n \"log-llm-responses\",\n \"type\", // Allowed for inheritance compatibility, ignored for built-in commands\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 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\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 if (\"log-llm-responses\" in rawObj) {\n result[\"log-llm-responses\"] = validateStringOrBoolean(\n rawObj[\"log-llm-responses\"],\n \"log-llm-responses\",\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 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 (\"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 if (\"log-llm-responses\" in rawObj) {\n result[\"log-llm-responses\"] = validateStringOrBoolean(\n rawObj[\"log-llm-responses\"],\n \"log-llm-responses\",\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 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\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 {\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\"]);\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 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\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 // Apply own values on top (excluding 'inherits' key - it's metadata, not a value)\n const { inherits: _inherits, ...ownValues } = sectionObj;\n merged = { ...merged, ...ownValues };\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 into context\n const fullContext = {\n ...context,\n env: process.env,\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 * 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\n try {\n if (gadget.timeoutMs && gadget.timeoutMs > 0) {\n result = 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 result = await Promise.resolve(gadget.execute(params));\n }\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 env.stderr.write(chalk.green(`\\n✓ Completed in ${elapsed}ms\\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\";\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}\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 */\nfunction 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 { createDefaultEnvironment, 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 // Create new environment with merged logging config\n return createDefaultEnvironment(loggerConfig);\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","chalk","chalk","chalk","gadgets","stderrTTY","chalk","homedir","join","join","homedir","path","chalk","createInterface","chalk","chalk","result","chalk","chalk","formatTokens","chalk","InvalidArgumentError"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/constants.ts","../src/cli/program.ts","../package.json","../src/cli/agent-command.ts","../src/cli/builtin-gadgets.ts","../src/cli/gadgets.ts","../src/cli/llm-logging.ts","../src/cli/utils.ts","../src/cli/ui/formatters.ts","../src/cli/option-helpers.ts","../src/cli/complete-command.ts","../src/cli/config.ts","../src/cli/templates.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 logLlmResponses: \"--log-llm-responses [dir]\",\n noBuiltins: \"--no-builtins\",\n noBuiltinInteraction: \"--no-builtin-interaction\",\n quiet: \"-q, --quiet\",\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 raw LLM requests as plain text. Optional dir, defaults to ~/.llmist/logs/requests/\",\n logLlmResponses: \"Save raw LLM responses as plain text. Optional dir, defaults to ~/.llmist/logs/responses/\",\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} 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 = { ...defaultEnv, ...envOverrides };\n const program = createProgram(env, config);\n await program.parseAsync(env.argv);\n}\n","{\n \"name\": \"llmist\",\n \"version\": \"1.3.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 \"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/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 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 { 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 { formatLlmRequest, resolveLogDir, writeLogFile } from \"./llm-logging.js\";\nimport { addAgentOptions, type AgentCommandOptions } from \"./option-helpers.js\";\nimport {\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\";\n\n/**\n * Prompts the user for approval with optional rejection feedback.\n * Used by the gating controller to approve dangerous gadget executions.\n *\n * SHOWCASE: This demonstrates how to build approval workflows using llmist's\n * controller hooks. The CLI gates RunCommand executions, but the pattern\n * can be applied to any gadget that needs user approval.\n *\n * @param env - CLI environment for I/O operations\n * @param prompt - The prompt to display to the user\n * @returns The user's input (empty string or \"y\" = approved, anything else = rejection reason)\n */\nasync function promptApproval(env: CLIEnvironment, prompt: string): Promise<string> {\n const rl = createInterface({ input: env.stdin, output: env.stderr });\n try {\n const answer = await rl.question(prompt);\n return answer.trim();\n } finally {\n rl.close();\n }\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 * @returns Human input handler function or undefined if not interactive\n */\nfunction createHumanInputHandler(\n env: CLIEnvironment,\n progress: StreamProgress,\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 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 }\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 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 let usage: TokenUsage | undefined;\n let iterations = 0;\n\n // Resolve LLM debug log directories (if enabled)\n const llmRequestsDir = resolveLogDir(options.logLlmRequests, \"requests\");\n const llmResponsesDir = resolveLogDir(options.logLlmResponses, \"responses\");\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 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 // Write LLM request to debug log if enabled\n if (llmRequestsDir) {\n const filename = `${Date.now()}_call_${llmCallCounter}.request.txt`;\n const content = formatLlmRequest(context.options.messages);\n await writeLogFile(llmRequestsDir, filename, content);\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 // 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 (llmResponsesDir) {\n const filename = `${Date.now()}_call_${llmCallCounter}.response.txt`;\n await writeLogFile(llmResponsesDir, filename, context.rawResponse);\n }\n },\n },\n\n // SHOWCASE: Controller-based approval gating for dangerous gadgets\n //\n // This demonstrates how to add safety layers WITHOUT modifying gadgets.\n // The RunCommand gadget is simple - it just executes commands. The CLI\n // adds the approval flow externally via beforeGadgetExecution controller.\n //\n // This pattern is composable: you can apply the same gating logic to\n // any gadget (DeleteFile, SendEmail, etc.) without changing the gadgets.\n controllers: {\n beforeGadgetExecution: async (ctx) => {\n // Only gate RunCommand - let other gadgets through\n if (ctx.gadgetName !== \"RunCommand\") {\n return { action: \"proceed\" };\n }\n\n // Only prompt for approval in interactive mode\n const stdinTTY = isInteractive(env.stdin);\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n if (!stdinTTY || !stderrTTY) {\n // Non-interactive mode: deny by default for safety\n return {\n action: \"skip\",\n syntheticResult:\n \"status=denied\\n\\nRunCommand requires interactive approval. Run in a terminal to approve commands.\",\n };\n }\n\n const command = ctx.parameters.command as string;\n\n // Pause progress indicator and prompt for approval\n progress.pause();\n env.stderr.write(`\\n🔒 Execute: ${chalk.cyan(command)}\\n`);\n\n const response = await promptApproval(env, \" ⏎ 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 env.stderr.write(` ${chalk.red(\"✗ Denied\")}\\n\\n`);\n return {\n action: \"skip\",\n syntheticResult: `status=denied\\n\\nCommand rejected by user with message: \"${response}\"`,\n };\n }\n\n env.stderr.write(` ${chalk.green(\"✓ Approved\")}\\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);\n if (humanInputHandler) {\n builder.onHumanInput(humanInputHandler);\n }\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 // 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 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\n // Flush any remaining buffered text with markdown rendering\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(() => executeAgent(prompt, options as AgentCommandOptions, env), env),\n );\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\";\n\n/**\n * Function type for importing modules dynamically.\n */\nexport type GadgetImportFunction = (specifier: string) => Promise<unknown>;\n\nconst PATH_PREFIXES = [\".\", \"/\", \"~\"];\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 * 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 file paths or npm module names.\n * Resolves paths, imports modules, and extracts gadgets.\n *\n * @param specifiers - Array of gadget specifiers (file paths or module names)\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 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 { 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","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\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 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 } 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 logLlmResponses?: 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 quiet?: boolean;\n logLlmRequests?: string | boolean;\n logLlmResponses?: string | boolean;\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 .option(OPTION_FLAGS.logLlmResponses, OPTION_DESCRIPTIONS.logLlmResponses, defaults?.[\"log-llm-responses\"]);\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?.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.logLlmResponses, OPTION_DESCRIPTIONS.logLlmResponses, defaults?.[\"log-llm-responses\"]);\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 if (config[\"log-llm-responses\"] !== undefined) result.logLlmResponses = config[\"log-llm-responses\"];\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 if (config.gadget !== undefined) result.gadget = config.gadget;\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.quiet !== undefined) result.quiet = config.quiet;\n if (config[\"log-llm-requests\"] !== undefined) result.logLlmRequests = config[\"log-llm-requests\"];\n if (config[\"log-llm-responses\"] !== undefined) result.logLlmResponses = config[\"log-llm-responses\"];\n return result;\n}\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 { formatLlmRequest, resolveLogDir, writeLogFile } 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 directories (if enabled)\n const llmRequestsDir = resolveLogDir(options.logLlmRequests, \"requests\");\n const llmResponsesDir = resolveLogDir(options.logLlmResponses, \"responses\");\n const timestamp = Date.now();\n\n // Log request before streaming\n if (llmRequestsDir) {\n const filename = `${timestamp}_complete.request.txt`;\n const content = formatLlmRequest(messages);\n await writeLogFile(llmRequestsDir, filename, content);\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 (llmResponsesDir) {\n const filename = `${timestamp}_complete.response.txt`;\n await writeLogFile(llmResponsesDir, 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","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\";\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 * 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}\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 \"log-llm-responses\"?: string | boolean;\n}\n\n/**\n * Configuration for the agent command.\n */\nexport interface AgentConfig extends BaseCommandConfig {\n \"max-iterations\"?: number;\n gadget?: string[];\n builtins?: boolean;\n \"builtin-interaction\"?: boolean;\n \"gadget-start-prefix\"?: string;\n \"gadget-end-prefix\"?: string;\n \"gadget-arg-prefix\"?: string;\n quiet?: boolean;\n \"log-level\"?: LogLevel;\n \"log-file\"?: string;\n \"log-reset\"?: boolean;\n \"log-llm-requests\"?: string | boolean;\n \"log-llm-responses\"?: 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 [customCommand: string]:\n | CustomCommandConfig\n | CompleteConfig\n | AgentConfig\n | GlobalConfig\n | PromptsConfig\n | undefined;\n}\n\n/** Valid keys for global config */\nconst GLOBAL_CONFIG_KEYS = new Set([\"log-level\", \"log-file\", \"log-reset\"]);\n\n/** Valid log levels */\nconst VALID_LOG_LEVELS: LogLevel[] = [\"silly\", \"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"];\n\n/** Valid keys for complete command config */\nconst COMPLETE_CONFIG_KEYS = new Set([\n \"model\",\n \"system\",\n \"temperature\",\n \"max-tokens\",\n \"quiet\",\n \"inherits\",\n \"log-level\",\n \"log-file\",\n \"log-reset\",\n \"log-llm-requests\",\n \"log-llm-responses\",\n \"type\", // Allowed for inheritance compatibility, ignored for built-in commands\n]);\n\n/** Valid keys for agent command config */\nconst AGENT_CONFIG_KEYS = new Set([\n \"model\",\n \"system\",\n \"temperature\",\n \"max-iterations\",\n \"gadget\",\n \"builtins\",\n \"builtin-interaction\",\n \"gadget-start-prefix\",\n \"gadget-end-prefix\",\n \"gadget-arg-prefix\",\n \"quiet\",\n \"inherits\",\n \"log-level\",\n \"log-file\",\n \"log-reset\",\n \"log-llm-requests\",\n \"log-llm-responses\",\n \"type\", // Allowed for inheritance compatibility, ignored for built-in commands\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 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\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 if (\"log-llm-responses\" in rawObj) {\n result[\"log-llm-responses\"] = validateStringOrBoolean(\n rawObj[\"log-llm-responses\"],\n \"log-llm-responses\",\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 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 (\"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 if (\"log-llm-responses\" in rawObj) {\n result[\"log-llm-responses\"] = validateStringOrBoolean(\n rawObj[\"log-llm-responses\"],\n \"log-llm-responses\",\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 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\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 {\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\"]);\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 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\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 // Apply own values on top (excluding 'inherits' key - it's metadata, not a value)\n const { inherits: _inherits, ...ownValues } = sectionObj;\n merged = { ...merged, ...ownValues };\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 * 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\n try {\n if (gadget.timeoutMs && gadget.timeoutMs > 0) {\n result = 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 result = await Promise.resolve(gadget.execute(params));\n }\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 env.stderr.write(chalk.green(`\\n✓ Completed in ${elapsed}ms\\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\";\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}\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 */\nfunction 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 { createDefaultEnvironment, 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 // Create new environment with merged logging config\n return createDefaultEnvironment(loggerConfig);\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","chalk","chalk","chalk","gadgets","stderrTTY","chalk","homedir","join","join","homedir","path","chalk","createInterface","chalk","chalk","result","chalk","chalk","formatTokens","chalk","InvalidArgumentError"]}
|