llmist 0.4.0 → 0.4.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/dist/{chunk-VRTKJK2X.js → chunk-A4GRCCXF.js} +2 -2
- package/dist/{chunk-VYBRYR2S.js → chunk-LQE7TKKW.js} +43 -38
- package/dist/chunk-LQE7TKKW.js.map +1 -0
- package/dist/{chunk-I55AV3WV.js → chunk-QVDGTUQN.js} +2 -2
- package/dist/cli.cjs +43 -38
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +42 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -3
- package/dist/index.d.ts +17 -3
- package/dist/index.js +3 -3
- package/dist/testing/index.cjs +42 -37
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-VYBRYR2S.js.map +0 -1
- /package/dist/{chunk-VRTKJK2X.js.map → chunk-A4GRCCXF.js.map} +0 -0
- /package/dist/{chunk-I55AV3WV.js.map → chunk-QVDGTUQN.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
createGadget
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QVDGTUQN.js";
|
|
5
5
|
import {
|
|
6
6
|
AgentBuilder,
|
|
7
7
|
BaseGadget,
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
init_model_shortcuts,
|
|
23
23
|
init_registry,
|
|
24
24
|
resolveModel
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-LQE7TKKW.js";
|
|
26
26
|
|
|
27
27
|
// src/cli/constants.ts
|
|
28
28
|
var CLI_NAME = "llmist";
|
|
@@ -69,7 +69,7 @@ import { Command, InvalidArgumentError as InvalidArgumentError3 } from "commande
|
|
|
69
69
|
// package.json
|
|
70
70
|
var package_default = {
|
|
71
71
|
name: "llmist",
|
|
72
|
-
version: "0.
|
|
72
|
+
version: "0.4.0",
|
|
73
73
|
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.",
|
|
74
74
|
type: "module",
|
|
75
75
|
main: "dist/index.cjs",
|
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/utils.ts","../src/cli/ui/formatters.ts","../src/cli/complete-command.ts","../src/cli/models-command.ts","../src/cli/environment.ts","../src/cli.ts"],"sourcesContent":["import type { ParameterFormat } from \"../gadgets/parser.js\";\n\n/** 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} 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/** Default parameter format for gadgets */\nexport const DEFAULT_PARAMETER_FORMAT: ParameterFormat = \"json\";\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 parameterFormat: \"--parameter-format <format>\",\n logLevel: \"--log-level <level>\",\n logFile: \"--log-file <path>\",\n noBuiltins: \"--no-builtins\",\n noBuiltinInteraction: \"--no-builtin-interaction\",\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 parameterFormat: \"Format for gadget parameter schemas: 'json', 'yaml', or 'auto'.\",\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 noBuiltins: \"Disable built-in gadgets (AskUser, TellUser).\",\n noBuiltinInteraction: \"Disable interactive gadgets (AskUser) while keeping TellUser.\",\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 { registerModelsCommand } from \"./models-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}\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 * @returns Configured Commander program ready for parsing\n */\nexport function createProgram(env: CLIEnvironment): 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 .configureOutput({\n writeOut: (str) => env.stdout.write(str),\n writeErr: (str) => env.stderr.write(str),\n });\n\n registerCompleteCommand(program, env);\n registerAgentCommand(program, env);\n registerModelsCommand(program, env);\n\n return program;\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 for testing or customization\n */\nexport async function runCLI(overrides: Partial<CLIEnvironment> = {}): Promise<void> {\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 .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 const loggerConfig: CLILoggerConfig = {\n logLevel: globalOpts.logLevel,\n logFile: globalOpts.logFile,\n };\n\n const defaultEnv = createDefaultEnvironment(loggerConfig);\n const env: CLIEnvironment = { ...defaultEnv, ...overrides };\n const program = createProgram(env);\n await program.parseAsync(env.argv);\n}\n","{\n \"name\": \"llmist\",\n \"version\": \"0.3.1\",\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 \"js-yaml\": \"^4.1.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/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, InvalidArgumentError } from \"commander\";\nimport { AgentBuilder } from \"../agent/builder.js\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { TokenUsage } from \"../core/options.js\";\nimport type { ParameterFormat } from \"../gadgets/parser.js\";\nimport { GadgetRegistry } from \"../gadgets/registry.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"../providers/constants.js\";\nimport { builtinGadgets } from \"./builtin-gadgets.js\";\nimport {\n COMMANDS,\n DEFAULT_MODEL,\n DEFAULT_PARAMETER_FORMAT,\n OPTION_DESCRIPTIONS,\n OPTION_FLAGS,\n} from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { loadGadgets } from \"./gadgets.js\";\nimport {\n createNumericParser,\n executeAction,\n isInteractive,\n renderSummary,\n resolvePrompt,\n StreamPrinter,\n StreamProgress,\n} from \"./utils.js\";\nimport { formatGadgetSummary, type GadgetResult } from \"./ui/formatters.js\";\n\n/**\n * Configuration options for the agent command.\n */\ninterface AgentCommandOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxIterations?: number;\n gadget?: string[];\n parameterFormat: ParameterFormat;\n builtins: boolean; // --no-builtins sets this to false\n builtinInteraction: boolean; // --no-builtin-interaction sets this to false\n}\n\nconst PARAMETER_FORMAT_VALUES: ParameterFormat[] = [\"json\", \"yaml\", \"auto\"];\n\n/**\n * Parses and validates the parameter format option value.\n *\n * @param value - User-provided parameter format string\n * @returns Validated parameter format\n * @throws InvalidArgumentError if format is not one of: json, yaml, auto\n */\nfunction parseParameterFormat(value: string): ParameterFormat {\n const normalized = value.toLowerCase() as ParameterFormat;\n if (!PARAMETER_FORMAT_VALUES.includes(normalized)) {\n throw new InvalidArgumentError(\"Parameter format must be one of 'json', 'yaml', or 'auto'.\");\n }\n return normalized;\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\n const questionLine = question.trim() ? `\\n${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 * Handles the agent command execution.\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 */\nasync function handleAgentCommand(\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 if (options.builtins !== false) {\n for (const gadget of builtinGadgets) {\n // Skip AskUser if --no-builtin-interaction is set\n // Useful for non-interactive environments (CI, pipes, etc.)\n if (options.builtinInteraction === false && gadget.name === \"AskUser\") {\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 finishReason: string | null | undefined;\n let usage: TokenUsage | undefined;\n let iterations = 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 // 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 // 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 // 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 }\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 finishReason = context.finishReason;\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 // End this call's progress tracking and switch to cumulative mode\n progress.endCall(context.usage);\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 // Note: parameterFormat is not directly supported in AgentBuilder\n // This might need to be added to AgentBuilder API if needed\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 for await (const event of agent.run()) {\n if (event.type === \"text\") {\n // Stream LLM output to stdout\n // Pause progress indicator to avoid stderr/stdout interleaving\n progress.pause();\n printer.write(event.content);\n } else if (event.type === \"gadget_result\") {\n // Show gadget execution feedback on stderr\n // Only displayed in TTY mode (hidden when piped)\n progress.pause();\n if (stderrTTY) {\n env.stderr.write(`${formatGadgetSummary(event.result)}\\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 progress.complete();\n printer.ensureNewline();\n\n // Only show summary if stderr is a TTY (not redirected)\n if (stderrTTY) {\n const summary = renderSummary({\n finishReason,\n usage,\n iterations,\n cost: progress.getTotalCost(),\n elapsedSeconds: progress.getTotalElapsedSeconds(),\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 */\nexport function registerAgentCommand(program: Command, env: CLIEnvironment): void {\n 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 .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, DEFAULT_MODEL)\n .option(OPTION_FLAGS.systemPrompt, OPTION_DESCRIPTIONS.systemPrompt)\n .option(\n OPTION_FLAGS.temperature,\n OPTION_DESCRIPTIONS.temperature,\n createNumericParser({ label: \"Temperature\", min: 0, max: 2 }),\n )\n .option(\n OPTION_FLAGS.maxIterations,\n OPTION_DESCRIPTIONS.maxIterations,\n createNumericParser({ label: \"Max iterations\", integer: true, min: 1 }),\n )\n .option(\n OPTION_FLAGS.gadgetModule,\n OPTION_DESCRIPTIONS.gadgetModule,\n (value: string, previous: string[] = []) => [...previous, value],\n [] as string[],\n )\n .option(\n OPTION_FLAGS.parameterFormat,\n OPTION_DESCRIPTIONS.parameterFormat,\n parseParameterFormat,\n DEFAULT_PARAMETER_FORMAT,\n )\n .option(OPTION_FLAGS.noBuiltins, OPTION_DESCRIPTIONS.noBuiltins)\n .option(OPTION_FLAGS.noBuiltinInteraction, OPTION_DESCRIPTIONS.noBuiltinInteraction)\n .action((prompt, options) =>\n executeAction(() => handleAgentCommand(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 chalk from \"chalk\";\nimport { z } from \"zod\";\n\nimport { createGadget } from \"../gadgets/create-gadget.js\";\nimport { BreakLoopException, HumanInputException } from \"../gadgets/exceptions.js\";\n\n/**\n * AskUser gadget - Asks the user a question and waits for their response.\n *\n * Use this when you need more information or clarification from the user.\n */\nexport const askUser = createGadget({\n name: \"AskUser\",\n description:\n \"Ask the user a question when you need more information or clarification. The user's response will be provided back to you.\",\n schema: z.object({\n question: z.string().describe(\"The question to ask the user\"),\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.string().describe(\"The message to display to the user\"),\n done: z.boolean().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 execute: ({ message, done, type }) => {\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 * 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 return Boolean(prototype) && prototype instanceof BaseGadget;\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 if (value instanceof BaseGadget) {\n results.push(value);\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 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\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 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\n */\n endCall(usage?: { inputTokens: number; outputTokens: number; totalTokens: number }): 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 );\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 * 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 * 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 | ↑ in │ ↓ out │ time | cost\n const parts: string[] = [];\n\n // #N (iteration number)\n parts.push(chalk.cyan(`#${this.currentIteration}`));\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 // Cost\n if (this.totalCost > 0) {\n parts.push(chalk.cyan(`$${formatCost(this.totalCost)}`));\n }\n\n this.target.write(`\\r${chalk.cyan(spinner)} ${parts.join(chalk.dim(\" | \"))}`);\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${chalk.cyan(spinner)} ${parts.join(chalk.dim(\" | \"))}`);\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 this.target.write(\"\\r\\x1b[K\");\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 type { TokenUsage } from \"../../core/options.js\";\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 /** 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\n * renderSummary({\n * iterations: 3,\n * usage: { inputTokens: 896, outputTokens: 11500, totalTokens: 12396 },\n * elapsedSeconds: 9,\n * cost: 0.0123,\n * finishReason: \"stop\"\n * });\n * // Output: \"#3 | ↑ 896 │ ↓ 11.5k │ 9s | $0.0123 | stop\"\n *\n * // Partial summary (only tokens)\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 (#N) - shown first for context\n if (metadata.iterations !== undefined) {\n parts.push(chalk.cyan(`#${metadata.iterations}`));\n }\n\n // Token usage (↑ input │ ↓ output) - core metrics\n if (metadata.usage) {\n const { inputTokens, outputTokens } = metadata.usage;\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${formatTokens(inputTokens)}`));\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 * 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\n/**\n * Formats a gadget execution result for stderr output with color-coded status.\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 → result 123ms`\n * - Error: `✗ GadgetName error: message 123ms`\n * - Completion: `⏹ GadgetName finished: result 123ms`\n *\n * **Special handling:**\n * - TellUser gadget shows full result (user-facing messages)\n * - Other gadgets truncate long results to 80 chars (keep output clean)\n *\n * @param result - Gadget execution result with timing and output info\n * @returns Formatted summary string with ANSI colors\n *\n * @example\n * ```typescript\n * // Successful gadget execution\n * formatGadgetSummary({\n * gadgetName: \"Calculator\",\n * executionTimeMs: 45,\n * result: \"345\"\n * });\n * // Output: \"✓ Calculator → 345 45ms\" (with colors)\n *\n * // Error case\n * formatGadgetSummary({\n * gadgetName: \"Database\",\n * executionTimeMs: 123,\n * error: \"Connection timeout\"\n * });\n * // Output: \"✗ Database error: Connection timeout 123ms\" (with red colors)\n *\n * // Loop-breaking gadget (TellUser with done=true)\n * formatGadgetSummary({\n * gadgetName: \"TellUser\",\n * executionTimeMs: 12,\n * result: \"Task completed successfully!\",\n * breaksLoop: true\n * });\n * // Output: \"⏹ TellUser finished: Task completed successfully! 12ms\" (with yellow)\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 // Error case - show error message in red\n if (result.error) {\n return `${chalk.red(\"✗\")} ${gadgetLabel} ${chalk.red(\"error:\")} ${result.error} ${timeLabel}`;\n }\n\n // Loop-breaking case - indicate completion in yellow\n if (result.breaksLoop) {\n return `${chalk.yellow(\"⏹\")} ${gadgetLabel} ${chalk.yellow(\"finished:\")} ${result.result} ${timeLabel}`;\n }\n\n // Success case - format result with optional truncation\n const maxLen = 80;\n const shouldTruncate = result.gadgetName !== \"TellUser\";\n const resultText = result.result\n ? shouldTruncate && result.result.length > maxLen\n ? `${result.result.slice(0, maxLen)}...`\n : result.result\n : \"\";\n\n return `${chalk.green(\"✓\")} ${gadgetLabel} ${chalk.dim(\"→\")} ${resultText} ${timeLabel}`;\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 { COMMANDS, DEFAULT_MODEL, OPTION_DESCRIPTIONS, OPTION_FLAGS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport {\n createNumericParser,\n executeAction,\n renderSummary,\n resolvePrompt,\n StreamPrinter,\n StreamProgress,\n} from \"./utils.js\";\n\n/**\n * Configuration options for the complete command.\n */\ninterface CompleteCommandOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxTokens?: number;\n}\n\n/**\n * Handles the complete command execution.\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 */\nasync function handleCompleteCommand(\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 stream = client.stream({\n model,\n messages: builder.build(),\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 totalChars = 0;\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 totalChars += chunk.text.length;\n progress.update(totalChars); // 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 // Only show summary if stderr is a TTY (not redirected)\n if (stderrTTY) {\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 */\nexport function registerCompleteCommand(program: Command, env: CLIEnvironment): void {\n 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 .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, DEFAULT_MODEL)\n .option(OPTION_FLAGS.systemPrompt, OPTION_DESCRIPTIONS.systemPrompt)\n .option(\n OPTION_FLAGS.temperature,\n OPTION_DESCRIPTIONS.temperature,\n createNumericParser({ label: \"Temperature\", min: 0, max: 2 }),\n )\n .option(\n OPTION_FLAGS.maxTokens,\n OPTION_DESCRIPTIONS.maxTokens,\n createNumericParser({ label: \"Max tokens\", integer: true, min: 1 }),\n )\n .action((prompt, options) =>\n executeAction(\n () => handleCompleteCommand(prompt, options as CompleteCommandOptions, env),\n env,\n ),\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}\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-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","#!/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","InvalidArgumentError","chalk","chalk","InvalidArgumentError","gadgets","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/utils.ts","../src/cli/ui/formatters.ts","../src/cli/complete-command.ts","../src/cli/models-command.ts","../src/cli/environment.ts","../src/cli.ts"],"sourcesContent":["import type { ParameterFormat } from \"../gadgets/parser.js\";\n\n/** 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} 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/** Default parameter format for gadgets */\nexport const DEFAULT_PARAMETER_FORMAT: ParameterFormat = \"json\";\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 parameterFormat: \"--parameter-format <format>\",\n logLevel: \"--log-level <level>\",\n logFile: \"--log-file <path>\",\n noBuiltins: \"--no-builtins\",\n noBuiltinInteraction: \"--no-builtin-interaction\",\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 parameterFormat: \"Format for gadget parameter schemas: 'json', 'yaml', or 'auto'.\",\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 noBuiltins: \"Disable built-in gadgets (AskUser, TellUser).\",\n noBuiltinInteraction: \"Disable interactive gadgets (AskUser) while keeping TellUser.\",\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 { registerModelsCommand } from \"./models-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}\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 * @returns Configured Commander program ready for parsing\n */\nexport function createProgram(env: CLIEnvironment): 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 .configureOutput({\n writeOut: (str) => env.stdout.write(str),\n writeErr: (str) => env.stderr.write(str),\n });\n\n registerCompleteCommand(program, env);\n registerAgentCommand(program, env);\n registerModelsCommand(program, env);\n\n return program;\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 for testing or customization\n */\nexport async function runCLI(overrides: Partial<CLIEnvironment> = {}): Promise<void> {\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 .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 const loggerConfig: CLILoggerConfig = {\n logLevel: globalOpts.logLevel,\n logFile: globalOpts.logFile,\n };\n\n const defaultEnv = createDefaultEnvironment(loggerConfig);\n const env: CLIEnvironment = { ...defaultEnv, ...overrides };\n const program = createProgram(env);\n await program.parseAsync(env.argv);\n}\n","{\n \"name\": \"llmist\",\n \"version\": \"0.4.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 \"js-yaml\": \"^4.1.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/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, InvalidArgumentError } from \"commander\";\nimport { AgentBuilder } from \"../agent/builder.js\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { TokenUsage } from \"../core/options.js\";\nimport type { ParameterFormat } from \"../gadgets/parser.js\";\nimport { GadgetRegistry } from \"../gadgets/registry.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"../providers/constants.js\";\nimport { builtinGadgets } from \"./builtin-gadgets.js\";\nimport {\n COMMANDS,\n DEFAULT_MODEL,\n DEFAULT_PARAMETER_FORMAT,\n OPTION_DESCRIPTIONS,\n OPTION_FLAGS,\n} from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { loadGadgets } from \"./gadgets.js\";\nimport {\n createNumericParser,\n executeAction,\n isInteractive,\n renderSummary,\n resolvePrompt,\n StreamPrinter,\n StreamProgress,\n} from \"./utils.js\";\nimport { formatGadgetSummary, type GadgetResult } from \"./ui/formatters.js\";\n\n/**\n * Configuration options for the agent command.\n */\ninterface AgentCommandOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxIterations?: number;\n gadget?: string[];\n parameterFormat: ParameterFormat;\n builtins: boolean; // --no-builtins sets this to false\n builtinInteraction: boolean; // --no-builtin-interaction sets this to false\n}\n\nconst PARAMETER_FORMAT_VALUES: ParameterFormat[] = [\"json\", \"yaml\", \"auto\"];\n\n/**\n * Parses and validates the parameter format option value.\n *\n * @param value - User-provided parameter format string\n * @returns Validated parameter format\n * @throws InvalidArgumentError if format is not one of: json, yaml, auto\n */\nfunction parseParameterFormat(value: string): ParameterFormat {\n const normalized = value.toLowerCase() as ParameterFormat;\n if (!PARAMETER_FORMAT_VALUES.includes(normalized)) {\n throw new InvalidArgumentError(\"Parameter format must be one of 'json', 'yaml', or 'auto'.\");\n }\n return normalized;\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\n const questionLine = question.trim() ? `\\n${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 * Handles the agent command execution.\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 */\nasync function handleAgentCommand(\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 if (options.builtins !== false) {\n for (const gadget of builtinGadgets) {\n // Skip AskUser if --no-builtin-interaction is set\n // Useful for non-interactive environments (CI, pipes, etc.)\n if (options.builtinInteraction === false && gadget.name === \"AskUser\") {\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 finishReason: string | null | undefined;\n let usage: TokenUsage | undefined;\n let iterations = 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 // 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 // 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 // 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 }\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 finishReason = context.finishReason;\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 // End this call's progress tracking and switch to cumulative mode\n progress.endCall(context.usage);\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 // Note: parameterFormat is not directly supported in AgentBuilder\n // This might need to be added to AgentBuilder API if needed\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 for await (const event of agent.run()) {\n if (event.type === \"text\") {\n // Stream LLM output to stdout\n // Pause progress indicator to avoid stderr/stdout interleaving\n progress.pause();\n printer.write(event.content);\n } else if (event.type === \"gadget_result\") {\n // Show gadget execution feedback on stderr\n // Only displayed in TTY mode (hidden when piped)\n progress.pause();\n if (stderrTTY) {\n env.stderr.write(`${formatGadgetSummary(event.result)}\\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 progress.complete();\n printer.ensureNewline();\n\n // Only show summary if stderr is a TTY (not redirected)\n if (stderrTTY) {\n const summary = renderSummary({\n finishReason,\n usage,\n iterations,\n cost: progress.getTotalCost(),\n elapsedSeconds: progress.getTotalElapsedSeconds(),\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 */\nexport function registerAgentCommand(program: Command, env: CLIEnvironment): void {\n 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 .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, DEFAULT_MODEL)\n .option(OPTION_FLAGS.systemPrompt, OPTION_DESCRIPTIONS.systemPrompt)\n .option(\n OPTION_FLAGS.temperature,\n OPTION_DESCRIPTIONS.temperature,\n createNumericParser({ label: \"Temperature\", min: 0, max: 2 }),\n )\n .option(\n OPTION_FLAGS.maxIterations,\n OPTION_DESCRIPTIONS.maxIterations,\n createNumericParser({ label: \"Max iterations\", integer: true, min: 1 }),\n )\n .option(\n OPTION_FLAGS.gadgetModule,\n OPTION_DESCRIPTIONS.gadgetModule,\n (value: string, previous: string[] = []) => [...previous, value],\n [] as string[],\n )\n .option(\n OPTION_FLAGS.parameterFormat,\n OPTION_DESCRIPTIONS.parameterFormat,\n parseParameterFormat,\n DEFAULT_PARAMETER_FORMAT,\n )\n .option(OPTION_FLAGS.noBuiltins, OPTION_DESCRIPTIONS.noBuiltins)\n .option(OPTION_FLAGS.noBuiltinInteraction, OPTION_DESCRIPTIONS.noBuiltinInteraction)\n .action((prompt, options) =>\n executeAction(() => handleAgentCommand(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 chalk from \"chalk\";\nimport { z } from \"zod\";\n\nimport { createGadget } from \"../gadgets/create-gadget.js\";\nimport { BreakLoopException, HumanInputException } from \"../gadgets/exceptions.js\";\n\n/**\n * AskUser gadget - Asks the user a question and waits for their response.\n *\n * Use this when you need more information or clarification from the user.\n */\nexport const askUser = createGadget({\n name: \"AskUser\",\n description:\n \"Ask the user a question when you need more information or clarification. The user's response will be provided back to you.\",\n schema: z.object({\n question: z.string().describe(\"The question to ask the user\"),\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.string().describe(\"The message to display to the user\"),\n done: z.boolean().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 execute: ({ message, done, type }) => {\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 * 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 return Boolean(prototype) && prototype instanceof BaseGadget;\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 if (value instanceof BaseGadget) {\n results.push(value);\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 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\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 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\n */\n endCall(usage?: { inputTokens: number; outputTokens: number; totalTokens: number }): 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 );\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 * 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 * 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 | ↑ in │ ↓ out │ time | cost\n const parts: string[] = [];\n\n // #N (iteration number)\n parts.push(chalk.cyan(`#${this.currentIteration}`));\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 // Cost\n if (this.totalCost > 0) {\n parts.push(chalk.cyan(`$${formatCost(this.totalCost)}`));\n }\n\n this.target.write(`\\r${chalk.cyan(spinner)} ${parts.join(chalk.dim(\" | \"))}`);\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${chalk.cyan(spinner)} ${parts.join(chalk.dim(\" | \"))}`);\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 this.target.write(\"\\r\\x1b[K\");\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 type { TokenUsage } from \"../../core/options.js\";\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 /** 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\n * renderSummary({\n * iterations: 3,\n * usage: { inputTokens: 896, outputTokens: 11500, totalTokens: 12396 },\n * elapsedSeconds: 9,\n * cost: 0.0123,\n * finishReason: \"stop\"\n * });\n * // Output: \"#3 | ↑ 896 │ ↓ 11.5k │ 9s | $0.0123 | stop\"\n *\n * // Partial summary (only tokens)\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 (#N) - shown first for context\n if (metadata.iterations !== undefined) {\n parts.push(chalk.cyan(`#${metadata.iterations}`));\n }\n\n // Token usage (↑ input │ ↓ output) - core metrics\n if (metadata.usage) {\n const { inputTokens, outputTokens } = metadata.usage;\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${formatTokens(inputTokens)}`));\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 * 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\n/**\n * Formats a gadget execution result for stderr output with color-coded status.\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 → result 123ms`\n * - Error: `✗ GadgetName error: message 123ms`\n * - Completion: `⏹ GadgetName finished: result 123ms`\n *\n * **Special handling:**\n * - TellUser gadget shows full result (user-facing messages)\n * - Other gadgets truncate long results to 80 chars (keep output clean)\n *\n * @param result - Gadget execution result with timing and output info\n * @returns Formatted summary string with ANSI colors\n *\n * @example\n * ```typescript\n * // Successful gadget execution\n * formatGadgetSummary({\n * gadgetName: \"Calculator\",\n * executionTimeMs: 45,\n * result: \"345\"\n * });\n * // Output: \"✓ Calculator → 345 45ms\" (with colors)\n *\n * // Error case\n * formatGadgetSummary({\n * gadgetName: \"Database\",\n * executionTimeMs: 123,\n * error: \"Connection timeout\"\n * });\n * // Output: \"✗ Database error: Connection timeout 123ms\" (with red colors)\n *\n * // Loop-breaking gadget (TellUser with done=true)\n * formatGadgetSummary({\n * gadgetName: \"TellUser\",\n * executionTimeMs: 12,\n * result: \"Task completed successfully!\",\n * breaksLoop: true\n * });\n * // Output: \"⏹ TellUser finished: Task completed successfully! 12ms\" (with yellow)\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 // Error case - show error message in red\n if (result.error) {\n return `${chalk.red(\"✗\")} ${gadgetLabel} ${chalk.red(\"error:\")} ${result.error} ${timeLabel}`;\n }\n\n // Loop-breaking case - indicate completion in yellow\n if (result.breaksLoop) {\n return `${chalk.yellow(\"⏹\")} ${gadgetLabel} ${chalk.yellow(\"finished:\")} ${result.result} ${timeLabel}`;\n }\n\n // Success case - format result with optional truncation\n const maxLen = 80;\n const shouldTruncate = result.gadgetName !== \"TellUser\";\n const resultText = result.result\n ? shouldTruncate && result.result.length > maxLen\n ? `${result.result.slice(0, maxLen)}...`\n : result.result\n : \"\";\n\n return `${chalk.green(\"✓\")} ${gadgetLabel} ${chalk.dim(\"→\")} ${resultText} ${timeLabel}`;\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 { COMMANDS, DEFAULT_MODEL, OPTION_DESCRIPTIONS, OPTION_FLAGS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport {\n createNumericParser,\n executeAction,\n renderSummary,\n resolvePrompt,\n StreamPrinter,\n StreamProgress,\n} from \"./utils.js\";\n\n/**\n * Configuration options for the complete command.\n */\ninterface CompleteCommandOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxTokens?: number;\n}\n\n/**\n * Handles the complete command execution.\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 */\nasync function handleCompleteCommand(\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 stream = client.stream({\n model,\n messages: builder.build(),\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 totalChars = 0;\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 totalChars += chunk.text.length;\n progress.update(totalChars); // 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 // Only show summary if stderr is a TTY (not redirected)\n if (stderrTTY) {\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 */\nexport function registerCompleteCommand(program: Command, env: CLIEnvironment): void {\n 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 .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, DEFAULT_MODEL)\n .option(OPTION_FLAGS.systemPrompt, OPTION_DESCRIPTIONS.systemPrompt)\n .option(\n OPTION_FLAGS.temperature,\n OPTION_DESCRIPTIONS.temperature,\n createNumericParser({ label: \"Temperature\", min: 0, max: 2 }),\n )\n .option(\n OPTION_FLAGS.maxTokens,\n OPTION_DESCRIPTIONS.maxTokens,\n createNumericParser({ label: \"Max tokens\", integer: true, min: 1 }),\n )\n .action((prompt, options) =>\n executeAction(\n () => handleCompleteCommand(prompt, options as CompleteCommandOptions, env),\n env,\n ),\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}\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-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","#!/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","InvalidArgumentError","chalk","chalk","InvalidArgumentError","gadgets","chalk","chalk","formatTokens","chalk","InvalidArgumentError"]}
|