llmist 1.2.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -75
- package/dist/{chunk-KORMY3CD.js → chunk-RZTAKIDE.js} +605 -4
- package/dist/chunk-RZTAKIDE.js.map +1 -0
- package/dist/{chunk-LELPPETT.js → chunk-TFIKR2RK.js} +459 -3
- package/dist/chunk-TFIKR2RK.js.map +1 -0
- package/dist/cli.cjs +628 -23
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +49 -22
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +769 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +354 -32
- package/dist/index.d.ts +354 -32
- package/dist/index.js +177 -2
- package/dist/index.js.map +1 -1
- package/dist/{mock-stream-DKF5yatf.d.cts → mock-stream-DNt-HBTn.d.cts} +525 -79
- package/dist/{mock-stream-DKF5yatf.d.ts → mock-stream-DNt-HBTn.d.ts} +525 -79
- package/dist/testing/index.cjs +1063 -4
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +437 -3
- package/dist/testing/index.d.ts +437 -3
- package/dist/testing/index.js +54 -4
- package/package.json +1 -1
- package/dist/chunk-KORMY3CD.js.map +0 -1
- package/dist/chunk-LELPPETT.js.map +0 -1
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/constants.ts","../src/core/model-shortcuts.ts","../src/gadgets/schema-validator.ts","../src/gadgets/registry.ts","../src/core/prompt-config.ts","../src/core/messages.ts","../src/logging/logger.ts","../src/gadgets/schema-to-json.ts","../src/gadgets/gadget.ts","../src/gadgets/create-gadget.ts","../src/gadgets/output-viewer.ts","../src/agent/gadget-output-store.ts","../src/agent/agent-internal-key.ts","../src/agent/conversation-manager.ts","../src/agent/event-handlers.ts","../src/agent/hook-validators.ts","../src/gadgets/schema-introspector.ts","../src/gadgets/block-params.ts","../src/gadgets/error-formatter.ts","../src/gadgets/exceptions.ts","../src/gadgets/parser.ts","../src/gadgets/executor.ts","../src/agent/stream-processor.ts","../src/agent/agent.ts","../src/providers/anthropic-models.ts","../src/providers/base-provider.ts","../src/providers/constants.ts","../src/providers/utils.ts","../src/providers/anthropic.ts","../src/providers/gemini-models.ts","../src/providers/gemini.ts","../src/providers/openai-models.ts","../src/providers/openai.ts","../src/providers/discovery.ts","../src/core/model-registry.ts","../src/core/options.ts","../src/core/quick-methods.ts","../src/core/client.ts","../src/agent/builder.ts","../src/cli/constants.ts","../src/cli/program.ts","../package.json","../src/cli/agent-command.ts","../src/cli/builtin-gadgets.ts","../src/cli/gadgets.ts","../src/cli/llm-logging.ts","../src/cli/utils.ts","../src/cli/ui/formatters.ts","../src/cli/option-helpers.ts","../src/cli/complete-command.ts","../src/cli/config.ts","../src/cli/templates.ts","../src/cli/gadget-command.ts","../src/cli/gadget-prompts.ts","../src/cli/models-command.ts","../src/cli/environment.ts","../src/cli/custom-command.ts","../src/cli.ts"],"sourcesContent":["// Gadget marker constants\nexport const GADGET_START_PREFIX = \"!!!GADGET_START:\";\nexport const GADGET_END_PREFIX = \"!!!GADGET_END\";\nexport const GADGET_ARG_PREFIX = \"!!!ARG:\";\n\n// Default configuration values\nexport const DEFAULT_MAX_TOKENS = 1024;\nexport const DEFAULT_MAX_ITERATIONS = 10;\n\n// Gadget output limiting defaults\n/** Default: gadget output limiting is enabled */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT = true;\n\n/** Default: limit gadget output to 15% of context window */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;\n\n/** Approximate characters per token for limit calculation */\nexport const CHARS_PER_TOKEN = 4;\n\n/** Fallback context window size if model is not in registry */\nexport const FALLBACK_CONTEXT_WINDOW = 128_000;\n","/**\n * Model shortcuts and aliases for more expressive DX.\n *\n * This module provides convenient aliases for common model names,\n * allowing developers to use short, memorable names instead of\n * verbose provider:model-id formats.\n *\n * @example\n * ```typescript\n * // Instead of:\n * model: \"openai:gpt-5-nano\"\n *\n * // You can use:\n * model: \"gpt5-nano\"\n * // or even:\n * model: \"gpt-5-nano\" // Auto-detects provider\n * ```\n */\n\n/**\n * Map of common model aliases to their full provider:model-id format.\n */\nexport const MODEL_ALIASES: Record<string, string> = {\n // OpenAI aliases\n gpt4: \"openai:gpt-4o\",\n gpt4o: \"openai:gpt-4o\",\n gpt5: \"openai:gpt-5\",\n \"gpt5-mini\": \"openai:gpt-5-mini\",\n \"gpt5-nano\": \"openai:gpt-5-nano\",\n\n // Anthropic aliases\n sonnet: \"anthropic:claude-sonnet-4-5\",\n \"claude-sonnet\": \"anthropic:claude-sonnet-4-5\",\n haiku: \"anthropic:claude-haiku-4-5\",\n \"claude-haiku\": \"anthropic:claude-haiku-4-5\",\n opus: \"anthropic:claude-opus-4-5\",\n \"claude-opus\": \"anthropic:claude-opus-4-5\",\n\n // Gemini aliases\n flash: \"gemini:gemini-2.0-flash\",\n \"gemini-flash\": \"gemini:gemini-2.0-flash\",\n \"gemini-pro\": \"gemini:gemini-2.5-pro\",\n pro: \"gemini:gemini-2.5-pro\",\n};\n\n/**\n * Options for resolveModel function.\n */\nexport interface ResolveModelOptions {\n /**\n * If true, throw an error for unknown model names instead of falling back to OpenAI.\n * This helps catch typos like \"gp4\" instead of \"gpt4\".\n * Default: false\n */\n strict?: boolean;\n\n /**\n * If true, suppress warnings for unknown model names.\n * Default: false\n */\n silent?: boolean;\n}\n\n/**\n * Known model name patterns for validation.\n * These patterns help detect typos and unknown models.\n */\nconst KNOWN_MODEL_PATTERNS = [\n /^gpt-?\\d/i, // gpt-4, gpt-3.5, gpt4, etc.\n /^claude-?\\d/i, // claude-3, claude-2, etc.\n /^gemini-?(\\d|pro|flash)/i, // gemini-2.0, gemini-pro, gemini-flash, etc.\n /^o\\d/i, // OpenAI o1, o3, etc.\n];\n\n/**\n * Check if a model name matches known patterns.\n *\n * @param model - Model name to check\n * @returns True if the model matches a known pattern\n */\nfunction isKnownModelPattern(model: string): boolean {\n const normalized = model.toLowerCase();\n\n // Check if it's a known alias\n if (MODEL_ALIASES[normalized]) {\n return true;\n }\n\n // Check against known patterns\n return KNOWN_MODEL_PATTERNS.some((pattern) => pattern.test(model));\n}\n\n/**\n * Resolves a model name to its full provider:model format.\n *\n * Supports:\n * - Direct aliases: 'gpt5', 'sonnet', 'flash'\n * - Auto-detection: 'gpt-5-nano' → 'openai:gpt-5-nano'\n * - Pass-through: 'openai:gpt-5' → 'openai:gpt-5'\n *\n * Warnings:\n * - Logs a warning when an unknown model name falls back to OpenAI\n * - Use { strict: true } to throw an error instead\n * - Use { silent: true } to suppress warnings\n *\n * @param model - Model name or alias\n * @param options - Resolution options\n * @returns Full provider:model-id string\n *\n * @example\n * ```typescript\n * resolveModel('gpt5') // → 'openai:gpt-5'\n * resolveModel('sonnet') // → 'anthropic:claude-sonnet-4-5'\n * resolveModel('gpt-5-nano') // → 'openai:gpt-5-nano'\n * resolveModel('openai:gpt-5') // → 'openai:gpt-5' (passthrough)\n * resolveModel('claude-3-5-sonnet') // → 'anthropic:claude-3-5-sonnet'\n *\n * // Typo detection\n * resolveModel('gp5') // ⚠️ Warning: Unknown model 'gp5', falling back to 'openai:gp5'\n *\n * // Strict mode (throws on typos)\n * resolveModel('gp5', { strict: true }) // ❌ Error: Unknown model 'gp5'\n * ```\n */\nexport function resolveModel(model: string, options: ResolveModelOptions = {}): string {\n // Already has provider prefix - pass through\n if (model.includes(\":\")) {\n return model;\n }\n\n // Check if it's a known alias\n const normalized = model.toLowerCase();\n if (MODEL_ALIASES[normalized]) {\n return MODEL_ALIASES[normalized];\n }\n\n // Smart detection by model name patterns\n const modelLower = model.toLowerCase();\n\n // OpenAI models start with 'gpt'\n if (modelLower.startsWith(\"gpt\")) {\n return `openai:${model}`;\n }\n\n // Anthropic models start with 'claude'\n if (modelLower.startsWith(\"claude\")) {\n return `anthropic:${model}`;\n }\n\n // Gemini models start with 'gemini'\n if (modelLower.startsWith(\"gemini\")) {\n return `gemini:${model}`;\n }\n\n // OpenAI o-series models (o1, o3, etc.)\n if (modelLower.match(/^o\\d/)) {\n return `openai:${model}`;\n }\n\n // Unknown model: validate and warn/error\n if (!isKnownModelPattern(model)) {\n if (options.strict) {\n throw new Error(\n `Unknown model '${model}'. Did you mean one of: gpt4, sonnet, haiku, flash? ` +\n `Use explicit provider prefix like 'openai:${model}' to bypass this check.`,\n );\n }\n\n if (!options.silent) {\n console.warn(\n `⚠️ Unknown model '${model}', falling back to 'openai:${model}'. ` +\n `This might be a typo. Did you mean: gpt4, gpt5, gpt5-nano, sonnet, haiku, flash? ` +\n `Use { strict: true } to error on unknown models, or { silent: true } to suppress this warning.`,\n );\n }\n }\n\n // Default: assume OpenAI for unknown models\n // This provides a reasonable fallback for most cases\n return `openai:${model}`;\n}\n\n/**\n * Check if a model string is already in provider:model format.\n *\n * @param model - Model string to check\n * @returns True if the model has a provider prefix\n *\n * @example\n * ```typescript\n * hasProviderPrefix('openai:gpt-4o') // → true\n * hasProviderPrefix('gpt4') // → false\n * hasProviderPrefix('claude-3-5-sonnet') // → false\n * ```\n */\nexport function hasProviderPrefix(model: string): boolean {\n return model.includes(\":\");\n}\n\n/**\n * Extract the provider from a full model string.\n *\n * @param model - Full model string (provider:model-id)\n * @returns Provider name, or undefined if no prefix\n *\n * @example\n * ```typescript\n * getProvider('openai:gpt-4o') // → 'openai'\n * getProvider('anthropic:claude') // → 'anthropic'\n * getProvider('gpt4') // → undefined\n * ```\n */\nexport function getProvider(model: string): string | undefined {\n const separatorIndex = model.indexOf(\":\");\n if (separatorIndex === -1) {\n return undefined;\n }\n return model.slice(0, separatorIndex);\n}\n\n/**\n * Extract the model ID from a full model string.\n *\n * @param model - Full model string (provider:model-id)\n * @returns Model ID, or the original string if no prefix\n *\n * @example\n * ```typescript\n * getModelId('openai:gpt-4o') // → 'gpt-4o'\n * getModelId('anthropic:claude') // → 'claude'\n * getModelId('gpt4') // → 'gpt4'\n * ```\n */\nexport function getModelId(model: string): string {\n const separatorIndex = model.indexOf(\":\");\n if (separatorIndex === -1) {\n return model;\n }\n return model.slice(separatorIndex + 1);\n}\n","import type { ZodTypeAny } from \"zod\";\nimport * as z from \"zod\";\n\n/**\n * Validates that a Zod schema doesn't contain z.unknown() which produces\n * incomplete JSON schemas without type information.\n *\n * @param schema - The Zod schema to validate\n * @param gadgetName - Name of the gadget (for error messages)\n * @throws Error if z.unknown() is detected with helpful suggestions\n */\nexport function validateGadgetSchema(schema: ZodTypeAny, gadgetName: string): void {\n let jsonSchema;\n try {\n jsonSchema = z.toJSONSchema(schema, { target: \"draft-7\" });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Gadget \"${gadgetName}\" has a schema that cannot be serialized to JSON Schema.\\n` +\n `This usually happens with unsupported patterns like:\\n` +\n `- z.record() - use z.object({}).passthrough() instead\\n` +\n `- Complex transforms or custom refinements\\n` +\n `- Circular references\\n` +\n `\\n` +\n `Original error: ${errorMessage}\\n` +\n `\\n` +\n `Only use schema patterns that Zod v4's native toJSONSchema() supports.`,\n );\n }\n const issues = findUnknownTypes(jsonSchema);\n\n if (issues.length > 0) {\n const fieldList = issues.join(\", \");\n throw new Error(\n `Gadget \"${gadgetName}\" uses z.unknown() which produces incomplete schemas.\\n` +\n `Problematic fields: ${fieldList}\\n` +\n `\\n` +\n `z.unknown() doesn't generate type information in JSON Schema, making it unclear\\n` +\n `to the LLM what data structure to provide.\\n` +\n `\\n` +\n `Suggestions:\\n` +\n `- Use z.object({}).passthrough() for flexible objects\\n` +\n `- Use z.record(z.string()) for key-value objects with string values\\n` +\n `- Define specific structure if possible\\n` +\n `\\n` +\n `Example fixes:\\n` +\n ` // ❌ Bad\\n` +\n ` content: z.unknown()\\n` +\n `\\n` +\n ` // ✅ Good\\n` +\n ` content: z.object({}).passthrough() // for flexible objects\\n` +\n ` content: z.record(z.string()) // for key-value objects\\n` +\n ` content: z.array(z.string()) // for arrays of strings\\n`,\n );\n }\n}\n\n/**\n * Recursively searches a JSON Schema for properties without type information,\n * which indicates z.unknown() usage.\n *\n * @param schema - JSON Schema object to search\n * @param path - Current path in schema (for error reporting)\n * @returns Array of problematic field paths\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction findUnknownTypes(schema: any, path: string[] = []): string[] {\n const issues: string[] = [];\n\n if (!schema || typeof schema !== \"object\") {\n return issues;\n }\n\n // Check if we're in a definitions block\n if (schema.definitions) {\n for (const defSchema of Object.values(schema.definitions)) {\n issues.push(...findUnknownTypes(defSchema, []));\n }\n }\n\n // Check properties of objects\n if (schema.properties) {\n for (const [propName, propSchema] of Object.entries(schema.properties)) {\n const propPath = [...path, propName];\n\n // Check if this property has no type information\n if (hasNoType(propSchema)) {\n issues.push(propPath.join(\".\") || propName);\n }\n\n // Recursively check nested properties\n issues.push(...findUnknownTypes(propSchema, propPath));\n }\n }\n\n // Check array items\n if (schema.items) {\n const itemPath = [...path, \"[]\"];\n if (hasNoType(schema.items)) {\n issues.push(itemPath.join(\".\"));\n }\n issues.push(...findUnknownTypes(schema.items, itemPath));\n }\n\n // Check anyOf/oneOf/allOf unions\n if (schema.anyOf) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema.anyOf.forEach((subSchema: any, index: number) => {\n issues.push(...findUnknownTypes(subSchema, [...path, `anyOf[${index}]`]));\n });\n }\n\n if (schema.oneOf) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema.oneOf.forEach((subSchema: any, index: number) => {\n issues.push(...findUnknownTypes(subSchema, [...path, `oneOf[${index}]`]));\n });\n }\n\n if (schema.allOf) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema.allOf.forEach((subSchema: any, index: number) => {\n issues.push(...findUnknownTypes(subSchema, [...path, `allOf[${index}]`]));\n });\n }\n\n return issues;\n}\n\n/**\n * Checks if a schema property has no type information.\n * This indicates z.unknown() usage.\n *\n * A property has \"no type\" if it:\n * - Is an object\n * - Has no \"type\" field\n * - Has no \"$ref\" (reference to definition)\n * - Has no \"anyOf\", \"oneOf\", or \"allOf\" (union types)\n * - Has only \"description\" or is empty\n *\n * @param prop - Property schema to check\n * @returns true if property has no type information\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction hasNoType(prop: any): boolean {\n if (!prop || typeof prop !== \"object\") {\n return false;\n }\n\n const hasType = prop.type !== undefined;\n const hasRef = prop.$ref !== undefined;\n const hasUnion = prop.anyOf !== undefined || prop.oneOf !== undefined || prop.allOf !== undefined;\n\n // If it has any type information, it's fine\n if (hasType || hasRef || hasUnion) {\n return false;\n }\n\n // Check if it only has description and/or other non-type metadata\n const keys = Object.keys(prop);\n const metadataKeys = [\"description\", \"title\", \"default\", \"examples\"];\n const hasOnlyMetadata = keys.every((key) => metadataKeys.includes(key));\n\n // If it only has metadata or is empty (besides metadata), it's missing type info\n return hasOnlyMetadata || keys.length === 0;\n}\n","import type { BaseGadget } from \"./gadget.js\";\nimport { validateGadgetSchema } from \"./schema-validator.js\";\n\n// Type for gadget constructor\nexport type GadgetClass = new (...args: unknown[]) => BaseGadget;\n\n// Type for gadget or gadget class\nexport type GadgetOrClass = BaseGadget | GadgetClass;\n\nexport class GadgetRegistry {\n private readonly gadgets = new Map<string, BaseGadget>();\n\n /**\n * Creates a registry from an array of gadget classes or instances,\n * or an object mapping names to gadgets.\n *\n * @param gadgets - Array of gadgets/classes or object with custom names\n * @returns New GadgetRegistry with all gadgets registered\n *\n * @example\n * ```typescript\n * // From array of classes\n * const registry = GadgetRegistry.from([Calculator, Weather]);\n *\n * // From array of instances\n * const registry = GadgetRegistry.from([new Calculator(), new Weather()]);\n *\n * // From object with custom names\n * const registry = GadgetRegistry.from({\n * calc: Calculator,\n * weather: new Weather({ apiKey: \"...\" })\n * });\n * ```\n */\n static from(gadgets: GadgetOrClass[] | Record<string, GadgetOrClass>): GadgetRegistry {\n const registry = new GadgetRegistry();\n\n if (Array.isArray(gadgets)) {\n // Array of gadgets or classes\n registry.registerMany(gadgets);\n } else {\n // Object with custom names\n for (const [name, gadget] of Object.entries(gadgets)) {\n const instance = typeof gadget === \"function\" ? new gadget() : gadget;\n registry.register(name, instance);\n }\n }\n\n return registry;\n }\n\n /**\n * Registers multiple gadgets at once from an array.\n *\n * @param gadgets - Array of gadget instances or classes\n * @returns This registry for chaining\n *\n * @example\n * ```typescript\n * registry.registerMany([Calculator, Weather, Email]);\n * registry.registerMany([new Calculator(), new Weather()]);\n * ```\n */\n registerMany(gadgets: GadgetOrClass[]): this {\n for (const gadget of gadgets) {\n const instance = typeof gadget === \"function\" ? new gadget() : gadget;\n this.registerByClass(instance);\n }\n return this;\n }\n\n // Register a gadget by name\n register(name: string, gadget: BaseGadget): void {\n const normalizedName = name.toLowerCase();\n if (this.gadgets.has(normalizedName)) {\n throw new Error(`Gadget '${name}' is already registered`);\n }\n\n // Validate schema if present\n if (gadget.parameterSchema) {\n validateGadgetSchema(gadget.parameterSchema, name);\n }\n\n this.gadgets.set(normalizedName, gadget);\n }\n\n // Register a gadget using its name property or class name\n registerByClass(gadget: BaseGadget): void {\n const name = gadget.name ?? gadget.constructor.name;\n this.register(name, gadget);\n }\n\n // Get gadget by name (case-insensitive)\n get(name: string): BaseGadget | undefined {\n return this.gadgets.get(name.toLowerCase());\n }\n\n // Check if gadget exists (case-insensitive)\n has(name: string): boolean {\n return this.gadgets.has(name.toLowerCase());\n }\n\n // Get all registered gadget names\n getNames(): string[] {\n return Array.from(this.gadgets.keys());\n }\n\n // Get all gadgets for instruction generation\n getAll(): BaseGadget[] {\n return Array.from(this.gadgets.values());\n }\n\n // Unregister gadget (useful for testing, case-insensitive)\n unregister(name: string): boolean {\n return this.gadgets.delete(name.toLowerCase());\n }\n\n // Clear all gadgets (useful for testing)\n clear(): void {\n this.gadgets.clear();\n }\n}\n","/**\n * Context provided to prompt template functions for rendering dynamic content.\n */\nexport interface PromptContext {\n /** Custom gadget start prefix */\n startPrefix: string;\n /** Custom gadget end prefix */\n endPrefix: string;\n /** Custom argument prefix for block format */\n argPrefix: string;\n /** Number of gadgets being registered */\n gadgetCount: number;\n /** Names of all gadgets */\n gadgetNames: string[];\n}\n\n/**\n * Template that can be either a static string or a function that renders based on context.\n */\nexport type PromptTemplate = string | ((context: PromptContext) => string);\n\n/**\n * Configuration for customizing all prompts used internally by llmist.\n *\n * Each field can be either a string (static text) or a function that receives\n * context and returns a string (for dynamic content).\n *\n * @example\n * ```typescript\n * const customConfig: PromptConfig = {\n * mainInstruction: \"USE ONLY THE GADGET MARKERS BELOW:\",\n * criticalUsage: \"Important: Follow the exact format shown.\",\n * rules: (ctx) => [\n * \"Always use the markers to invoke gadgets\",\n * \"Never use function calling\",\n * `You have ${ctx.gadgetCount} gadgets available`\n * ]\n * };\n * ```\n */\nexport interface PromptConfig {\n /**\n * Main instruction block that appears at the start of the gadget system prompt.\n * Default emphasizes using text markers instead of function calling.\n */\n mainInstruction?: PromptTemplate;\n\n /**\n * Critical usage instruction that appears in the usage section.\n * Default emphasizes the exact format requirement.\n */\n criticalUsage?: PromptTemplate;\n\n /**\n * Format description for the block parameter format.\n * Default uses the configured argPrefix dynamically.\n */\n formatDescription?: PromptTemplate;\n\n /**\n * Rules that appear in the rules section.\n * Can be an array of strings or a function that returns an array.\n * Default includes rules about not using function calling.\n */\n rules?: PromptTemplate | string[] | ((context: PromptContext) => string[]);\n\n /**\n * Custom examples to show in the examples section.\n * If provided, replaces the default examples entirely.\n * Should be a function that returns formatted example strings.\n */\n customExamples?: (context: PromptContext) => string;\n}\n\n/**\n * Default prompt templates used by llmist.\n */\nexport const DEFAULT_PROMPTS: Required<\n Omit<PromptConfig, \"rules\" | \"customExamples\"> & {\n rules: (context: PromptContext) => string[];\n customExamples: null;\n }\n> = {\n mainInstruction: [\n \"⚠️ CRITICAL: RESPOND ONLY WITH GADGET INVOCATIONS\",\n \"DO NOT use function calling or tool calling\",\n \"You must output the exact text markers shown below in plain text.\",\n \"EACH MARKER MUST START WITH A NEWLINE.\",\n ].join(\"\\n\"),\n\n criticalUsage: \"INVOKE gadgets using the markers - do not describe what you want to do.\",\n\n formatDescription: (ctx) =>\n `Parameters using ${ctx.argPrefix}name markers (value on next line(s), no escaping needed)`,\n\n rules: () => [\n \"Output ONLY plain text with the exact markers - never use function/tool calling\",\n \"You can invoke multiple gadgets in a single response\",\n \"For dependent gadgets, invoke the first one and wait for the result\",\n ],\n\n customExamples: null,\n};\n\n/**\n * Resolve a prompt template to a string using the given context.\n */\nexport function resolvePromptTemplate(\n template: PromptTemplate | undefined,\n defaultValue: PromptTemplate,\n context: PromptContext,\n): string {\n const resolved = template ?? defaultValue;\n return typeof resolved === \"function\" ? resolved(context) : resolved;\n}\n\n/**\n * Resolve rules template to an array of strings.\n */\nexport function resolveRulesTemplate(\n rules: PromptConfig[\"rules\"] | undefined,\n context: PromptContext,\n): string[] {\n const resolved = rules ?? DEFAULT_PROMPTS.rules;\n\n if (Array.isArray(resolved)) {\n return resolved;\n }\n\n if (typeof resolved === \"function\") {\n const result = resolved(context);\n return Array.isArray(result) ? result : [result];\n }\n\n return [resolved];\n}\n","import type { BaseGadget } from \"../gadgets/gadget.js\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"./constants.js\";\nimport type { PromptConfig } from \"./prompt-config.js\";\nimport { DEFAULT_PROMPTS, resolvePromptTemplate, resolveRulesTemplate } from \"./prompt-config.js\";\n\nexport type LLMRole = \"system\" | \"user\" | \"assistant\";\n\nexport interface LLMMessage {\n role: LLMRole;\n content: string;\n name?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport class LLMMessageBuilder {\n private readonly messages: LLMMessage[] = [];\n private startPrefix: string = GADGET_START_PREFIX;\n private endPrefix: string = GADGET_END_PREFIX;\n private argPrefix: string = GADGET_ARG_PREFIX;\n private promptConfig: PromptConfig;\n\n constructor(promptConfig?: PromptConfig) {\n this.promptConfig = promptConfig ?? {};\n }\n\n /**\n * Set custom prefixes for gadget markers.\n * Used to configure history builder to match system prompt markers.\n */\n withPrefixes(startPrefix: string, endPrefix: string, argPrefix?: string): this {\n this.startPrefix = startPrefix;\n this.endPrefix = endPrefix;\n if (argPrefix) {\n this.argPrefix = argPrefix;\n }\n return this;\n }\n\n addSystem(content: string, metadata?: Record<string, unknown>): this {\n this.messages.push({ role: \"system\", content, metadata });\n return this;\n }\n\n addGadgets(\n gadgets: BaseGadget[],\n options?: { startPrefix?: string; endPrefix?: string; argPrefix?: string },\n ): this {\n // Store custom prefixes for later use in addGadgetCall\n if (options?.startPrefix) {\n this.startPrefix = options.startPrefix;\n }\n if (options?.endPrefix) {\n this.endPrefix = options.endPrefix;\n }\n if (options?.argPrefix) {\n this.argPrefix = options.argPrefix;\n }\n\n const context = {\n startPrefix: this.startPrefix,\n endPrefix: this.endPrefix,\n argPrefix: this.argPrefix,\n gadgetCount: gadgets.length,\n gadgetNames: gadgets.map((g) => g.name ?? g.constructor.name),\n };\n\n const parts: string[] = [];\n\n // Use configurable main instruction\n const mainInstruction = resolvePromptTemplate(\n this.promptConfig.mainInstruction,\n DEFAULT_PROMPTS.mainInstruction,\n context,\n );\n parts.push(mainInstruction);\n\n parts.push(this.buildGadgetsSection(gadgets));\n parts.push(this.buildUsageSection(context));\n\n this.messages.push({ role: \"system\", content: parts.join(\"\") });\n return this;\n }\n\n private buildGadgetsSection(gadgets: BaseGadget[]): string {\n const parts: string[] = [];\n parts.push(\"\\n\\nAVAILABLE GADGETS\");\n parts.push(\"\\n=================\\n\");\n\n for (const gadget of gadgets) {\n const gadgetName = gadget.name ?? gadget.constructor.name;\n const instruction = gadget.getInstruction(this.argPrefix);\n\n // Parse instruction to separate description and schema\n const schemaMarker = \"\\n\\nInput Schema (BLOCK):\";\n const schemaIndex = instruction.indexOf(schemaMarker);\n\n const description = (\n schemaIndex !== -1 ? instruction.substring(0, schemaIndex) : instruction\n ).trim();\n const schema =\n schemaIndex !== -1 ? instruction.substring(schemaIndex + schemaMarker.length).trim() : \"\";\n\n parts.push(`\\nGADGET: ${gadgetName}`);\n parts.push(`\\n${description}`);\n if (schema) {\n parts.push(`\\n\\nPARAMETERS (BLOCK):\\n${schema}`);\n }\n parts.push(\"\\n\\n---\");\n }\n\n return parts.join(\"\");\n }\n\n private buildUsageSection(context: {\n startPrefix: string;\n endPrefix: string;\n argPrefix: string;\n gadgetCount: number;\n gadgetNames: string[];\n }): string {\n const parts: string[] = [];\n\n // Use configurable format description\n const formatDescription = resolvePromptTemplate(\n this.promptConfig.formatDescription,\n DEFAULT_PROMPTS.formatDescription,\n context,\n );\n\n parts.push(\"\\n\\nHOW TO INVOKE GADGETS\");\n parts.push(\"\\n=====================\\n\");\n\n // Use configurable critical usage instruction\n const criticalUsage = resolvePromptTemplate(\n this.promptConfig.criticalUsage,\n DEFAULT_PROMPTS.criticalUsage,\n context,\n );\n parts.push(`\\nCRITICAL: ${criticalUsage}\\n`);\n\n // Format section\n parts.push(\"\\nFORMAT:\");\n parts.push(`\\n 1. Start marker: ${this.startPrefix}gadget_name`);\n parts.push(`\\n 2. ${formatDescription}`);\n parts.push(`\\n 3. End marker: ${this.endPrefix}`);\n\n parts.push(this.buildExamplesSection(context));\n parts.push(this.buildRulesSection(context));\n\n parts.push(\"\\n\");\n\n return parts.join(\"\");\n }\n\n private buildExamplesSection(context: {\n startPrefix: string;\n endPrefix: string;\n argPrefix: string;\n gadgetCount: number;\n gadgetNames: string[];\n }): string {\n // Allow custom examples to completely replace default examples\n if (this.promptConfig.customExamples) {\n return this.promptConfig.customExamples(context);\n }\n\n const parts: string[] = [];\n\n // Single gadget example\n const singleExample = `${this.startPrefix}translate\n${this.argPrefix}from\nEnglish\n${this.argPrefix}to\nPolish\n${this.argPrefix}content\nParis is the capital of France: a beautiful city.\n${this.endPrefix}`;\n\n parts.push(`\\n\\nEXAMPLE (Single Gadget):\\n\\n${singleExample}`);\n\n // Multiple gadget example with multiline content\n const multipleExample = `${this.startPrefix}translate\n${this.argPrefix}from\nEnglish\n${this.argPrefix}to\nPolish\n${this.argPrefix}content\nParis is the capital of France: a beautiful city.\n${this.endPrefix}\n${this.startPrefix}analyze\n${this.argPrefix}type\neconomic_analysis\n${this.argPrefix}matter\nPolish Economy\n${this.argPrefix}question\nAnalyze the following:\n- Polish arms exports 2025\n- Economic implications\n${this.endPrefix}`;\n\n parts.push(`\\n\\nEXAMPLE (Multiple Gadgets):\\n\\n${multipleExample}`);\n\n // Block format syntax guide\n parts.push(`\n\nBLOCK FORMAT SYNTAX:\nBlock format uses ${this.argPrefix}name markers. Values are captured verbatim until the next marker.\n\n${this.argPrefix}filename\ncalculator.ts\n${this.argPrefix}code\nclass Calculator {\n private history: string[] = [];\n\n add(a: number, b: number): number {\n const result = a + b;\n this.history.push(\\`\\${a} + \\${b} = \\${result}\\`);\n return result;\n }\n}\n\nBLOCK FORMAT RULES:\n- Each parameter starts with ${this.argPrefix}parameterName on its own line\n- The value starts on the NEXT line after the marker\n- Value ends when the next ${this.argPrefix} or ${this.endPrefix} appears\n- NO escaping needed - write values exactly as they should appear\n- Perfect for code, JSON, markdown, or any content with special characters\n\nNESTED OBJECTS (use / separator):\n${this.argPrefix}config/timeout\n30\n${this.argPrefix}config/retries\n3\nProduces: { \"config\": { \"timeout\": \"30\", \"retries\": \"3\" } }\n\nARRAYS (use numeric indices):\n${this.argPrefix}items/0\nfirst\n${this.argPrefix}items/1\nsecond\nProduces: { \"items\": [\"first\", \"second\"] }`);\n\n return parts.join(\"\");\n }\n\n private buildRulesSection(context: {\n startPrefix: string;\n endPrefix: string;\n argPrefix: string;\n gadgetCount: number;\n gadgetNames: string[];\n }): string {\n const parts: string[] = [];\n parts.push(\"\\n\\nRULES:\");\n\n // Use configurable rules\n const rules = resolveRulesTemplate(this.promptConfig.rules, context);\n\n for (const rule of rules) {\n parts.push(`\\n - ${rule}`);\n }\n\n return parts.join(\"\");\n }\n\n addUser(content: string, metadata?: Record<string, unknown>): this {\n this.messages.push({ role: \"user\", content, metadata });\n return this;\n }\n\n addAssistant(content: string, metadata?: Record<string, unknown>): this {\n this.messages.push({ role: \"assistant\", content, metadata });\n return this;\n }\n\n addGadgetCall(gadget: string, parameters: Record<string, unknown>, result: string) {\n const paramStr = this.formatBlockParameters(parameters, \"\");\n\n // Assistant message with simplified gadget markers (no invocation ID)\n this.messages.push({\n role: \"assistant\",\n content: `${this.startPrefix}${gadget}\\n${paramStr}\\n${this.endPrefix}`,\n });\n\n // User message with result\n this.messages.push({\n role: \"user\",\n content: `Result: ${result}`,\n });\n\n return this;\n }\n\n /**\n * Format parameters as Block format with JSON Pointer paths.\n * Uses the configured argPrefix for consistency with system prompt.\n */\n private formatBlockParameters(\n params: Record<string, unknown>,\n prefix: string,\n ): string {\n const lines: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n const fullPath = prefix ? `${prefix}/${key}` : key;\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n const itemPath = `${fullPath}/${index}`;\n if (typeof item === \"object\" && item !== null) {\n lines.push(this.formatBlockParameters(item as Record<string, unknown>, itemPath));\n } else {\n lines.push(`${this.argPrefix}${itemPath}`);\n lines.push(String(item));\n }\n });\n } else if (typeof value === \"object\" && value !== null) {\n lines.push(this.formatBlockParameters(value as Record<string, unknown>, fullPath));\n } else {\n lines.push(`${this.argPrefix}${fullPath}`);\n lines.push(String(value));\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n build(): LLMMessage[] {\n return [...this.messages];\n }\n}\n\nexport const isLLMMessage = (value: unknown): value is LLMMessage => {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const message = value as Partial<LLMMessage>;\n return (\n (message.role === \"system\" || message.role === \"user\" || message.role === \"assistant\") &&\n typeof message.content === \"string\"\n );\n};\n","import { createWriteStream, mkdirSync, type WriteStream } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { type ILogObj, Logger } from \"tslog\";\n\nconst LEVEL_NAME_TO_ID: 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\nfunction parseLogLevel(value?: string): number | undefined {\n if (!value) {\n return undefined;\n }\n\n const normalized = value.trim().toLowerCase();\n\n if (normalized === \"\") {\n return undefined;\n }\n\n const numericLevel = Number(normalized);\n if (Number.isFinite(numericLevel)) {\n return Math.max(0, Math.min(6, Math.floor(numericLevel)));\n }\n\n return LEVEL_NAME_TO_ID[normalized];\n}\n\n/**\n * Logger configuration options for the library.\n */\nexport interface LoggerOptions {\n /**\n * Log level: 0=silly, 1=trace, 2=debug, 3=info, 4=warn, 5=error, 6=fatal\n * @default 4 (warn)\n */\n minLevel?: number;\n\n /**\n * Output type: 'pretty' for development, 'json' for production\n * @default 'pretty'\n */\n type?: \"pretty\" | \"json\" | \"hidden\";\n\n /**\n * Logger name (appears in logs)\n */\n name?: string;\n\n /**\n * When true, reset (truncate) the log file instead of appending.\n * Useful for getting clean logs per session.\n * @default false\n */\n logReset?: boolean;\n}\n\n/**\n * Parses a boolean environment variable.\n */\nfunction parseEnvBoolean(value?: string): boolean | undefined {\n if (!value) return undefined;\n const normalized = value.trim().toLowerCase();\n if (normalized === \"true\" || normalized === \"1\") return true;\n if (normalized === \"false\" || normalized === \"0\") return false;\n return undefined;\n}\n\n/**\n * Create a new logger instance for the library.\n *\n * @param options - Logger configuration options\n * @returns Configured Logger instance\n *\n * @example\n * ```typescript\n * // Development logger with pretty output\n * const logger = createLogger({ type: 'pretty', minLevel: 2 });\n *\n * // Production logger with JSON output\n * const logger = createLogger({ type: 'json', minLevel: 3 });\n *\n * // Silent logger for tests\n * const logger = createLogger({ type: 'hidden' });\n * ```\n */\nexport function createLogger(options: LoggerOptions = {}): Logger<ILogObj> {\n const envMinLevel = parseLogLevel(process.env.LLMIST_LOG_LEVEL);\n const envLogFile = process.env.LLMIST_LOG_FILE?.trim() ?? \"\";\n const envLogReset = parseEnvBoolean(process.env.LLMIST_LOG_RESET);\n\n const minLevel = options.minLevel ?? envMinLevel ?? 4;\n const defaultType = options.type ?? \"pretty\";\n const name = options.name ?? \"llmist\";\n // Priority: options > env var > default (false = append)\n const logReset = options.logReset ?? envLogReset ?? false;\n\n let logFileStream: WriteStream | undefined;\n let finalType = defaultType;\n\n if (envLogFile) {\n try {\n mkdirSync(dirname(envLogFile), { recursive: true });\n // Use \"w\" (write/truncate) when logReset is true, \"a\" (append) otherwise\n const flags = logReset ? \"w\" : \"a\";\n logFileStream = createWriteStream(envLogFile, { flags });\n finalType = \"hidden\";\n } catch (error) {\n console.error(\"Failed to initialize LLMIST_LOG_FILE output:\", error);\n }\n }\n\n const logger = new Logger<ILogObj>({\n name,\n minLevel,\n type: finalType,\n // Optimize for production\n hideLogPositionForProduction: finalType !== \"pretty\",\n // Pretty output settings\n prettyLogTemplate:\n finalType === \"pretty\"\n ? \"{{yyyy}}-{{mm}}-{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}} {{logLevelName}} [{{name}}] \"\n : undefined,\n });\n\n if (logFileStream) {\n logger.attachTransport((logObj) => {\n logFileStream?.write(`${JSON.stringify(logObj)}\\n`);\n });\n }\n\n return logger;\n}\n\n/**\n * Default logger instance for the library.\n * Users can replace this with their own configured logger.\n */\nexport const defaultLogger = createLogger();\n","/**\n * Zod schema to JSON Schema conversion with instance mismatch detection.\n *\n * When consumers use their own `import { z } from \"zod\"` instead of\n * `import { z } from \"llmist\"`, the `.describe()` metadata can be lost\n * because Zod stores metadata on schema instances and `toJSONSchema()`\n * only reads from schemas created by the same Zod module instance.\n *\n * This module provides a `schemaToJSONSchema()` function that:\n * 1. Converts Zod schema to JSON Schema using the standard API\n * 2. Detects if descriptions were lost due to instance mismatch\n * 3. Logs a warning recommending `import { z } from \"llmist\"`\n * 4. Falls back to extracting descriptions from `schema._def`\n *\n * @module gadgets/schema-to-json\n */\n\nimport type { ZodTypeAny } from \"zod\";\nimport * as z from \"zod\";\nimport { defaultLogger } from \"../logging/logger.js\";\n\n/**\n * Convert a Zod schema to JSON Schema with description fallback.\n *\n * If descriptions exist in schema._def but are missing from the generated\n * JSON Schema (indicating a Zod instance mismatch), this function:\n * 1. Logs a warning recommending `import { z } from \"llmist\"`\n * 2. Extracts descriptions from _def and merges them into the JSON Schema\n *\n * @param schema - Zod schema to convert\n * @param options - Conversion options (target JSON Schema version)\n * @returns JSON Schema object with descriptions preserved\n *\n * @example\n * ```typescript\n * import { schemaToJSONSchema } from './schema-to-json.js';\n * import { z } from 'zod';\n *\n * const schema = z.object({\n * name: z.string().describe('User name'),\n * });\n *\n * const jsonSchema = schemaToJSONSchema(schema);\n * // { type: 'object', properties: { name: { type: 'string', description: 'User name' } } }\n * ```\n */\nexport function schemaToJSONSchema(\n schema: ZodTypeAny,\n options?: { target?: \"draft-7\" | \"draft-2020-12\" },\n): Record<string, unknown> {\n const jsonSchema = z.toJSONSchema(schema, options ?? { target: \"draft-7\" });\n\n // Check for instance mismatch by comparing _def descriptions with JSON schema\n const mismatches = detectDescriptionMismatch(schema, jsonSchema);\n\n if (mismatches.length > 0) {\n defaultLogger.warn(\n `Zod instance mismatch detected: ${mismatches.length} description(s) lost. ` +\n `For best results, use: import { z } from \"llmist\"`,\n );\n\n // Merge descriptions from _def into JSON schema\n return mergeDescriptions(schema, jsonSchema);\n }\n\n return jsonSchema;\n}\n\n/**\n * Detect if schema._def contains descriptions that are missing from JSON schema.\n * Returns array of paths where descriptions were lost.\n */\nfunction detectDescriptionMismatch(\n schema: ZodTypeAny,\n jsonSchema: Record<string, unknown>,\n): string[] {\n const mismatches: string[] = [];\n\n function checkSchema(zodSchema: ZodTypeAny, json: unknown, path: string): void {\n if (!zodSchema || typeof zodSchema !== \"object\") return;\n\n const def = zodSchema._def as unknown as Record<string, unknown> | undefined;\n const jsonObj = json as Record<string, unknown> | undefined;\n\n // Check if _def has description but JSON schema doesn't\n if (def?.description && !jsonObj?.description) {\n mismatches.push(path || \"root\");\n }\n\n // Recursively check object properties\n if (def?.typeName === \"ZodObject\" && def?.shape) {\n const shape =\n typeof def.shape === \"function\"\n ? (def.shape as () => Record<string, ZodTypeAny>)()\n : def.shape;\n for (const [key, fieldSchema] of Object.entries(shape as Record<string, ZodTypeAny>)) {\n const properties = jsonObj?.properties as Record<string, unknown> | undefined;\n const jsonProp = properties?.[key];\n checkSchema(fieldSchema, jsonProp, path ? `${path}.${key}` : key);\n }\n }\n\n // Check array items\n if (def?.typeName === \"ZodArray\" && def?.type) {\n checkSchema(def.type as ZodTypeAny, jsonObj?.items, path ? `${path}[]` : \"[]\");\n }\n\n // Check optional/nullable wrapped types\n if ((def?.typeName === \"ZodOptional\" || def?.typeName === \"ZodNullable\") && def?.innerType) {\n checkSchema(def.innerType as ZodTypeAny, json, path);\n }\n\n // Check default wrapped types\n if (def?.typeName === \"ZodDefault\" && def?.innerType) {\n checkSchema(def.innerType as ZodTypeAny, json, path);\n }\n }\n\n checkSchema(schema, jsonSchema, \"\");\n return mismatches;\n}\n\n/**\n * Merge descriptions from schema._def into JSON schema.\n * Returns a new JSON schema object with descriptions filled in from _def.\n */\nfunction mergeDescriptions(\n schema: ZodTypeAny,\n jsonSchema: Record<string, unknown>,\n): Record<string, unknown> {\n function merge(zodSchema: ZodTypeAny, json: unknown): unknown {\n if (!json || typeof json !== \"object\") return json;\n\n const def = zodSchema._def as unknown as Record<string, unknown> | undefined;\n const jsonObj = json as Record<string, unknown>;\n const merged: Record<string, unknown> = { ...jsonObj };\n\n // Copy description from _def if missing in JSON\n if (def?.description && !jsonObj.description) {\n merged.description = def.description;\n }\n\n // Recursively merge object properties\n if (def?.typeName === \"ZodObject\" && def?.shape && jsonObj.properties) {\n const shape =\n typeof def.shape === \"function\"\n ? (def.shape as () => Record<string, ZodTypeAny>)()\n : def.shape;\n const properties = jsonObj.properties as Record<string, unknown>;\n merged.properties = { ...properties };\n for (const [key, fieldSchema] of Object.entries(shape as Record<string, ZodTypeAny>)) {\n if (properties[key]) {\n (merged.properties as Record<string, unknown>)[key] = merge(fieldSchema, properties[key]);\n }\n }\n }\n\n // Merge array items\n if (def?.typeName === \"ZodArray\" && def?.type && jsonObj.items) {\n merged.items = merge(def.type as ZodTypeAny, jsonObj.items);\n }\n\n // Handle optional/nullable wrapped types\n if ((def?.typeName === \"ZodOptional\" || def?.typeName === \"ZodNullable\") && def?.innerType) {\n return merge(def.innerType as ZodTypeAny, json);\n }\n\n // Handle default wrapped types\n if (def?.typeName === \"ZodDefault\" && def?.innerType) {\n return merge(def.innerType as ZodTypeAny, json);\n }\n\n return merged;\n }\n\n return merge(schema, jsonSchema) as Record<string, unknown>;\n}\n","import type { ZodTypeAny } from \"zod\";\n\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { schemaToJSONSchema } from \"./schema-to-json.js\";\nimport { validateGadgetSchema } from \"./schema-validator.js\";\nimport type { GadgetExample } from \"./types.js\";\n\n/**\n * Format parameters object as Block format.\n * Uses JSON Pointer paths for nested structures.\n *\n * @param params - The parameters object to format\n * @param prefix - Path prefix for nested structures (internal use)\n * @param argPrefix - The argument prefix marker (defaults to GADGET_ARG_PREFIX)\n */\nfunction formatParamsAsBlock(\n params: Record<string, unknown>,\n prefix: string = \"\",\n argPrefix: string = GADGET_ARG_PREFIX,\n): string {\n const lines: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n const fullPath = prefix ? `${prefix}/${key}` : key;\n\n if (Array.isArray(value)) {\n // Arrays: use numeric indices\n value.forEach((item, index) => {\n const itemPath = `${fullPath}/${index}`;\n if (typeof item === \"object\" && item !== null) {\n // Nested object in array\n lines.push(formatParamsAsBlock(item as Record<string, unknown>, itemPath, argPrefix));\n } else {\n lines.push(`${argPrefix}${itemPath}`);\n lines.push(String(item));\n }\n });\n } else if (typeof value === \"object\" && value !== null) {\n // Nested objects: recurse with path prefix\n lines.push(formatParamsAsBlock(value as Record<string, unknown>, fullPath, argPrefix));\n } else {\n // Simple values\n lines.push(`${argPrefix}${fullPath}`);\n lines.push(String(value));\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format JSON Schema as plain text description.\n * This avoids format confusion by presenting parameters in a neutral,\n * human-readable format that works equally well for JSON, YAML, TOML, or XML.\n */\nfunction formatSchemaAsPlainText(schema: Record<string, unknown>, indent = \"\"): string {\n const lines: string[] = [];\n const properties = (schema.properties || {}) as Record<string, unknown>;\n const required = (schema.required || []) as string[];\n\n for (const [key, prop] of Object.entries(properties)) {\n const propObj = prop as Record<string, unknown>;\n const type = propObj.type as string;\n const description = propObj.description as string | undefined;\n const isRequired = required.includes(key);\n const enumValues = propObj.enum as string[] | undefined;\n\n // Build the line\n let line = `${indent}- ${key}`;\n\n // Add type info\n if (type === \"array\") {\n const items = propObj.items as Record<string, unknown> | undefined;\n const itemType = items?.type || \"any\";\n line += ` (array of ${itemType})`;\n } else if (type === \"object\" && propObj.properties) {\n line += \" (object)\";\n } else {\n line += ` (${type})`;\n }\n\n // Add required marker\n if (isRequired) {\n line += \" [required]\";\n }\n\n // Add description\n if (description) {\n line += `: ${description}`;\n }\n\n // Add enum values if present\n if (enumValues) {\n line += ` - one of: ${enumValues.map((v) => `\"${v}\"`).join(\", \")}`;\n }\n\n lines.push(line);\n\n // Recurse for nested objects\n if (type === \"object\" && propObj.properties) {\n lines.push(formatSchemaAsPlainText(propObj, indent + \" \"));\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Internal base class for gadgets. Most users should use the `Gadget` class\n * (formerly TypedGadget) or `createGadget()` function instead, as they provide\n * better type safety and simpler APIs.\n *\n * @internal\n */\nexport abstract class BaseGadget {\n /**\n * The name of the gadget. Used for identification when LLM calls it.\n * If not provided, defaults to the class name.\n */\n name?: string;\n\n /**\n * Human-readable description of what the gadget does.\n */\n abstract description: string;\n\n /**\n * Optional Zod schema describing the expected input payload. When provided,\n * it will be validated before execution and transformed into a JSON Schema\n * representation that is surfaced to the LLM as part of the instructions.\n */\n parameterSchema?: ZodTypeAny;\n\n /**\n * Optional timeout in milliseconds for gadget execution.\n * If execution exceeds this timeout, a TimeoutException will be thrown.\n * If not set, the global defaultGadgetTimeoutMs from runtime options will be used.\n * Set to 0 or undefined to disable timeout for this gadget.\n */\n timeoutMs?: number;\n\n /**\n * Optional usage examples to help LLMs understand proper invocation.\n * Examples are rendered in getInstruction() alongside the schema.\n *\n * Note: Uses broader `unknown` type to allow typed examples from subclasses\n * while maintaining runtime compatibility.\n */\n examples?: GadgetExample<unknown>[];\n\n /**\n * Execute the gadget with the given parameters.\n * Can be synchronous or asynchronous.\n *\n * @param params - Parameters passed from the LLM\n * @returns Result as a string\n */\n abstract execute(params: Record<string, unknown>): string | Promise<string>;\n\n /**\n * Auto-generated instruction text for the LLM.\n * Combines name, description, and parameter schema into a formatted instruction.\n * @deprecated Use getInstruction() instead\n */\n get instruction(): string {\n return this.getInstruction();\n }\n\n /**\n * Generate instruction text for the LLM.\n * Combines name, description, and parameter schema into a formatted instruction.\n *\n * @param argPrefix - Optional custom argument prefix for block format examples\n * @returns Formatted instruction string\n */\n getInstruction(argPrefix?: string): string {\n const parts: string[] = [];\n\n // Add description\n parts.push(this.description);\n\n if (this.parameterSchema) {\n // Validate that the schema doesn't use z.unknown() and can be serialized\n const gadgetName = this.name ?? this.constructor.name;\n validateGadgetSchema(this.parameterSchema, gadgetName);\n\n const jsonSchema = schemaToJSONSchema(this.parameterSchema, {\n target: \"draft-7\",\n });\n\n // Use plain text schema description\n parts.push(\"\\n\\nParameters:\");\n parts.push(formatSchemaAsPlainText(jsonSchema));\n }\n\n // Render examples if present\n if (this.examples && this.examples.length > 0) {\n parts.push(\"\\n\\nExamples:\");\n\n // Use custom argPrefix if provided, otherwise use default\n const effectiveArgPrefix = argPrefix ?? GADGET_ARG_PREFIX;\n\n this.examples.forEach((example, index) => {\n // Add blank line between examples (but not before the first one)\n if (index > 0) {\n parts.push(\"\");\n }\n\n // Add comment if provided\n if (example.comment) {\n parts.push(`# ${example.comment}`);\n }\n\n // Render params in block format\n parts.push(\"Input:\");\n parts.push(formatParamsAsBlock(example.params as Record<string, unknown>, \"\", effectiveArgPrefix));\n\n // Render output if provided\n if (example.output !== undefined) {\n parts.push(\"Output:\");\n parts.push(example.output);\n }\n });\n }\n\n return parts.join(\"\\n\");\n }\n}\n","/**\n * Function-based gadget creation helper.\n *\n * For simple gadgets, use createGadget() instead of defining a class.\n * Parameters are automatically typed from the Zod schema.\n *\n * @example\n * ```typescript\n * const calculator = createGadget({\n * description: \"Performs arithmetic operations\",\n * schema: z.object({\n * operation: z.enum([\"add\", \"subtract\"]),\n * a: z.number(),\n * b: z.number(),\n * }),\n * execute: ({ operation, a, b }) => {\n * // Automatically typed!\n * return operation === \"add\" ? String(a + b) : String(a - b);\n * },\n * });\n * ```\n */\n\nimport type { ZodType } from \"zod\";\nimport { BaseGadget } from \"./gadget.js\";\nimport type { GadgetExample } from \"./types.js\";\n\n/**\n * Infer the TypeScript type from a Zod schema.\n */\ntype InferSchema<T> = T extends ZodType<infer U> ? U : never;\n\n/**\n * Configuration for creating a function-based gadget.\n */\nexport interface CreateGadgetConfig<TSchema extends ZodType> {\n /** Optional custom name (defaults to \"FunctionGadget\") */\n name?: string;\n\n /** Human-readable description of what the gadget does */\n description: string;\n\n /** Zod schema for parameter validation */\n schema: TSchema;\n\n /** Execution function with typed parameters */\n execute: (params: InferSchema<TSchema>) => string | Promise<string>;\n\n /** Optional timeout in milliseconds */\n timeoutMs?: number;\n\n /** Optional usage examples to help LLMs understand proper invocation */\n examples?: GadgetExample<InferSchema<TSchema>>[];\n}\n\n/**\n * Creates a gadget from a function (simpler than class-based approach).\n *\n * This is perfect for simple gadgets where you don't need the full\n * power of a class. Parameters are automatically typed from the schema.\n *\n * @param config - Configuration with execute function and schema\n * @returns Gadget instance ready to be registered\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { createGadget } from 'llmist';\n *\n * // Simple calculator gadget\n * const calculator = createGadget({\n * description: \"Performs arithmetic operations\",\n * schema: z.object({\n * operation: z.enum([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n * a: z.number().describe(\"First number\"),\n * b: z.number().describe(\"Second number\"),\n * }),\n * execute: ({ operation, a, b }) => {\n * // Parameters are automatically typed!\n * switch (operation) {\n * case \"add\": return String(a + b);\n * case \"subtract\": return String(a - b);\n * case \"multiply\": return String(a * b);\n * case \"divide\": return String(a / b);\n * }\n * },\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Async gadget with custom name and timeout\n * const weather = createGadget({\n * name: \"weather\",\n * description: \"Fetches current weather for a city\",\n * schema: z.object({\n * city: z.string().min(1).describe(\"City name\"),\n * }),\n * timeoutMs: 10000,\n * execute: async ({ city }) => {\n * const response = await fetch(`https://api.weather.com/${city}`);\n * const data = await response.json();\n * return `Weather in ${city}: ${data.description}, ${data.temp}°C`;\n * },\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Use with agent\n * const agent = LLMist.createAgent()\n * .withGadgets(calculator, weather)\n * .ask(\"What's the weather in Paris and what's 10 + 5?\");\n * ```\n */\nexport function createGadget<TSchema extends ZodType>(\n config: CreateGadgetConfig<TSchema>,\n): BaseGadget {\n class DynamicGadget extends BaseGadget {\n name = config.name;\n description = config.description;\n parameterSchema = config.schema;\n timeoutMs = config.timeoutMs;\n examples = config.examples;\n\n execute(params: Record<string, unknown>): string | Promise<string> {\n // Cast to inferred type and call user's function\n return config.execute(params as InferSchema<TSchema>);\n }\n }\n\n return new DynamicGadget();\n}\n","/**\n * GadgetOutputViewer - Browse stored outputs from gadgets that exceeded the size limit.\n *\n * When a gadget returns too much data, the output is stored and can be browsed\n * using this gadget with grep-like pattern filtering and line limiting.\n */\n\nimport { z } from \"zod\";\nimport type { GadgetOutputStore } from \"../agent/gadget-output-store.js\";\nimport { createGadget } from \"./create-gadget.js\";\n\n/**\n * Pattern filter configuration.\n */\ninterface PatternFilter {\n /** Regular expression to match */\n regex: string;\n /** true = keep matches, false = exclude matches */\n include: boolean;\n /** Context lines before match (like grep -B) */\n before: number;\n /** Context lines after match (like grep -A) */\n after: number;\n}\n\n/**\n * Apply a single pattern filter to lines.\n *\n * For include=true: keeps lines that match (with before/after context).\n * For include=false: removes lines that match.\n */\nfunction applyPattern(lines: string[], pattern: PatternFilter): string[] {\n const regex = new RegExp(pattern.regex);\n\n if (!pattern.include) {\n // Exclude mode: remove matching lines\n return lines.filter((line) => !regex.test(line));\n }\n\n // Include mode: keep matching lines with context\n const matchIndices = new Set<number>();\n\n // Find all matching line indices\n for (let i = 0; i < lines.length; i++) {\n if (regex.test(lines[i])) {\n // Add the matching line and its context\n const start = Math.max(0, i - pattern.before);\n const end = Math.min(lines.length - 1, i + pattern.after);\n for (let j = start; j <= end; j++) {\n matchIndices.add(j);\n }\n }\n }\n\n // Return lines at matching indices (preserving order)\n return lines.filter((_, index) => matchIndices.has(index));\n}\n\n/**\n * Apply multiple pattern filters in sequence (like piping through grep commands).\n */\nfunction applyPatterns(lines: string[], patterns: PatternFilter[]): string[] {\n let result = lines;\n for (const pattern of patterns) {\n result = applyPattern(result, pattern);\n }\n return result;\n}\n\n/**\n * Parse and apply a line limit string.\n *\n * Formats:\n * - \"100-\" → first 100 lines (slice 0 to 100)\n * - \"-25\" → last 25 lines (slice -25)\n * - \"50-100\" → lines 50-100 (1-indexed, so slice 49 to 100)\n */\nfunction applyLineLimit(lines: string[], limit: string): string[] {\n const trimmed = limit.trim();\n\n // Format: \"100-\" (first N lines)\n if (trimmed.endsWith(\"-\") && !trimmed.startsWith(\"-\")) {\n const n = parseInt(trimmed.slice(0, -1), 10);\n if (!isNaN(n) && n > 0) {\n return lines.slice(0, n);\n }\n }\n\n // Format: \"-25\" (last N lines)\n if (trimmed.startsWith(\"-\") && !trimmed.includes(\"-\", 1)) {\n const n = parseInt(trimmed, 10);\n if (!isNaN(n) && n < 0) {\n return lines.slice(n);\n }\n }\n\n // Format: \"50-100\" (range, 1-indexed)\n const rangeMatch = trimmed.match(/^(\\d+)-(\\d+)$/);\n if (rangeMatch) {\n const start = parseInt(rangeMatch[1], 10);\n const end = parseInt(rangeMatch[2], 10);\n if (!isNaN(start) && !isNaN(end) && start > 0 && end >= start) {\n // Convert from 1-indexed to 0-indexed\n return lines.slice(start - 1, end);\n }\n }\n\n // Invalid format - return unchanged\n return lines;\n}\n\n/**\n * Schema for pattern filter objects.\n */\nconst patternSchema = z.object({\n regex: z.string().describe(\"Regular expression to match\"),\n include: z\n .boolean()\n .default(true)\n .describe(\"true = keep matching lines, false = exclude matching lines\"),\n before: z\n .number()\n .int()\n .min(0)\n .default(0)\n .describe(\"Context lines before each match (like grep -B)\"),\n after: z\n .number()\n .int()\n .min(0)\n .default(0)\n .describe(\"Context lines after each match (like grep -A)\"),\n});\n\n/**\n * Create a GadgetOutputViewer gadget instance bound to a specific output store.\n *\n * This is a factory function because the gadget needs access to the output store,\n * which is created per-agent-run.\n *\n * @param store - The GadgetOutputStore to read outputs from\n * @returns A GadgetOutputViewer gadget instance\n *\n * @example\n * ```typescript\n * const store = new GadgetOutputStore();\n * const viewer = createGadgetOutputViewer(store);\n * registry.register(\"GadgetOutputViewer\", viewer);\n * ```\n */\nexport function createGadgetOutputViewer(store: GadgetOutputStore) {\n return createGadget({\n name: \"GadgetOutputViewer\",\n description:\n \"View stored output from gadgets that returned too much data. \" +\n \"Use patterns to filter lines (like grep) and limit to control output size. \" +\n \"Patterns are applied first in order, then the limit is applied to the result.\",\n schema: z.object({\n id: z.string().describe(\"ID of the stored output (from the truncation message)\"),\n patterns: z\n .array(patternSchema)\n .optional()\n .describe(\n \"Filter patterns applied in order (like piping through grep). \" +\n \"Each pattern can include or exclude lines with optional before/after context.\",\n ),\n limit: z\n .string()\n .optional()\n .describe(\n \"Line range to return after filtering. \" +\n \"Formats: '100-' (first 100), '-25' (last 25), '50-100' (lines 50-100)\",\n ),\n }),\n examples: [\n {\n comment: \"View first 50 lines of stored output\",\n params: { id: \"Search_abc12345\", limit: \"50-\" },\n },\n {\n comment: \"Filter for error lines with context\",\n params: {\n id: \"Search_abc12345\",\n patterns: [{ regex: \"error|Error|ERROR\", include: true, before: 2, after: 5 }],\n },\n },\n {\n comment: \"Exclude blank lines, then show first 100\",\n params: {\n id: \"Search_abc12345\",\n patterns: [{ regex: \"^\\\\s*$\", include: false, before: 0, after: 0 }],\n limit: \"100-\",\n },\n },\n {\n comment: \"Chain filters: find TODOs, exclude tests, limit to 50 lines\",\n params: {\n id: \"Search_abc12345\",\n patterns: [\n { regex: \"TODO\", include: true, before: 1, after: 1 },\n { regex: \"test|spec\", include: false, before: 0, after: 0 },\n ],\n limit: \"50-\",\n },\n },\n ],\n execute: ({ id, patterns, limit }) => {\n const stored = store.get(id);\n if (!stored) {\n return `Error: No stored output with id \"${id}\". Available IDs: ${store.getIds().join(\", \") || \"(none)\"}`;\n }\n\n let lines = stored.content.split(\"\\n\");\n\n // Step 1: Apply patterns in order (like piping through grep)\n if (patterns && patterns.length > 0) {\n lines = applyPatterns(\n lines,\n patterns.map((p) => ({\n regex: p.regex,\n include: p.include ?? true,\n before: p.before ?? 0,\n after: p.after ?? 0,\n })),\n );\n }\n\n // Step 2: Apply line limit AFTER all patterns\n if (limit) {\n lines = applyLineLimit(lines, limit);\n }\n\n // Return result with metadata\n const totalLines = stored.lineCount;\n const returnedLines = lines.length;\n\n if (returnedLines === 0) {\n return `No lines matched the filters. Original output had ${totalLines} lines.`;\n }\n\n const header =\n returnedLines < totalLines\n ? `[Showing ${returnedLines} of ${totalLines} lines]\\n`\n : `[Showing all ${totalLines} lines]\\n`;\n\n return header + lines.join(\"\\n\");\n },\n });\n}\n\n// Export helpers for testing\nexport { applyPattern, applyPatterns, applyLineLimit };\n","/**\n * Storage for large gadget outputs that exceed the configured limit.\n *\n * When a gadget returns more data than the configured limit, the output\n * is stored here and can be browsed later using GadgetOutputViewer.\n */\n\nimport { randomBytes } from \"node:crypto\";\n\n/**\n * Metadata and content for a stored gadget output.\n */\nexport interface StoredOutput {\n /** Unique identifier (e.g., \"Search_d34db33f\") */\n id: string;\n /** Name of the gadget that produced this output */\n gadgetName: string;\n /** Full output content */\n content: string;\n /** Size in bytes */\n byteSize: number;\n /** Number of lines */\n lineCount: number;\n /** When the output was stored */\n timestamp: Date;\n}\n\n/**\n * In-memory store for large gadget outputs.\n *\n * Outputs are stored with generated IDs in the format `{GadgetName}_{hex8}`.\n * The store is tied to an agent run and cleared when the agent completes.\n *\n * @example\n * ```typescript\n * const store = new GadgetOutputStore();\n * const id = store.store(\"Search\", largeOutput);\n * // id = \"Search_a1b2c3d4\"\n *\n * const stored = store.get(id);\n * console.log(stored?.lineCount); // 4200\n * ```\n */\nexport class GadgetOutputStore {\n private outputs = new Map<string, StoredOutput>();\n\n /**\n * Store a gadget output and return its ID.\n *\n * @param gadgetName - Name of the gadget that produced the output\n * @param content - Full output content to store\n * @returns Generated ID for retrieving the output later\n */\n store(gadgetName: string, content: string): string {\n const id = this.generateId(gadgetName);\n const encoder = new TextEncoder();\n\n const stored: StoredOutput = {\n id,\n gadgetName,\n content,\n byteSize: encoder.encode(content).length,\n lineCount: content.split(\"\\n\").length,\n timestamp: new Date(),\n };\n\n this.outputs.set(id, stored);\n return id;\n }\n\n /**\n * Retrieve a stored output by ID.\n *\n * @param id - The output ID (e.g., \"Search_d34db33f\")\n * @returns The stored output or undefined if not found\n */\n get(id: string): StoredOutput | undefined {\n return this.outputs.get(id);\n }\n\n /**\n * Check if an output exists.\n *\n * @param id - The output ID to check\n * @returns True if the output exists\n */\n has(id: string): boolean {\n return this.outputs.has(id);\n }\n\n /**\n * Get all stored output IDs.\n *\n * @returns Array of output IDs\n */\n getIds(): string[] {\n return Array.from(this.outputs.keys());\n }\n\n /**\n * Get the number of stored outputs.\n */\n get size(): number {\n return this.outputs.size;\n }\n\n /**\n * Clear all stored outputs.\n * Called when the agent run completes.\n */\n clear(): void {\n this.outputs.clear();\n }\n\n /**\n * Generate a unique ID for a stored output.\n * Format: {GadgetName}_{8 hex chars}\n */\n private generateId(gadgetName: string): string {\n const hex = randomBytes(4).toString(\"hex\");\n return `${gadgetName}_${hex}`;\n }\n}\n","/**\n * Internal key for Agent instantiation.\n * This Symbol is used to ensure only AgentBuilder can create Agent instances.\n *\n * @internal\n */\nexport const AGENT_INTERNAL_KEY = Symbol(\"AGENT_INTERNAL_KEY\");\n\n/**\n * Type guard to check if the key is the correct internal key\n * @internal\n */\nexport function isValidAgentKey(key: unknown): key is typeof AGENT_INTERNAL_KEY {\n return key === AGENT_INTERNAL_KEY;\n}\n","/**\n * ConversationManager handles conversation state and message building.\n * Extracted from AgentLoop to follow Single Responsibility Principle.\n */\n\nimport { type LLMMessage, LLMMessageBuilder } from \"../core/messages.js\";\nimport type { IConversationManager } from \"./interfaces.js\";\n\n/**\n * Options for ConversationManager constructor.\n */\nexport interface ConversationManagerOptions {\n /** Custom gadget start marker prefix */\n startPrefix?: string;\n /** Custom gadget end marker prefix */\n endPrefix?: string;\n /** Custom argument prefix for block format */\n argPrefix?: string;\n}\n\n/**\n * Default implementation of IConversationManager.\n * Manages conversation history by building on top of base messages (system prompt, gadget instructions).\n */\nexport class ConversationManager implements IConversationManager {\n private readonly baseMessages: LLMMessage[];\n private readonly initialMessages: LLMMessage[];\n private readonly historyBuilder: LLMMessageBuilder;\n\n constructor(\n baseMessages: LLMMessage[],\n initialMessages: LLMMessage[],\n options: ConversationManagerOptions = {},\n ) {\n this.baseMessages = baseMessages;\n this.initialMessages = initialMessages;\n this.historyBuilder = new LLMMessageBuilder();\n\n // Apply custom prefixes if provided (must match system prompt markers)\n if (options.startPrefix && options.endPrefix) {\n this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix, options.argPrefix);\n }\n }\n\n addUserMessage(content: string): void {\n this.historyBuilder.addUser(content);\n }\n\n addAssistantMessage(content: string): void {\n this.historyBuilder.addAssistant(content);\n }\n\n addGadgetCall(gadgetName: string, parameters: Record<string, unknown>, result: string): void {\n this.historyBuilder.addGadgetCall(gadgetName, parameters, result);\n }\n\n getMessages(): LLMMessage[] {\n return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];\n }\n}\n","/**\n * Event handler sugar for cleaner event processing.\n *\n * Instead of verbose if/else chains, use named handlers\n * for each event type.\n *\n * @example\n * ```typescript\n * await agent.runWith({\n * onText: (content) => console.log(\"LLM:\", content),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\n\nimport type { StreamEvent } from \"../gadgets/types.js\";\n\n/**\n * Named event handlers for different event types.\n */\nexport interface EventHandlers {\n /** Called when text is generated by the LLM */\n onText?: (content: string) => void | Promise<void>;\n\n /** Called when a gadget is about to be executed */\n onGadgetCall?: (call: {\n gadgetName: string;\n parameters?: Record<string, unknown>;\n parametersRaw: string;\n }) => void | Promise<void>;\n\n /** Called when a gadget execution completes */\n onGadgetResult?: (result: {\n gadgetName: string;\n result?: string;\n error?: string;\n parameters: Record<string, unknown>;\n }) => void | Promise<void>;\n\n /** Called when human input is required */\n onHumanInputRequired?: (data: { question: string; gadgetName: string }) => void | Promise<void>;\n\n /** Called for any other event type */\n onOther?: (event: StreamEvent) => void | Promise<void>;\n}\n\n/**\n * Helper to run an agent with named event handlers.\n *\n * @param agentGenerator - Agent's run() async generator\n * @param handlers - Named event handlers\n *\n * @example\n * ```typescript\n * await runWithHandlers(agent.run(), {\n * onText: (text) => console.log(\"LLM:\", text),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\nexport async function runWithHandlers(\n agentGenerator: AsyncGenerator<StreamEvent>,\n handlers: EventHandlers,\n): Promise<void> {\n for await (const event of agentGenerator) {\n switch (event.type) {\n case \"text\":\n if (handlers.onText) {\n await handlers.onText(event.content);\n }\n break;\n\n case \"gadget_call\":\n if (handlers.onGadgetCall) {\n await handlers.onGadgetCall({\n gadgetName: event.call.gadgetName,\n parameters: event.call.parameters,\n parametersRaw: event.call.parametersRaw,\n });\n }\n break;\n\n case \"gadget_result\":\n if (handlers.onGadgetResult) {\n await handlers.onGadgetResult(event.result);\n }\n break;\n\n case \"human_input_required\":\n if (handlers.onHumanInputRequired) {\n await handlers.onHumanInputRequired({\n question: event.question,\n gadgetName: event.gadgetName,\n });\n }\n break;\n\n default:\n if (handlers.onOther) {\n await handlers.onOther(event);\n }\n break;\n }\n }\n}\n\n/**\n * Helper to collect events by type.\n *\n * @param agentGenerator - Agent's run() async generator\n * @param collect - Object specifying which event types to collect\n * @returns Object with collected events\n *\n * @example\n * ```typescript\n * const { text, gadgetResults } = await collectEvents(agent.run(), {\n * text: true,\n * gadgetResults: true,\n * });\n *\n * console.log(\"Full response:\", text.join(\"\"));\n * console.log(\"Gadget calls:\", gadgetResults.length);\n * ```\n */\nexport async function collectEvents(\n agentGenerator: AsyncGenerator<StreamEvent>,\n collect: {\n text?: boolean;\n gadgetCalls?: boolean;\n gadgetResults?: boolean;\n },\n): Promise<{\n text: string[];\n gadgetCalls: Array<{ gadgetName: string; parameters: Record<string, unknown> }>;\n gadgetResults: Array<{\n gadgetName: string;\n result?: string;\n error?: string;\n parameters: Record<string, unknown>;\n }>;\n}> {\n const result = {\n text: [] as string[],\n gadgetCalls: [] as Array<{ gadgetName: string; parameters: Record<string, unknown> }>,\n gadgetResults: [] as Array<{\n gadgetName: string;\n result?: string;\n error?: string;\n parameters: Record<string, unknown>;\n }>,\n };\n\n for await (const event of agentGenerator) {\n switch (event.type) {\n case \"text\":\n if (collect.text) {\n result.text.push(event.content);\n }\n break;\n\n case \"gadget_call\":\n if (collect.gadgetCalls && event.call.parameters) {\n result.gadgetCalls.push({\n gadgetName: event.call.gadgetName,\n parameters: event.call.parameters,\n });\n }\n break;\n\n case \"gadget_result\":\n if (collect.gadgetResults) {\n result.gadgetResults.push(event.result);\n }\n break;\n }\n }\n\n return result;\n}\n\n/**\n * Helper to collect only text from an agent run.\n *\n * @param agentGenerator - Agent's run() async generator\n * @returns Combined text response\n *\n * @example\n * ```typescript\n * const response = await collectText(agent.run());\n * console.log(response);\n * ```\n */\nexport async function collectText(agentGenerator: AsyncGenerator<StreamEvent>): Promise<string> {\n const chunks: string[] = [];\n\n for await (const event of agentGenerator) {\n if (event.type === \"text\") {\n chunks.push(event.content);\n }\n }\n\n return chunks.join(\"\");\n}\n","/**\n * Runtime validators for hook action types.\n *\n * These validators ensure that controllers return valid action objects,\n * catching common mistakes like missing required fields.\n */\n\nimport type {\n AfterGadgetExecutionAction,\n AfterLLMCallAction,\n AfterLLMErrorAction,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n} from \"./hooks.js\";\n\nexport class HookValidationError extends Error {\n constructor(hookName: string, message: string) {\n super(`Invalid action from ${hookName}: ${message}`);\n this.name = \"HookValidationError\";\n }\n}\n\n/**\n * Validate beforeLLMCall action.\n */\nexport function validateBeforeLLMCallAction(action: BeforeLLMCallAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"beforeLLMCall\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"proceed\" && actionType !== \"skip\") {\n throw new HookValidationError(\n \"beforeLLMCall\",\n `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n );\n }\n\n if (actionType === \"skip\" && !action.syntheticResponse) {\n throw new HookValidationError(\n \"beforeLLMCall\",\n \"When action is 'skip', syntheticResponse is required\",\n );\n }\n}\n\n/**\n * Validate afterLLMCall action.\n */\nexport function validateAfterLLMCallAction(action: AfterLLMCallAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n const validActions = [\"continue\", \"append_messages\", \"modify_and_continue\", \"append_and_modify\"];\n if (!validActions.includes(actionType)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Invalid action type: ${actionType}. Must be one of: ${validActions.join(\", \")}`,\n );\n }\n\n if (actionType === \"append_messages\" || actionType === \"append_and_modify\") {\n if (!(\"messages\" in action) || !action.messages || !Array.isArray(action.messages)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', messages array is required`,\n );\n }\n\n if (action.messages.length === 0) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', messages array must not be empty`,\n );\n }\n\n // Validate each message\n for (let i = 0; i < action.messages.length; i++) {\n const msg = action.messages[i];\n if (!msg || typeof msg !== \"object\") {\n throw new HookValidationError(\"afterLLMCall\", `Message at index ${i} must be an object`);\n }\n if (!msg.role || !msg.content) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Message at index ${i} must have 'role' and 'content' fields`,\n );\n }\n if (![\"system\", \"user\", \"assistant\"].includes(msg.role)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Message at index ${i} has invalid role: ${msg.role}`,\n );\n }\n }\n }\n\n if (actionType === \"modify_and_continue\" || actionType === \"append_and_modify\") {\n if (!(\"modifiedMessage\" in action) || !action.modifiedMessage) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', modifiedMessage is required`,\n );\n }\n }\n}\n\n/**\n * Validate afterLLMError action.\n */\nexport function validateAfterLLMErrorAction(action: AfterLLMErrorAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterLLMError\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"rethrow\" && actionType !== \"recover\") {\n throw new HookValidationError(\n \"afterLLMError\",\n `Invalid action type: ${actionType}. Must be 'rethrow' or 'recover'`,\n );\n }\n\n if (actionType === \"recover\" && !action.fallbackResponse) {\n throw new HookValidationError(\n \"afterLLMError\",\n \"When action is 'recover', fallbackResponse is required\",\n );\n }\n}\n\n/**\n * Validate beforeGadgetExecution action.\n */\nexport function validateBeforeGadgetExecutionAction(action: BeforeGadgetExecutionAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"proceed\" && actionType !== \"skip\") {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n );\n }\n\n if (actionType === \"skip\" && !action.syntheticResult) {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n \"When action is 'skip', syntheticResult is required\",\n );\n }\n}\n\n/**\n * Validate afterGadgetExecution action.\n */\nexport function validateAfterGadgetExecutionAction(action: AfterGadgetExecutionAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"continue\" && actionType !== \"recover\") {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n `Invalid action type: ${actionType}. Must be 'continue' or 'recover'`,\n );\n }\n\n if (actionType === \"recover\" && !action.fallbackResult) {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n \"When action is 'recover', fallbackResult is required\",\n );\n }\n}\n","import type { ZodTypeAny } from \"zod\";\n\n/**\n * Helper to safely access Zod's internal _def structure.\n * Zod's _def is not publicly typed, so we cast through unknown.\n */\nfunction getDef(schema: ZodTypeAny): Record<string, unknown> {\n return schema._def as unknown as Record<string, unknown>;\n}\n\n/**\n * Type hints that guide value coercion.\n * - 'string': Keep the value as a string, no coercion\n * - 'number': Coerce to number if possible\n * - 'boolean': Coerce to boolean if possible\n * - 'unknown': Use default auto-coercion logic (backwards compatible)\n */\nexport type TypeHint = \"string\" | \"number\" | \"boolean\" | \"unknown\";\n\n/**\n * Get the type name from a Zod schema's _def.\n * Handles both Zod v3 (typeName) and Zod v4 (type) structures.\n * Note: We cast _def to any since Zod's internal structure isn't publicly typed.\n */\nfunction getTypeName(schema: ZodTypeAny): string | undefined {\n const def = getDef(schema);\n // Zod v4 uses _def.type, Zod v3 uses _def.typeName\n return (def?.type ?? def?.typeName) as string | undefined;\n}\n\n/**\n * Get the shape from a Zod object schema's _def.\n * Handles both Zod v3 (shape()) and Zod v4 (shape) structures.\n * Note: We cast _def to any since Zod's internal structure isn't publicly typed.\n */\nfunction getShape(\n schema: ZodTypeAny\n): Record<string, ZodTypeAny> | undefined {\n const def = getDef(schema);\n // Zod v4 uses _def.shape directly, Zod v3 uses _def.shape()\n if (typeof def?.shape === \"function\") {\n return (def.shape as () => Record<string, ZodTypeAny>)();\n }\n return def?.shape as Record<string, ZodTypeAny> | undefined;\n}\n\n/**\n * Introspects Zod schemas to determine expected types at JSON pointer paths.\n *\n * This enables schema-aware type coercion - instead of blindly converting\n * \"1\" to a number, the parser can check if the schema expects a string\n * and preserve the original value.\n *\n * Design decisions:\n * - Union types prefer string over other primitives (preserves LLM intent)\n * - Transform/effect schemas return 'unknown' (let Zod handle transformation)\n * - Invalid paths return 'unknown' (fall back to auto-coercion)\n *\n * @example\n * ```typescript\n * const schema = z.object({\n * id: z.string(),\n * count: z.number(),\n * config: z.object({ timeout: z.number() })\n * });\n *\n * const introspector = new SchemaIntrospector(schema);\n * introspector.getTypeAtPath(\"id\"); // 'string'\n * introspector.getTypeAtPath(\"count\"); // 'number'\n * introspector.getTypeAtPath(\"config/timeout\"); // 'number'\n * introspector.getTypeAtPath(\"unknown\"); // 'unknown'\n * ```\n */\nexport class SchemaIntrospector {\n private readonly schema: ZodTypeAny;\n private readonly cache = new Map<string, TypeHint>();\n\n constructor(schema: ZodTypeAny) {\n this.schema = schema;\n }\n\n /**\n * Get the expected type at a JSON pointer path.\n *\n * @param pointer - JSON pointer path without leading / (e.g., \"config/timeout\", \"items/0\")\n * @returns Type hint for coercion decision\n */\n getTypeAtPath(pointer: string): TypeHint {\n // Check cache first\n const cached = this.cache.get(pointer);\n if (cached !== undefined) {\n return cached;\n }\n\n const result = this.resolveTypeAtPath(pointer);\n this.cache.set(pointer, result);\n return result;\n }\n\n /**\n * Internal method to resolve type at path without caching.\n */\n private resolveTypeAtPath(pointer: string): TypeHint {\n // Empty pointer means the root - shouldn't happen for parameters\n if (!pointer) {\n return this.getBaseType(this.schema);\n }\n\n const segments = pointer.split(\"/\");\n let current: ZodTypeAny = this.schema;\n\n for (const segment of segments) {\n // Unwrap any wrapper types (optional, default, nullable, etc.)\n current = this.unwrapSchema(current);\n\n // Navigate based on schema type\n const typeName = getTypeName(current);\n\n if (typeName === \"object\" || typeName === \"ZodObject\") {\n // Navigate into object property\n const shape = getShape(current);\n if (!shape || !(segment in shape)) {\n return \"unknown\"; // Property doesn't exist in schema\n }\n current = shape[segment];\n } else if (typeName === \"array\" || typeName === \"ZodArray\") {\n // For array indices, get element type\n if (!/^\\d+$/.test(segment)) {\n return \"unknown\"; // Not a numeric index\n }\n // Zod v4 uses _def.element, Zod v3 uses _def.type\n const def = getDef(current);\n const elementType = (def?.element ?? def?.type) as ZodTypeAny | undefined;\n if (!elementType) {\n return \"unknown\";\n }\n current = elementType;\n } else if (typeName === \"tuple\" || typeName === \"ZodTuple\") {\n // For tuples, get element at specific index\n if (!/^\\d+$/.test(segment)) {\n return \"unknown\";\n }\n const index = parseInt(segment, 10);\n const def = getDef(current);\n const items = def?.items as ZodTypeAny[] | undefined;\n if (!items || index >= items.length) {\n return \"unknown\";\n }\n current = items[index];\n } else if (typeName === \"record\" || typeName === \"ZodRecord\") {\n // For records, all values have the same type\n // Zod v4 uses _def.valueType, Zod v3 uses _def.valueType\n const def = getDef(current);\n const valueType = def?.valueType as ZodTypeAny | undefined;\n if (!valueType) {\n return \"unknown\";\n }\n current = valueType;\n } else {\n // Can't navigate further (e.g., trying to access property on a string)\n return \"unknown\";\n }\n }\n\n // Get the base type of the final schema\n return this.getBaseType(current);\n }\n\n /**\n * Unwrap schema modifiers (optional, default, nullable, branded, etc.)\n * to get to the underlying type.\n */\n private unwrapSchema(schema: ZodTypeAny): ZodTypeAny {\n let current = schema;\n let iterations = 0;\n const maxIterations = 20; // Prevent infinite loops\n\n while (iterations < maxIterations) {\n const typeName = getTypeName(current);\n\n // Check for wrapper types (both Zod v3 and v4 naming)\n const wrapperTypes = [\n \"optional\",\n \"nullable\",\n \"default\",\n \"catch\",\n \"branded\",\n \"readonly\",\n \"pipeline\",\n \"ZodOptional\",\n \"ZodNullable\",\n \"ZodDefault\",\n \"ZodCatch\",\n \"ZodBranded\",\n \"ZodReadonly\",\n \"ZodPipeline\",\n ];\n\n if (typeName && wrapperTypes.includes(typeName)) {\n const def = getDef(current);\n const inner = (def?.innerType ?? def?.in ?? def?.type) as ZodTypeAny | undefined;\n if (!inner || inner === current) break;\n current = inner;\n iterations++;\n continue;\n }\n\n break;\n }\n\n return current;\n }\n\n /**\n * Get the primitive type hint from an unwrapped schema.\n */\n private getBaseType(schema: ZodTypeAny): TypeHint {\n const unwrapped = this.unwrapSchema(schema);\n const typeName = getTypeName(unwrapped);\n\n // Map both Zod v3 (ZodString) and v4 (string) type names\n switch (typeName) {\n // Primitive types\n case \"string\":\n case \"ZodString\":\n return \"string\";\n case \"number\":\n case \"ZodNumber\":\n case \"bigint\":\n case \"ZodBigInt\":\n return \"number\";\n case \"boolean\":\n case \"ZodBoolean\":\n return \"boolean\";\n\n // Literal types - check the literal value type\n case \"literal\":\n case \"ZodLiteral\": {\n // Zod v4 uses _def.values (array), Zod v3 uses _def.value\n const def = getDef(unwrapped);\n const values = def?.values as unknown[] | undefined;\n const value = values?.[0] ?? def?.value;\n if (typeof value === \"string\") return \"string\";\n if (typeof value === \"number\" || typeof value === \"bigint\")\n return \"number\";\n if (typeof value === \"boolean\") return \"boolean\";\n return \"unknown\";\n }\n\n // Enum - always string keys\n case \"enum\":\n case \"ZodEnum\":\n case \"nativeEnum\":\n case \"ZodNativeEnum\":\n return \"string\";\n\n // Union - return 'unknown' to let auto-coercion decide\n // Since multiple types are valid, we can't definitively say what the LLM intended\n // Auto-coercion will handle common cases (numbers, booleans) appropriately\n case \"union\":\n case \"ZodUnion\":\n return \"unknown\";\n\n // Discriminated union - complex, return unknown\n case \"discriminatedUnion\":\n case \"ZodDiscriminatedUnion\":\n return \"unknown\";\n\n // Intersection - check both sides\n case \"intersection\":\n case \"ZodIntersection\": {\n const def = getDef(unwrapped);\n const left = def?.left as ZodTypeAny | undefined;\n const right = def?.right as ZodTypeAny | undefined;\n if (!left || !right) return \"unknown\";\n\n const leftType = this.getBaseType(left);\n const rightType = this.getBaseType(right);\n\n // If both are the same type, return it\n if (leftType === rightType) return leftType;\n // If one is string, prefer string\n if (leftType === \"string\" || rightType === \"string\") return \"string\";\n // Otherwise return unknown (complex intersection)\n return \"unknown\";\n }\n\n // Effects/transforms - return unknown to let Zod handle it\n case \"effects\":\n case \"ZodEffects\":\n // ZodEffects wraps transforms, refinements, etc.\n // The transform expects input in original format, so don't coerce\n return \"unknown\";\n\n // Lazy - can't resolve without evaluating\n case \"lazy\":\n case \"ZodLazy\":\n return \"unknown\";\n\n // Complex types - return unknown\n case \"object\":\n case \"ZodObject\":\n case \"array\":\n case \"ZodArray\":\n case \"tuple\":\n case \"ZodTuple\":\n case \"record\":\n case \"ZodRecord\":\n case \"map\":\n case \"ZodMap\":\n case \"set\":\n case \"ZodSet\":\n case \"function\":\n case \"ZodFunction\":\n case \"promise\":\n case \"ZodPromise\":\n case \"date\":\n case \"ZodDate\":\n return \"unknown\";\n\n // Unknown/any/never/void/undefined/null\n case \"unknown\":\n case \"ZodUnknown\":\n case \"any\":\n case \"ZodAny\":\n case \"never\":\n case \"ZodNever\":\n case \"void\":\n case \"ZodVoid\":\n case \"undefined\":\n case \"ZodUndefined\":\n case \"null\":\n case \"ZodNull\":\n return \"unknown\";\n\n default:\n return \"unknown\";\n }\n }\n}\n","import type { ZodTypeAny } from \"zod\";\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { SchemaIntrospector, type TypeHint } from \"./schema-introspector.js\";\n\nexport interface BlockParseOptions {\n /** Prefix that declares an argument. Default: \"!!!ARG:\" */\n argPrefix?: string;\n /** Optional Zod schema for schema-aware type coercion */\n schema?: ZodTypeAny;\n}\n\n/**\n * Parse block format parameters into an object.\n *\n * Block format uses !!!ARG:pointer syntax where pointer is a JSON Pointer\n * path (without leading /) that defines where to place the value.\n *\n * Example input:\n * ```\n * !!!ARG:filename\n * calculator.ts\n * !!!ARG:config/timeout\n * 30\n * !!!ARG:items/0\n * first\n * ```\n *\n * Produces:\n * ```json\n * {\n * \"filename\": \"calculator.ts\",\n * \"config\": { \"timeout\": 30 },\n * \"items\": [\"first\"]\n * }\n * ```\n *\n * Single-line values are automatically coerced:\n * - \"true\" / \"false\" → boolean\n * - Numeric strings → number\n * - Multiline values always stay as strings (for code/content)\n *\n * @param content - Raw parameter content (after gadget name line, before end marker)\n * @param options - Parser options\n * @returns Parsed parameters object with coerced values\n * @throws Error if duplicate pointers or invalid array indices\n */\nexport function parseBlockParams(\n content: string,\n options?: BlockParseOptions\n): Record<string, unknown> {\n const argPrefix = options?.argPrefix ?? GADGET_ARG_PREFIX;\n const result: Record<string, unknown> = {};\n const seenPointers = new Set<string>();\n\n // Create schema introspector if schema is provided\n const introspector = options?.schema\n ? new SchemaIntrospector(options.schema)\n : undefined;\n\n // Split content by arg prefix to get individual arg entries\n // First element will be empty or whitespace before first arg\n const parts = content.split(argPrefix);\n\n for (let i = 1; i < parts.length; i++) {\n const part = parts[i];\n\n // Find the pointer (first line) and value (rest)\n const newlineIndex = part.indexOf(\"\\n\");\n if (newlineIndex === -1) {\n // Arg with no value (just the pointer line)\n const pointer = part.trim();\n if (pointer) {\n if (seenPointers.has(pointer)) {\n throw new Error(`Duplicate pointer: ${pointer}`);\n }\n seenPointers.add(pointer);\n setByPointer(result, pointer, \"\", introspector);\n }\n continue;\n }\n\n const pointer = part.substring(0, newlineIndex).trim();\n let value = part.substring(newlineIndex + 1);\n\n // Strip single trailing newline if present (per spec)\n if (value.endsWith(\"\\n\")) {\n value = value.slice(0, -1);\n }\n\n if (!pointer) {\n continue; // Skip empty pointers\n }\n\n if (seenPointers.has(pointer)) {\n throw new Error(`Duplicate pointer: ${pointer}`);\n }\n seenPointers.add(pointer);\n\n setByPointer(result, pointer, value, introspector);\n }\n\n return result;\n}\n\n/**\n * Coerce a string value to its appropriate primitive type.\n *\n * When an `expectedType` hint is provided (from schema introspection), the coercion\n * respects the schema's expected type:\n * - 'string': Keep value as string, no coercion\n * - 'number': Coerce to number if valid\n * - 'boolean': Coerce to boolean if \"true\"/\"false\"\n * - 'unknown': Use auto-coercion logic (backwards compatible)\n *\n * Without a type hint (undefined), uses auto-coercion:\n * - \"true\" / \"false\" → boolean\n * - Numeric strings → number\n * - Everything else stays string\n *\n * Multiline values are never coerced (likely code/content).\n *\n * @param value - The string value to coerce\n * @param expectedType - Optional type hint from schema introspection\n * @returns Coerced value\n */\nfunction coerceValue(\n value: string,\n expectedType?: TypeHint\n): string | number | boolean {\n // Don't coerce multiline values - they're likely code/content\n if (value.includes(\"\\n\")) {\n return value;\n }\n\n const trimmed = value.trim();\n\n // If schema provides a type hint, respect it\n if (expectedType === \"string\") {\n // Keep as string - no coercion at all\n return value;\n }\n\n if (expectedType === \"boolean\") {\n // Only coerce recognized boolean strings\n if (trimmed === \"true\") return true;\n if (trimmed === \"false\") return false;\n // Invalid boolean - keep as string for Zod to report error\n return value;\n }\n\n if (expectedType === \"number\") {\n // Attempt to coerce to number\n const num = Number(trimmed);\n if (!isNaN(num) && isFinite(num) && trimmed !== \"\") {\n return num;\n }\n // Invalid number - keep as string for Zod to report error\n return value;\n }\n\n // expectedType === 'unknown' or undefined: use auto-coercion logic\n // This maintains backwards compatibility when no schema is provided\n // or when schema introspection can't determine the type\n\n // Boolean coercion\n if (trimmed === \"true\") return true;\n if (trimmed === \"false\") return false;\n\n // Number coercion - only for values that look clearly numeric\n // Avoid coercing things like \"123abc\" or empty strings\n if (trimmed !== \"\" && /^-?\\d+(\\.\\d+)?$/.test(trimmed)) {\n const num = Number(trimmed);\n if (!isNaN(num) && isFinite(num)) {\n return num;\n }\n }\n\n return value;\n}\n\n/**\n * Set a value in an object using a JSON Pointer path (without leading /).\n *\n * Handles:\n * - Simple keys: \"name\" → { name: value }\n * - Nested paths: \"config/timeout\" → { config: { timeout: value } }\n * - Array indices: \"items/0\" → { items: [value] }\n *\n * Values are coerced based on the schema's expected type when an introspector\n * is provided. Without a schema, falls back to auto-coercion (backwards compatible).\n *\n * @param obj - Target object to modify\n * @param pointer - JSON Pointer path without leading /\n * @param value - Value to set (string that may be coerced)\n * @param introspector - Optional schema introspector for type-aware coercion\n * @throws Error if array index gaps detected\n */\nfunction setByPointer(\n obj: Record<string, unknown>,\n pointer: string,\n value: string,\n introspector?: SchemaIntrospector\n): void {\n const segments = pointer.split(\"/\");\n let current: Record<string, unknown> | unknown[] = obj;\n\n for (let i = 0; i < segments.length - 1; i++) {\n const segment = segments[i];\n const nextSegment = segments[i + 1];\n const nextIsArrayIndex = /^\\d+$/.test(nextSegment);\n\n if (Array.isArray(current)) {\n const index = parseInt(segment, 10);\n if (isNaN(index) || index < 0) {\n throw new Error(`Invalid array index: ${segment}`);\n }\n // Validate no gaps\n if (index > current.length) {\n throw new Error(`Array index gap: expected ${current.length}, got ${index}`);\n }\n if (current[index] === undefined) {\n current[index] = nextIsArrayIndex ? [] : {};\n }\n current = current[index] as Record<string, unknown> | unknown[];\n } else {\n // current is an object\n const rec = current as Record<string, unknown>;\n if (rec[segment] === undefined) {\n rec[segment] = nextIsArrayIndex ? [] : {};\n }\n current = rec[segment] as Record<string, unknown> | unknown[];\n }\n }\n\n // Set the final value\n const lastSegment = segments[segments.length - 1];\n\n // Get expected type from schema if available, then coerce accordingly\n const expectedType = introspector?.getTypeAtPath(pointer);\n const coercedValue = coerceValue(value, expectedType);\n\n if (Array.isArray(current)) {\n const index = parseInt(lastSegment, 10);\n if (isNaN(index) || index < 0) {\n throw new Error(`Invalid array index: ${lastSegment}`);\n }\n // Validate no gaps\n if (index > current.length) {\n throw new Error(`Array index gap: expected ${current.length}, got ${index}`);\n }\n current[index] = coercedValue;\n } else {\n (current as Record<string, unknown>)[lastSegment] = coercedValue;\n }\n}\n","import type { ZodError } from \"zod\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { BaseGadget } from \"./gadget.js\";\n\nexport interface ErrorFormatterOptions {\n /** Custom argument prefix for block format examples. Default: \"!!!ARG:\" */\n argPrefix?: string;\n /** Custom start prefix for block format examples. Default: \"!!!GADGET_START:\" */\n startPrefix?: string;\n /** Custom end prefix for block format examples. Default: \"!!!GADGET_END\" */\n endPrefix?: string;\n}\n\n/**\n * Formats gadget errors with helpful context for LLMs.\n *\n * This class generates error messages that include:\n * - Clear error description\n * - Full gadget usage instructions (via getInstruction())\n * - Block format reference for parse errors\n *\n * The goal is to help LLMs self-correct on subsequent invocation attempts.\n */\nexport class GadgetErrorFormatter {\n private readonly argPrefix: string;\n private readonly startPrefix: string;\n private readonly endPrefix: string;\n\n constructor(options: ErrorFormatterOptions = {}) {\n this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;\n this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;\n this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;\n }\n\n /**\n * Format a Zod validation error with full gadget instructions.\n *\n * @param gadgetName - Name of the gadget that was called\n * @param zodError - The Zod validation error\n * @param gadget - The gadget instance (for generating instructions)\n * @returns Formatted error message with usage instructions\n */\n formatValidationError(gadgetName: string, zodError: ZodError, gadget: BaseGadget): string {\n const parts: string[] = [];\n\n // Error header\n parts.push(`Error: Invalid parameters for '${gadgetName}':`);\n\n // Format each validation issue\n for (const issue of zodError.issues) {\n const path = issue.path.join(\".\") || \"root\";\n parts.push(` - ${path}: ${issue.message}`);\n }\n\n // Add gadget usage instructions\n parts.push(\"\");\n parts.push(\"Gadget Usage:\");\n parts.push(gadget.getInstruction(this.argPrefix));\n\n return parts.join(\"\\n\");\n }\n\n /**\n * Format a parse error with block format reference.\n *\n * @param gadgetName - Name of the gadget that was called\n * @param parseError - The parse error message\n * @param gadget - The gadget instance if found (for generating instructions)\n * @returns Formatted error message with format reference\n */\n formatParseError(gadgetName: string, parseError: string, gadget: BaseGadget | undefined): string {\n const parts: string[] = [];\n\n // Error header\n parts.push(`Error: Failed to parse parameters for '${gadgetName}':`);\n parts.push(` ${parseError}`);\n\n // Add gadget usage instructions if gadget exists\n if (gadget) {\n parts.push(\"\");\n parts.push(\"Gadget Usage:\");\n parts.push(gadget.getInstruction(this.argPrefix));\n }\n\n // Always add block format reference\n parts.push(\"\");\n parts.push(\"Block Format Reference:\");\n parts.push(` ${this.startPrefix}${gadgetName}`);\n parts.push(` ${this.argPrefix}parameterName`);\n parts.push(\" parameter value here\");\n parts.push(` ${this.endPrefix}`);\n\n return parts.join(\"\\n\");\n }\n\n /**\n * Format a registry error (gadget not found) with available gadgets list.\n *\n * @param gadgetName - Name of the gadget that was not found\n * @param availableGadgets - List of available gadget names\n * @returns Formatted error message with available gadgets\n */\n formatRegistryError(gadgetName: string, availableGadgets: string[]): string {\n const parts: string[] = [];\n\n // Error header\n parts.push(`Error: Gadget '${gadgetName}' not found.`);\n\n // List available gadgets\n if (availableGadgets.length > 0) {\n parts.push(\"\");\n parts.push(`Available gadgets: ${availableGadgets.join(\", \")}`);\n } else {\n parts.push(\"\");\n parts.push(\"No gadgets are currently registered.\");\n }\n\n return parts.join(\"\\n\");\n }\n}\n\n/**\n * Create a pre-configured error formatter instance.\n *\n * @param options - Formatter options\n * @returns Configured GadgetErrorFormatter instance\n */\nexport function createErrorFormatter(options: ErrorFormatterOptions = {}): GadgetErrorFormatter {\n return new GadgetErrorFormatter(options);\n}\n","/**\n * Exception that gadgets can throw to signal the agent loop should terminate.\n *\n * When a gadget throws this exception, the agent loop will:\n * 1. Complete the current iteration\n * 2. Return the exception message as the gadget's result\n * 3. Exit the loop instead of continuing to the next iteration\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * class FinishGadget extends Gadget({\n * name: 'Finish',\n * description: 'Signals task completion',\n * schema: z.object({\n * message: z.string().optional(),\n * }),\n * }) {\n * execute(params: this['params']): string {\n * const message = params.message || 'Task completed';\n * throw new BreakLoopException(message);\n * }\n * }\n * ```\n */\nexport class BreakLoopException extends Error {\n constructor(message?: string) {\n super(message ?? \"Agent loop terminated by gadget\");\n this.name = \"BreakLoopException\";\n }\n}\n\n/**\n * Exception that gadgets can throw to request human input during execution.\n *\n * When a gadget throws this exception, the agent loop will:\n * 1. Pause execution and wait for human input\n * 2. If `onHumanInputRequired` callback is provided, call it and await the answer\n * 3. Return the user's answer as the gadget's result\n * 4. Continue the loop with the answer added to conversation history\n *\n * If no callback is provided, the loop will yield a `human_input_required` event\n * and the caller must handle it externally.\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * class AskUserGadget extends Gadget({\n * name: 'AskUser',\n * description: 'Ask the user a question and get their answer',\n * schema: z.object({\n * question: z.string().min(1, 'Question is required'),\n * }),\n * }) {\n * execute(params: this['params']): string {\n * throw new HumanInputException(params.question);\n * }\n * }\n * ```\n */\nexport class HumanInputException extends Error {\n public readonly question: string;\n\n constructor(question: string) {\n super(`Human input required: ${question}`);\n this.name = \"HumanInputException\";\n this.question = question;\n }\n}\n\n/**\n * Exception thrown when a gadget execution exceeds its timeout limit.\n *\n * When a gadget's execution time exceeds either:\n * - The gadget's own `timeoutMs` property, or\n * - The global `defaultGadgetTimeoutMs` configured in runtime/agent loop options\n *\n * The executor will automatically throw this exception and return it as an error.\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * class SlowApiGadget extends Gadget({\n * name: 'SlowApi',\n * description: 'Calls a slow external API',\n * timeoutMs: 5000, // 5 second timeout\n * schema: z.object({\n * endpoint: z.string(),\n * }),\n * }) {\n * async execute(params: this['params']): Promise<string> {\n * // If this takes longer than 5 seconds, execution will be aborted\n * const response = await fetch(params.endpoint);\n * return await response.text();\n * }\n * }\n * ```\n */\nexport class TimeoutException extends Error {\n public readonly timeoutMs: number;\n public readonly gadgetName: string;\n\n constructor(gadgetName: string, timeoutMs: number) {\n super(`Gadget '${gadgetName}' execution exceeded timeout of ${timeoutMs}ms`);\n this.name = \"TimeoutException\";\n this.gadgetName = gadgetName;\n this.timeoutMs = timeoutMs;\n }\n}\n","import { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { StreamEvent } from \"./types.js\";\nimport { parseBlockParams } from \"./block-params.js\";\n\nexport type ParameterFormat = \"block\";\n\n\n/**\n * Strip markdown code fences from parameter content.\n * LLMs sometimes wrap their parameters in ```toml, ```yaml, ```json, or plain ``` blocks.\n * This function removes those fences to allow successful parsing.\n *\n * @internal Exported for testing only\n */\nexport function stripMarkdownFences(content: string): string {\n let cleaned = content.trim();\n\n // Pattern: ```toml, ```yaml, ```json, or just ``` at start (case-insensitive)\n const openingFence = /^```(?:toml|yaml|json)?\\s*\\n/i;\n // Pattern: ``` at end (with optional preceding newline)\n const closingFence = /\\n?```\\s*$/;\n\n // Strip opening fence if present\n cleaned = cleaned.replace(openingFence, \"\");\n // Strip closing fence if present\n cleaned = cleaned.replace(closingFence, \"\");\n\n return cleaned.trim();\n}\n\nexport interface StreamParserOptions {\n startPrefix?: string;\n endPrefix?: string;\n /** Prefix for block format arguments. Default: \"!!!ARG:\" */\n argPrefix?: string;\n}\n\n// Global counter for generating unique invocation IDs across all parser instances\nlet globalInvocationCounter = 0;\n\n/**\n * Reset the global invocation counter. Only use this in tests!\n * @internal\n */\nexport function resetGlobalInvocationCounter(): void {\n globalInvocationCounter = 0;\n}\n\nexport class StreamParser {\n private buffer = \"\";\n private lastReportedTextLength = 0;\n private readonly startPrefix: string;\n private readonly endPrefix: string;\n private readonly argPrefix: string;\n\n constructor(options: StreamParserOptions = {}) {\n this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;\n this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;\n this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;\n }\n\n private takeTextUntil(index: number): string | undefined {\n if (index <= this.lastReportedTextLength) {\n return undefined;\n }\n\n const segment = this.buffer.slice(this.lastReportedTextLength, index);\n this.lastReportedTextLength = index;\n\n return segment.trim().length > 0 ? segment : undefined;\n }\n\n /**\n * Parse gadget name, handling both old format (name:invocationId) and new format (just name).\n * For new format, generates a unique invocation ID.\n */\n private parseGadgetName(gadgetName: string): { actualName: string; invocationId: string } {\n if (gadgetName.includes(\":\")) {\n // Old format: gadgetName:invocationId - support for backward compatibility\n const parts = gadgetName.split(\":\");\n return { actualName: parts[0], invocationId: parts[1] };\n }\n // New format: just gadget name, generate unique ID\n return { actualName: gadgetName, invocationId: `gadget_${++globalInvocationCounter}` };\n }\n\n /**\n * Extract the error message from a parse error.\n * Preserves full message since the error formatter adds contextual help\n * that benefits from precise, detailed error information.\n */\n private extractParseError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n }\n\n /**\n * Parse parameter string using block format\n */\n private parseParameters(raw: string): {\n parameters?: Record<string, unknown>;\n parseError?: string;\n } {\n // Strip markdown code fences if LLM wrapped the parameters\n const cleaned = stripMarkdownFences(raw);\n\n try {\n return { parameters: parseBlockParams(cleaned, { argPrefix: this.argPrefix }) };\n } catch (error) {\n return { parseError: this.extractParseError(error) };\n }\n }\n\n // Feed a chunk of text and get parsed events\n *feed(chunk: string): Generator<StreamEvent> {\n this.buffer += chunk;\n\n let startIndex = 0;\n while (true) {\n // Find next gadget start marker\n const partStartIndex = this.buffer.indexOf(this.startPrefix, startIndex);\n if (partStartIndex === -1) break;\n\n // Yield any text before the gadget\n const textBefore = this.takeTextUntil(partStartIndex);\n if (textBefore !== undefined) {\n yield { type: \"text\", content: textBefore };\n }\n\n // Extract gadget name (no more invocation ID)\n const metadataStartIndex = partStartIndex + this.startPrefix.length;\n const metadataEndIndex = this.buffer.indexOf(\"\\n\", metadataStartIndex);\n if (metadataEndIndex === -1) break; // Wait for more data\n\n const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);\n\n const contentStartIndex = metadataEndIndex + 1;\n\n let partEndIndex: number;\n let endMarkerLength = 0;\n\n if (gadgetName.includes(\":\")) {\n // Old format - look for old format end marker\n const oldEndMarker = `${this.endPrefix + actualGadgetName}:${invocationId}`;\n partEndIndex = this.buffer.indexOf(oldEndMarker, contentStartIndex);\n if (partEndIndex === -1) break; // Wait for more data\n endMarkerLength = oldEndMarker.length;\n } else {\n // New format - look for end marker OR next start marker (implicit end)\n // If a next gadget starts BEFORE an end marker, use that as implicit terminator\n\n // Look for next gadget start (potential implicit end)\n const nextStartPos = this.buffer.indexOf(this.startPrefix, contentStartIndex);\n\n // Look for proper end marker\n let validEndPos = -1;\n let searchPos = contentStartIndex;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const endPos = this.buffer.indexOf(this.endPrefix, searchPos);\n if (endPos === -1) break;\n\n // Check if this is a standalone end marker or part of old format\n const afterEnd = this.buffer.substring(endPos + this.endPrefix.length);\n if (\n afterEnd.startsWith(\"\\n\") ||\n afterEnd.startsWith(\"\\r\") ||\n afterEnd.startsWith(this.startPrefix) ||\n afterEnd.length === 0\n ) {\n // It's a standalone end marker\n validEndPos = endPos;\n break;\n } else {\n // It might be old format, skip this one\n searchPos = endPos + this.endPrefix.length;\n }\n }\n\n // Decide which terminator to use:\n // - If next start comes before end marker, use next start (implicit end)\n // - Otherwise use the end marker if found\n if (nextStartPos !== -1 && (validEndPos === -1 || nextStartPos < validEndPos)) {\n // Found next gadget start before any end marker - implicit end\n partEndIndex = nextStartPos;\n endMarkerLength = 0; // Don't consume the next start marker\n } else if (validEndPos !== -1) {\n // Found proper end marker\n partEndIndex = validEndPos;\n endMarkerLength = this.endPrefix.length;\n } else {\n // Neither end marker nor next start found - wait for more data\n break;\n }\n }\n\n // Extract parameters\n const parametersRaw = this.buffer.substring(contentStartIndex, partEndIndex).trim();\n\n // Parse parameters according to configured format\n const { parameters, parseError } = this.parseParameters(parametersRaw);\n\n yield {\n type: \"gadget_call\",\n call: {\n gadgetName: actualGadgetName,\n invocationId,\n parametersRaw,\n parameters,\n parseError,\n },\n };\n\n // Move past this gadget\n startIndex = partEndIndex + endMarkerLength;\n\n this.lastReportedTextLength = startIndex;\n }\n\n // Keep unprocessed data in buffer\n if (startIndex > 0) {\n this.buffer = this.buffer.substring(startIndex);\n this.lastReportedTextLength = 0;\n }\n }\n\n // Finalize parsing and return remaining text or incomplete gadgets\n *finalize(): Generator<StreamEvent> {\n // Check if there's an incomplete gadget in the buffer\n const startIndex = this.buffer.indexOf(this.startPrefix, this.lastReportedTextLength);\n\n if (startIndex !== -1) {\n // There's an incomplete gadget - try to parse it\n const textBefore = this.takeTextUntil(startIndex);\n if (textBefore !== undefined) {\n yield { type: \"text\", content: textBefore };\n }\n\n // Extract gadget name\n const metadataStartIndex = startIndex + this.startPrefix.length;\n const metadataEndIndex = this.buffer.indexOf(\"\\n\", metadataStartIndex);\n\n if (metadataEndIndex !== -1) {\n const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);\n const contentStartIndex = metadataEndIndex + 1;\n\n // Extract parameters (everything after the newline to end of buffer)\n const parametersRaw = this.buffer.substring(contentStartIndex).trim();\n\n const { parameters, parseError } = this.parseParameters(parametersRaw);\n\n yield {\n type: \"gadget_call\",\n call: {\n gadgetName: actualGadgetName,\n invocationId,\n parametersRaw: parametersRaw,\n parameters,\n parseError,\n },\n };\n\n return;\n }\n }\n\n // No incomplete gadget - just emit remaining text\n const remainingText = this.takeTextUntil(this.buffer.length);\n if (remainingText !== undefined) {\n yield { type: \"text\", content: remainingText };\n }\n }\n\n // Reset parser state (note: global invocation counter is NOT reset to ensure unique IDs)\n reset(): void {\n this.buffer = \"\";\n this.lastReportedTextLength = 0;\n }\n}\n","import type { ILogObj, Logger } from \"tslog\";\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { parseBlockParams } from \"./block-params.js\";\nimport { GadgetErrorFormatter, type ErrorFormatterOptions } from \"./error-formatter.js\";\nimport { BreakLoopException, HumanInputException, TimeoutException } from \"./exceptions.js\";\nimport { stripMarkdownFences } from \"./parser.js\";\nimport type { GadgetRegistry } from \"./registry.js\";\nimport type { GadgetExecutionResult, ParsedGadgetCall } from \"./types.js\";\n\nexport class GadgetExecutor {\n private readonly logger: Logger<ILogObj>;\n private readonly errorFormatter: GadgetErrorFormatter;\n private readonly argPrefix: string;\n\n constructor(\n private readonly registry: GadgetRegistry,\n private readonly onHumanInputRequired?: (question: string) => Promise<string>,\n logger?: Logger<ILogObj>,\n private readonly defaultGadgetTimeoutMs?: number,\n errorFormatterOptions?: ErrorFormatterOptions,\n ) {\n this.logger = logger ?? createLogger({ name: \"llmist:executor\" });\n this.errorFormatter = new GadgetErrorFormatter(errorFormatterOptions);\n this.argPrefix = errorFormatterOptions?.argPrefix ?? GADGET_ARG_PREFIX;\n }\n\n /**\n * Creates a promise that rejects with a TimeoutException after the specified timeout.\n */\n private createTimeoutPromise(gadgetName: string, timeoutMs: number): Promise<never> {\n return new Promise((_, reject) => {\n setTimeout(() => {\n reject(new TimeoutException(gadgetName, timeoutMs));\n }, timeoutMs);\n });\n }\n\n // Execute a gadget call asynchronously\n async execute(call: ParsedGadgetCall): Promise<GadgetExecutionResult> {\n const startTime = Date.now();\n\n this.logger.debug(\"Executing gadget\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters,\n });\n\n const rawParameters: Record<string, unknown> = call.parameters ?? {};\n let validatedParameters: Record<string, unknown> = rawParameters;\n\n try {\n // Check if gadget exists\n const gadget = this.registry.get(call.gadgetName);\n if (!gadget) {\n this.logger.error(\"Gadget not found\", { gadgetName: call.gadgetName });\n const availableGadgets = this.registry.getNames();\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n error: this.errorFormatter.formatRegistryError(call.gadgetName, availableGadgets),\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Check for parse errors\n if (call.parseError || !call.parameters) {\n this.logger.error(\"Gadget parameter parse error\", {\n gadgetName: call.gadgetName,\n parseError: call.parseError,\n rawParameters: call.parametersRaw,\n });\n const parseErrorMessage = call.parseError ?? \"Failed to parse parameters\";\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: {},\n error: this.errorFormatter.formatParseError(call.gadgetName, parseErrorMessage, gadget),\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Re-parse parameters with schema for type-aware coercion (Approach B)\n // This allows the parser to use the schema to determine correct types\n // (e.g., keeping \"1\" as string when schema expects z.string())\n // Only re-parse if:\n // 1. The raw content is in block format (contains configured arg prefix)\n // 2. Parameters weren't modified by an interceptor (compare with initial parse)\n let schemaAwareParameters: Record<string, unknown> = rawParameters;\n const hasBlockFormat = call.parametersRaw?.includes(this.argPrefix);\n if (gadget.parameterSchema && hasBlockFormat) {\n try {\n const cleanedRaw = stripMarkdownFences(call.parametersRaw);\n\n // First, parse without schema to get what initial parse would produce\n const initialParse = parseBlockParams(cleanedRaw, { argPrefix: this.argPrefix });\n\n // Check if parameters were modified by an interceptor\n // by comparing current parameters with what initial parse produces\n const parametersWereModified = !this.deepEquals(rawParameters, initialParse);\n\n if (parametersWereModified) {\n // Parameters were modified by an interceptor - keep the modifications\n this.logger.debug(\"Parameters modified by interceptor, skipping re-parse\", {\n gadgetName: call.gadgetName,\n });\n schemaAwareParameters = rawParameters;\n } else {\n // Re-parse with schema for type-aware coercion\n schemaAwareParameters = parseBlockParams(cleanedRaw, {\n argPrefix: this.argPrefix,\n schema: gadget.parameterSchema,\n });\n this.logger.debug(\"Re-parsed parameters with schema\", {\n gadgetName: call.gadgetName,\n original: rawParameters,\n schemaAware: schemaAwareParameters,\n });\n }\n } catch (error) {\n // If re-parsing fails, fall back to original parameters\n // This shouldn't happen if initial parse succeeded, but be safe\n this.logger.warn(\"Schema-aware re-parsing failed, using original parameters\", {\n gadgetName: call.gadgetName,\n error: error instanceof Error ? error.message : String(error),\n });\n schemaAwareParameters = rawParameters;\n }\n }\n\n if (gadget.parameterSchema) {\n const validationResult = gadget.parameterSchema.safeParse(schemaAwareParameters);\n if (!validationResult.success) {\n const validationError = this.errorFormatter.formatValidationError(\n call.gadgetName,\n validationResult.error,\n gadget,\n );\n this.logger.error(\"Gadget parameter validation failed\", {\n gadgetName: call.gadgetName,\n issueCount: validationResult.error.issues.length,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: schemaAwareParameters,\n error: validationError,\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n validatedParameters = validationResult.data as Record<string, unknown>;\n } else {\n // No schema - use the schema-aware parameters (which are same as raw if no schema)\n validatedParameters = schemaAwareParameters;\n }\n\n // Determine the timeout for this gadget\n // Priority: gadget's own timeoutMs > defaultGadgetTimeoutMs > no timeout\n const timeoutMs = gadget.timeoutMs ?? this.defaultGadgetTimeoutMs;\n\n // Execute gadget (handle both sync and async)\n let result: string;\n if (timeoutMs && timeoutMs > 0) {\n // Execute with timeout\n this.logger.debug(\"Executing gadget with timeout\", {\n gadgetName: call.gadgetName,\n timeoutMs,\n });\n result = await Promise.race([\n Promise.resolve(gadget.execute(validatedParameters)),\n this.createTimeoutPromise(call.gadgetName, timeoutMs),\n ]);\n } else {\n // Execute without timeout\n result = await Promise.resolve(gadget.execute(validatedParameters));\n }\n\n const executionTimeMs = Date.now() - startTime;\n this.logger.info(\"Gadget executed successfully\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n executionTimeMs,\n });\n\n this.logger.debug(\"Gadget result\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result,\n executionTimeMs,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result,\n executionTimeMs,\n };\n } catch (error) {\n // Check if this is a BreakLoopException\n if (error instanceof BreakLoopException) {\n this.logger.info(\"Gadget requested loop termination\", {\n gadgetName: call.gadgetName,\n message: error.message,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result: error.message,\n breaksLoop: true,\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Check if this is a TimeoutException\n if (error instanceof TimeoutException) {\n this.logger.error(\"Gadget execution timed out\", {\n gadgetName: call.gadgetName,\n timeoutMs: error.timeoutMs,\n executionTimeMs: Date.now() - startTime,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: error.message,\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Check if this is a HumanInputException\n if (error instanceof HumanInputException) {\n this.logger.info(\"Gadget requested human input\", {\n gadgetName: call.gadgetName,\n question: error.question,\n });\n\n // If callback is provided, call it and wait for answer\n if (this.onHumanInputRequired) {\n try {\n const answer = await this.onHumanInputRequired(error.question);\n this.logger.debug(\"Human input received\", {\n gadgetName: call.gadgetName,\n answerLength: answer.length,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result: answer,\n executionTimeMs: Date.now() - startTime,\n };\n } catch (inputError) {\n this.logger.error(\"Human input callback error\", {\n gadgetName: call.gadgetName,\n error: inputError instanceof Error ? inputError.message : String(inputError),\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: inputError instanceof Error ? inputError.message : String(inputError),\n executionTimeMs: Date.now() - startTime,\n };\n }\n }\n\n // No callback - return error since we can't get human input\n this.logger.warn(\"Human input required but no callback provided\", {\n gadgetName: call.gadgetName,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: \"Human input required but not available (stdin is not interactive)\",\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n const executionTimeMs = Date.now() - startTime;\n this.logger.error(\"Gadget execution failed\", {\n gadgetName: call.gadgetName,\n error: error instanceof Error ? error.message : String(error),\n executionTimeMs,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: error instanceof Error ? error.message : String(error),\n executionTimeMs,\n };\n }\n }\n\n // Execute multiple gadget calls in parallel\n async executeAll(calls: ParsedGadgetCall[]): Promise<GadgetExecutionResult[]> {\n return Promise.all(calls.map((call) => this.execute(call)));\n }\n\n /**\n * Deep equality check for objects/arrays.\n * Used to detect if parameters were modified by an interceptor.\n */\n private deepEquals(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a === null || b === null) return a === b;\n if (typeof a !== typeof b) return false;\n\n if (typeof a !== \"object\") return a === b;\n\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n return a.every((val, i) => this.deepEquals(val, b[i]));\n }\n\n const aObj = a as Record<string, unknown>;\n const bObj = b as Record<string, unknown>;\n\n const aKeys = Object.keys(aObj);\n const bKeys = Object.keys(bObj);\n\n if (aKeys.length !== bKeys.length) return false;\n\n return aKeys.every((key) => this.deepEquals(aObj[key], bObj[key]));\n }\n}\n","/**\n * StreamProcessor: The heart of the new hooks architecture.\n *\n * Replaces the complex wiring between Agent, ResponseProcessor, and GadgetRuntime.\n * Owns ALL stream processing and hook coordination with a clean, predictable flow.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMStreamChunk, TokenUsage } from \"../core/options.js\";\nimport { GadgetExecutor } from \"../gadgets/executor.js\";\nimport { StreamParser } from \"../gadgets/parser.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { GadgetExecutionResult, ParsedGadgetCall, StreamEvent } from \"../gadgets/types.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport {\n validateAfterGadgetExecutionAction,\n validateBeforeGadgetExecutionAction,\n} from \"./hook-validators.js\";\nimport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AgentHooks,\n BeforeGadgetExecutionAction,\n ChunkInterceptorContext,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetStartContext,\n} from \"./hooks.js\";\n\n/**\n * Configuration for the StreamProcessor.\n */\nexport interface StreamProcessorOptions {\n /** Current iteration number */\n iteration: number;\n\n /** Gadget registry for execution */\n registry: GadgetRegistry;\n\n /** Custom gadget start prefix */\n gadgetStartPrefix?: string;\n\n /** Custom gadget end prefix */\n gadgetEndPrefix?: string;\n\n /** Custom argument prefix for block format */\n gadgetArgPrefix?: string;\n\n /** Hooks for lifecycle events */\n hooks?: AgentHooks;\n\n /** Logger instance */\n logger?: Logger<ILogObj>;\n\n /** Callback for human input */\n onHumanInputRequired?: (question: string) => Promise<string>;\n\n /** Whether to stop on gadget errors */\n stopOnGadgetError?: boolean;\n\n /** Custom error continuation logic */\n shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n\n /** Default gadget timeout */\n defaultGadgetTimeoutMs?: number;\n}\n\n/**\n * Result of stream processing.\n */\nexport interface StreamProcessingResult {\n /** All emitted events */\n outputs: StreamEvent[];\n\n /** Whether the loop should break */\n shouldBreakLoop: boolean;\n\n /** Whether any gadgets were executed */\n didExecuteGadgets: boolean;\n\n /** LLM finish reason */\n finishReason: string | null;\n\n /** Token usage (including cached token counts when available) */\n usage?: TokenUsage;\n\n /** The raw accumulated response text */\n rawResponse: string;\n\n /** The final message (after interceptors) */\n finalMessage: string;\n}\n\n/**\n * StreamProcessor: Coordinates all stream processing and hook execution.\n *\n * Execution order:\n * 1. Raw chunk arrives from LLM\n * 2. Interceptor: interceptRawChunk (transform raw text)\n * 3. Observer: onStreamChunk (logging)\n * 4. Parse for gadgets\n * 5. If gadget found:\n * a. Interceptor: interceptGadgetParameters (transform params)\n * b. Controller: beforeGadgetExecution (can skip)\n * c. Observer: onGadgetExecutionStart\n * d. Execute gadget\n * e. Interceptor: interceptGadgetResult (transform result)\n * f. Controller: afterGadgetExecution (can provide fallback)\n * g. Observer: onGadgetExecutionComplete\n * 6. If text chunk:\n * a. Interceptor: interceptTextChunk (transform display text)\n * b. Yield to user\n * 7. Stream complete\n * 8. Interceptor: interceptAssistantMessage (transform final message)\n */\nexport class StreamProcessor {\n private readonly iteration: number;\n private readonly registry: GadgetRegistry;\n private readonly hooks: AgentHooks;\n private readonly logger: Logger<ILogObj>;\n private readonly parser: StreamParser;\n private readonly executor: GadgetExecutor;\n private readonly stopOnGadgetError: boolean;\n private readonly shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n\n private accumulatedText = \"\";\n private shouldStopExecution = false;\n private observerFailureCount = 0;\n\n constructor(options: StreamProcessorOptions) {\n this.iteration = options.iteration;\n this.registry = options.registry;\n this.hooks = options.hooks ?? {};\n this.logger = options.logger ?? createLogger({ name: \"llmist:stream-processor\" });\n this.stopOnGadgetError = options.stopOnGadgetError ?? true;\n this.shouldContinueAfterError = options.shouldContinueAfterError;\n\n this.parser = new StreamParser({\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n argPrefix: options.gadgetArgPrefix,\n });\n\n this.executor = new GadgetExecutor(\n options.registry,\n options.onHumanInputRequired,\n this.logger.getSubLogger({ name: \"executor\" }),\n options.defaultGadgetTimeoutMs,\n { argPrefix: options.gadgetArgPrefix },\n );\n }\n\n /**\n * Process an LLM stream and return structured results.\n */\n async process(stream: AsyncIterable<LLMStreamChunk>): Promise<StreamProcessingResult> {\n const outputs: StreamEvent[] = [];\n let finishReason: string | null = null;\n let usage: TokenUsage | undefined;\n let didExecuteGadgets = false;\n let shouldBreakLoop = false;\n\n // Process stream chunks\n for await (const chunk of stream) {\n // Capture metadata\n if (chunk.finishReason) finishReason = chunk.finishReason;\n if (chunk.usage) usage = chunk.usage;\n\n // Process text content if present\n let processedChunk = \"\";\n if (chunk.text) {\n // Step 1: Interceptor - Transform raw chunk\n processedChunk = chunk.text;\n if (this.hooks.interceptors?.interceptRawChunk) {\n const context: ChunkInterceptorContext = {\n iteration: this.iteration,\n accumulatedText: this.accumulatedText,\n logger: this.logger,\n };\n const intercepted = this.hooks.interceptors.interceptRawChunk(processedChunk, context);\n if (intercepted === null) {\n // Chunk suppressed\n processedChunk = \"\";\n } else {\n processedChunk = intercepted;\n }\n }\n\n // Accumulate text\n if (processedChunk) {\n this.accumulatedText += processedChunk;\n }\n }\n\n // Step 2: Observer - Observe chunk (called for text OR usage updates)\n if (this.hooks.observers?.onStreamChunk && (processedChunk || chunk.usage)) {\n const chunkObservers: Array<() => void | Promise<void>> = [];\n chunkObservers.push(async () => {\n const context: ObserveChunkContext = {\n iteration: this.iteration,\n rawChunk: processedChunk,\n accumulatedText: this.accumulatedText,\n usage,\n logger: this.logger,\n };\n await this.hooks.observers!.onStreamChunk!(context);\n });\n await this.runObserversInParallel(chunkObservers);\n }\n\n // Skip further processing if no text\n if (!processedChunk) {\n continue;\n }\n\n // Step 3: Parse and process events\n for (const event of this.parser.feed(processedChunk)) {\n const processedEvents = await this.processEvent(event);\n outputs.push(...processedEvents);\n\n // Check if any gadget was executed\n if (processedEvents.some((e) => e.type === \"gadget_result\")) {\n didExecuteGadgets = true;\n }\n\n // Check for loop termination signals\n for (const evt of processedEvents) {\n if (evt.type === \"gadget_result\" && evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n\n // Break if we should stop execution\n if (this.shouldStopExecution) {\n this.logger.info(\"Breaking from LLM stream due to gadget error\");\n break;\n }\n }\n\n // Finalize parsing\n if (!this.shouldStopExecution) {\n for (const event of this.parser.finalize()) {\n const processedEvents = await this.processEvent(event);\n outputs.push(...processedEvents);\n\n if (processedEvents.some((e) => e.type === \"gadget_result\")) {\n didExecuteGadgets = true;\n }\n\n for (const evt of processedEvents) {\n if (evt.type === \"gadget_result\" && evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n }\n\n // Step 4: Interceptor - Transform final message\n let finalMessage = this.accumulatedText;\n if (this.hooks.interceptors?.interceptAssistantMessage) {\n const context: MessageInterceptorContext = {\n iteration: this.iteration,\n rawResponse: this.accumulatedText,\n logger: this.logger,\n };\n finalMessage = this.hooks.interceptors.interceptAssistantMessage(finalMessage, context);\n }\n\n return {\n outputs,\n shouldBreakLoop,\n didExecuteGadgets,\n finishReason,\n usage,\n rawResponse: this.accumulatedText,\n finalMessage,\n };\n }\n\n /**\n * Process a single parsed event (text or gadget call).\n */\n private async processEvent(event: StreamEvent): Promise<StreamEvent[]> {\n if (event.type === \"text\") {\n return this.processTextEvent(event);\n } else if (event.type === \"gadget_call\") {\n return this.processGadgetCall(event.call);\n }\n return [event];\n }\n\n /**\n * Process a text event through interceptors.\n */\n private async processTextEvent(event: { type: \"text\"; content: string }): Promise<StreamEvent[]> {\n let content = event.content;\n\n // Interceptor: Transform text chunk\n if (this.hooks.interceptors?.interceptTextChunk) {\n const context: ChunkInterceptorContext = {\n iteration: this.iteration,\n accumulatedText: this.accumulatedText,\n logger: this.logger,\n };\n const intercepted = this.hooks.interceptors.interceptTextChunk(content, context);\n if (intercepted === null) {\n // Chunk suppressed\n return [];\n }\n content = intercepted;\n }\n\n return [{ type: \"text\", content }];\n }\n\n /**\n * Process a gadget call through the full lifecycle.\n */\n private async processGadgetCall(call: ParsedGadgetCall): Promise<StreamEvent[]> {\n // Check if we should skip due to previous error\n if (this.shouldStopExecution) {\n this.logger.debug(\"Skipping gadget execution due to previous error\", {\n gadgetName: call.gadgetName,\n });\n return [];\n }\n\n const events: StreamEvent[] = [];\n\n // Emit gadget call event\n events.push({ type: \"gadget_call\", call });\n\n // Check for parse errors\n if (call.parseError) {\n this.logger.warn(\"Gadget has parse error\", {\n gadgetName: call.gadgetName,\n error: call.parseError,\n rawParameters: call.parametersRaw,\n });\n\n const shouldContinue = await this.checkContinueAfterError(\n call.parseError,\n call.gadgetName,\n \"parse\",\n call.parameters,\n );\n\n if (!shouldContinue) {\n this.shouldStopExecution = true;\n }\n }\n\n // Step 1: Interceptor - Transform parameters\n let parameters = call.parameters ?? {};\n if (this.hooks.interceptors?.interceptGadgetParameters) {\n const context: GadgetParameterInterceptorContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n logger: this.logger,\n };\n parameters = this.hooks.interceptors.interceptGadgetParameters(parameters, context);\n }\n\n // Update call with intercepted parameters\n call.parameters = parameters;\n\n // Step 2: Controller - Before execution\n let shouldSkip = false;\n let syntheticResult: string | undefined;\n\n if (this.hooks.controllers?.beforeGadgetExecution) {\n const context: GadgetExecutionControllerContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters,\n logger: this.logger,\n };\n const action: BeforeGadgetExecutionAction =\n await this.hooks.controllers.beforeGadgetExecution(context);\n\n // Validate the action\n validateBeforeGadgetExecutionAction(action);\n\n if (action.action === \"skip\") {\n shouldSkip = true;\n syntheticResult = action.syntheticResult;\n this.logger.info(\"Controller skipped gadget execution\", {\n gadgetName: call.gadgetName,\n });\n }\n }\n\n // Step 3: Observer - Execution start\n const startObservers: Array<() => void | Promise<void>> = [];\n if (this.hooks.observers?.onGadgetExecutionStart) {\n startObservers.push(async () => {\n const context: ObserveGadgetStartContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters,\n logger: this.logger,\n };\n await this.hooks.observers!.onGadgetExecutionStart!(context);\n });\n }\n await this.runObserversInParallel(startObservers);\n\n // Step 4: Execute or use synthetic result\n let result: GadgetExecutionResult;\n if (shouldSkip) {\n result = {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters,\n result: syntheticResult ?? \"Execution skipped\",\n executionTimeMs: 0,\n };\n } else {\n result = await this.executor.execute(call);\n }\n\n const originalResult = result.result;\n\n // Step 5: Interceptor - Transform result\n if (result.result && this.hooks.interceptors?.interceptGadgetResult) {\n const context: GadgetResultInterceptorContext = {\n iteration: this.iteration,\n gadgetName: result.gadgetName,\n invocationId: result.invocationId,\n parameters,\n executionTimeMs: result.executionTimeMs,\n logger: this.logger,\n };\n result.result = this.hooks.interceptors.interceptGadgetResult(result.result, context);\n }\n\n // Step 6: Controller - After execution\n if (this.hooks.controllers?.afterGadgetExecution) {\n const context: AfterGadgetExecutionControllerContext = {\n iteration: this.iteration,\n gadgetName: result.gadgetName,\n invocationId: result.invocationId,\n parameters,\n result: result.result,\n error: result.error,\n executionTimeMs: result.executionTimeMs,\n logger: this.logger,\n };\n const action: AfterGadgetExecutionAction =\n await this.hooks.controllers.afterGadgetExecution(context);\n\n // Validate the action\n validateAfterGadgetExecutionAction(action);\n\n if (action.action === \"recover\" && result.error) {\n this.logger.info(\"Controller recovered from gadget error\", {\n gadgetName: result.gadgetName,\n originalError: result.error,\n });\n result = {\n ...result,\n error: undefined,\n result: action.fallbackResult,\n };\n }\n }\n\n // Step 7: Observer - Execution complete\n const completeObservers: Array<() => void | Promise<void>> = [];\n if (this.hooks.observers?.onGadgetExecutionComplete) {\n completeObservers.push(async () => {\n const context: ObserveGadgetCompleteContext = {\n iteration: this.iteration,\n gadgetName: result.gadgetName,\n invocationId: result.invocationId,\n parameters,\n originalResult,\n finalResult: result.result,\n error: result.error,\n executionTimeMs: result.executionTimeMs,\n breaksLoop: result.breaksLoop,\n logger: this.logger,\n };\n await this.hooks.observers!.onGadgetExecutionComplete!(context);\n });\n }\n await this.runObserversInParallel(completeObservers);\n\n // Emit result event\n events.push({ type: \"gadget_result\", result });\n\n // Check if we should stop after error\n if (result.error) {\n const errorType = this.determineErrorType(call, result);\n const shouldContinue = await this.checkContinueAfterError(\n result.error,\n result.gadgetName,\n errorType,\n result.parameters,\n );\n\n if (!shouldContinue) {\n this.shouldStopExecution = true;\n }\n }\n\n return events;\n }\n\n /**\n * Safely execute an observer, catching and logging any errors.\n * Observers are non-critical, so errors are logged but don't crash the system.\n */\n private async safeObserve(fn: () => void | Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (error) {\n this.observerFailureCount++;\n this.logger.error(\"Observer threw error (ignoring)\", {\n error: error instanceof Error ? error.message : String(error),\n failureCount: this.observerFailureCount,\n });\n }\n }\n\n /**\n * Execute multiple observers in parallel.\n * All observers run concurrently and failures are tracked but don't crash.\n */\n private async runObserversInParallel(\n observers: Array<() => void | Promise<void>>,\n ): Promise<void> {\n if (observers.length === 0) return;\n\n const results = await Promise.allSettled(\n observers.map((observer) => this.safeObserve(observer)),\n );\n\n // All errors are already logged in safeObserve, no need to handle rejected promises\n // This just ensures we wait for all observers to complete\n }\n\n /**\n * Check if execution should continue after an error.\n *\n * Returns true if we should continue processing subsequent gadgets, false if we should stop.\n *\n * Logic:\n * - If custom shouldContinueAfterError is provided, use it\n * - Otherwise, use stopOnGadgetError config:\n * - stopOnGadgetError=true → return false (stop execution)\n * - stopOnGadgetError=false → return true (continue execution)\n */\n private async checkContinueAfterError(\n error: string,\n gadgetName: string,\n errorType: \"parse\" | \"validation\" | \"execution\",\n parameters?: Record<string, unknown>,\n ): Promise<boolean> {\n // Custom error continuation logic takes precedence\n if (this.shouldContinueAfterError) {\n return await this.shouldContinueAfterError({\n error,\n gadgetName,\n errorType,\n parameters,\n });\n }\n\n // Default behavior based on stopOnGadgetError config\n // If stopOnGadgetError=true, we want to STOP (return false to stop continuing)\n // If stopOnGadgetError=false, we want to CONTINUE (return true to keep going)\n const shouldContinue = !this.stopOnGadgetError;\n\n this.logger.debug(\"Checking if should continue after error\", {\n error,\n gadgetName,\n errorType,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinue,\n });\n\n return shouldContinue;\n }\n\n /**\n * Determine the type of error from a gadget execution.\n */\n private determineErrorType(\n call: ParsedGadgetCall,\n result: GadgetExecutionResult,\n ): \"parse\" | \"validation\" | \"execution\" {\n if (call.parseError) {\n return \"parse\";\n }\n if (result.error?.includes(\"Invalid parameters:\")) {\n return \"validation\";\n }\n return \"execution\";\n }\n}\n","/**\n * Agent: Lean orchestrator using the clean hooks architecture.\n *\n * The Agent delegates ALL stream processing and hook coordination to StreamProcessor,\n * making it a simple loop orchestrator with clear responsibilities.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport {\n CHARS_PER_TOKEN,\n DEFAULT_GADGET_OUTPUT_LIMIT,\n DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT,\n FALLBACK_CONTEXT_WINDOW,\n} from \"../core/constants.js\";\nimport { LLMMessageBuilder } from \"../core/messages.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { LLMGenerationOptions } from \"../core/options.js\";\nimport type { PromptConfig } from \"../core/prompt-config.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { StreamEvent, TextOnlyHandler } from \"../gadgets/types.js\";\nimport { createGadgetOutputViewer } from \"../gadgets/output-viewer.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { GadgetOutputStore } from \"./gadget-output-store.js\";\nimport type { GadgetResultInterceptorContext } from \"./hooks.js\";\nimport { type AGENT_INTERNAL_KEY, isValidAgentKey } from \"./agent-internal-key.js\";\nimport { ConversationManager } from \"./conversation-manager.js\";\nimport { type EventHandlers, runWithHandlers } from \"./event-handlers.js\";\nimport {\n validateAfterLLMCallAction,\n validateAfterLLMErrorAction,\n validateBeforeLLMCallAction,\n} from \"./hook-validators.js\";\nimport type {\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n BeforeLLMCallAction,\n LLMCallControllerContext,\n LLMErrorControllerContext,\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n} from \"./hooks.js\";\nimport { StreamProcessor } from \"./stream-processor.js\";\n\n/**\n * Configuration options for the Agent.\n */\nexport interface AgentOptions {\n /** The LLM client */\n client: LLMist;\n\n /** The model ID */\n model: string;\n\n /** System prompt */\n systemPrompt?: string;\n\n /** Initial user prompt (optional if using build()) */\n userPrompt?: string;\n\n /** Maximum iterations */\n maxIterations?: number;\n\n /** Temperature */\n temperature?: number;\n\n /** Gadget registry */\n registry: GadgetRegistry;\n\n /** Logger */\n logger?: Logger<ILogObj>;\n\n /** Clean hooks system */\n hooks?: AgentHooks;\n\n /** Callback for human input */\n onHumanInputRequired?: (question: string) => Promise<string>;\n\n /** Custom gadget start prefix */\n gadgetStartPrefix?: string;\n\n /** Custom gadget end prefix */\n gadgetEndPrefix?: string;\n\n /** Custom gadget argument prefix for block format parameters */\n gadgetArgPrefix?: string;\n\n /** Initial messages */\n initialMessages?: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>;\n\n /** Text-only handler */\n textOnlyHandler?: TextOnlyHandler;\n\n /**\n * Handler for text content that appears alongside gadget calls.\n * When set, text accompanying gadgets will be wrapped as a synthetic gadget call.\n */\n textWithGadgetsHandler?: {\n /** Name of the gadget to use for wrapping text */\n gadgetName: string;\n /** Maps text content to gadget parameters */\n parameterMapping: (text: string) => Record<string, unknown>;\n /** Maps text content to the result string (optional, defaults to text) */\n resultMapping?: (text: string) => string;\n };\n\n /** Stop on gadget error */\n stopOnGadgetError?: boolean;\n\n /** Custom error continuation logic */\n shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n\n /** Default gadget timeout */\n defaultGadgetTimeoutMs?: number;\n\n /** Custom prompt configuration for gadget system prompts */\n promptConfig?: PromptConfig;\n\n /** Enable gadget output limiting (default: true) */\n gadgetOutputLimit?: boolean;\n\n /** Max gadget output as % of model context window (default: 15) */\n gadgetOutputLimitPercent?: number;\n}\n\n/**\n * Agent: Lean orchestrator that delegates to StreamProcessor.\n *\n * Responsibilities:\n * - Run the main agent loop\n * - Call LLM API\n * - Delegate stream processing to StreamProcessor\n * - Coordinate conversation management\n * - Execute top-level lifecycle controllers\n *\n * NOT responsible for:\n * - Stream parsing (StreamProcessor)\n * - Hook coordination (StreamProcessor)\n * - Gadget execution (StreamProcessor -> GadgetExecutor)\n */\nexport class Agent {\n private readonly client: LLMist;\n private readonly model: string;\n private readonly maxIterations: number;\n private readonly temperature?: number;\n private readonly logger: Logger<ILogObj>;\n private readonly hooks: AgentHooks;\n private readonly conversation: ConversationManager;\n private readonly registry: GadgetRegistry;\n private readonly gadgetStartPrefix?: string;\n private readonly gadgetEndPrefix?: string;\n private readonly gadgetArgPrefix?: string;\n private readonly onHumanInputRequired?: (question: string) => Promise<string>;\n private readonly textOnlyHandler: TextOnlyHandler;\n private readonly textWithGadgetsHandler?: {\n gadgetName: string;\n parameterMapping: (text: string) => Record<string, unknown>;\n resultMapping?: (text: string) => string;\n };\n private readonly stopOnGadgetError: boolean;\n private readonly shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n private readonly defaultGadgetTimeoutMs?: number;\n private readonly defaultMaxTokens?: number;\n private userPromptProvided: boolean;\n\n // Gadget output limiting\n private readonly outputStore: GadgetOutputStore;\n private readonly outputLimitEnabled: boolean;\n private readonly outputLimitCharLimit: number;\n\n /**\n * Creates a new Agent instance.\n * @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.\n */\n constructor(key: typeof AGENT_INTERNAL_KEY, options: AgentOptions) {\n if (!isValidAgentKey(key)) {\n throw new Error(\n \"Agent cannot be instantiated directly. Use LLMist.createAgent() or new AgentBuilder() instead.\",\n );\n }\n\n this.client = options.client;\n this.model = resolveModel(options.model);\n this.maxIterations = options.maxIterations ?? 10;\n this.temperature = options.temperature;\n this.logger = options.logger ?? createLogger({ name: \"llmist:agent\" });\n this.registry = options.registry;\n this.gadgetStartPrefix = options.gadgetStartPrefix;\n this.gadgetEndPrefix = options.gadgetEndPrefix;\n this.gadgetArgPrefix = options.gadgetArgPrefix;\n this.onHumanInputRequired = options.onHumanInputRequired;\n this.textOnlyHandler = options.textOnlyHandler ?? \"terminate\";\n this.textWithGadgetsHandler = options.textWithGadgetsHandler;\n this.stopOnGadgetError = options.stopOnGadgetError ?? true;\n this.shouldContinueAfterError = options.shouldContinueAfterError;\n this.defaultGadgetTimeoutMs = options.defaultGadgetTimeoutMs;\n this.defaultMaxTokens = this.resolveMaxTokensFromCatalog(options.model);\n\n // Initialize gadget output limiting\n this.outputLimitEnabled = options.gadgetOutputLimit ?? DEFAULT_GADGET_OUTPUT_LIMIT;\n this.outputStore = new GadgetOutputStore();\n\n // Calculate character limit from model context window\n const limitPercent = options.gadgetOutputLimitPercent ?? DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT;\n const limits = this.client.modelRegistry.getModelLimits(this.model);\n const contextWindow = limits?.contextWindow ?? FALLBACK_CONTEXT_WINDOW;\n this.outputLimitCharLimit = Math.floor(contextWindow * (limitPercent / 100) * CHARS_PER_TOKEN);\n\n // Auto-register GadgetOutputViewer when limiting is enabled\n if (this.outputLimitEnabled) {\n this.registry.register(\"GadgetOutputViewer\", createGadgetOutputViewer(this.outputStore));\n }\n\n // Merge output limiter interceptor into hooks\n this.hooks = this.mergeOutputLimiterHook(options.hooks);\n\n // Build conversation\n const baseBuilder = new LLMMessageBuilder(options.promptConfig);\n if (options.systemPrompt) {\n baseBuilder.addSystem(options.systemPrompt);\n }\n\n baseBuilder.addGadgets(this.registry.getAll(), {\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n argPrefix: options.gadgetArgPrefix,\n });\n const baseMessages = baseBuilder.build();\n\n const initialMessages = (options.initialMessages ?? []).map((message) => ({\n role: message.role,\n content: message.content,\n }));\n\n this.conversation = new ConversationManager(baseMessages, initialMessages, {\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n argPrefix: options.gadgetArgPrefix,\n });\n this.userPromptProvided = !!options.userPrompt;\n if (options.userPrompt) {\n this.conversation.addUserMessage(options.userPrompt);\n }\n }\n\n /**\n * Get the gadget registry for this agent.\n *\n * Useful for inspecting registered gadgets in tests or advanced use cases.\n *\n * @returns The GadgetRegistry instance\n *\n * @example\n * ```typescript\n * const agent = new AgentBuilder()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator, Weather)\n * .build();\n *\n * // Inspect registered gadgets\n * console.log(agent.getRegistry().getNames()); // ['Calculator', 'Weather']\n * ```\n */\n getRegistry(): GadgetRegistry {\n return this.registry;\n }\n\n /**\n * Run the agent loop.\n * Clean, simple orchestration - all complexity is in StreamProcessor.\n *\n * @throws {Error} If no user prompt was provided (when using build() without ask())\n */\n async *run(): AsyncGenerator<StreamEvent> {\n if (!this.userPromptProvided) {\n throw new Error(\n \"No user prompt provided. Use .ask(prompt) instead of .build(), or call agent.run() after providing a prompt.\",\n );\n }\n\n let currentIteration = 0;\n\n this.logger.info(\"Starting agent loop\", {\n model: this.model,\n maxIterations: this.maxIterations,\n });\n\n while (currentIteration < this.maxIterations) {\n this.logger.debug(\"Starting iteration\", { iteration: currentIteration });\n\n try {\n // Prepare LLM call options\n let llmOptions: LLMGenerationOptions = {\n model: this.model,\n messages: this.conversation.getMessages(),\n temperature: this.temperature,\n maxTokens: this.defaultMaxTokens,\n };\n\n // Observer: LLM call start\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onLLMCallStart) {\n const context: ObserveLLMCallContext = {\n iteration: currentIteration,\n options: llmOptions,\n logger: this.logger,\n };\n await this.hooks.observers.onLLMCallStart(context);\n }\n });\n\n // Controller: Before LLM call\n if (this.hooks.controllers?.beforeLLMCall) {\n const context: LLMCallControllerContext = {\n iteration: currentIteration,\n options: llmOptions,\n logger: this.logger,\n };\n const action: BeforeLLMCallAction = await this.hooks.controllers.beforeLLMCall(context);\n\n // Validate the action\n validateBeforeLLMCallAction(action);\n\n if (action.action === \"skip\") {\n this.logger.info(\"Controller skipped LLM call, using synthetic response\");\n // Add synthetic response to conversation\n this.conversation.addAssistantMessage(action.syntheticResponse);\n // Yield as text event\n yield { type: \"text\", content: action.syntheticResponse };\n break;\n } else if (action.action === \"proceed\" && action.modifiedOptions) {\n llmOptions = { ...llmOptions, ...action.modifiedOptions };\n }\n }\n\n // Call LLM\n this.logger.info(\"Calling LLM\", { model: this.model });\n this.logger.silly(\"LLM request details\", {\n model: llmOptions.model,\n temperature: llmOptions.temperature,\n maxTokens: llmOptions.maxTokens,\n messageCount: llmOptions.messages.length,\n messages: llmOptions.messages,\n });\n const stream = this.client.stream(llmOptions);\n\n // Process stream - ALL complexity delegated to StreamProcessor\n const processor = new StreamProcessor({\n iteration: currentIteration,\n registry: this.registry,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n hooks: this.hooks,\n logger: this.logger.getSubLogger({ name: \"stream-processor\" }),\n onHumanInputRequired: this.onHumanInputRequired,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinueAfterError: this.shouldContinueAfterError,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n });\n\n const result = await processor.process(stream);\n\n // Yield all outputs to user\n for (const output of result.outputs) {\n yield output;\n }\n\n this.logger.info(\"LLM response completed\", {\n finishReason: result.finishReason,\n usage: result.usage,\n didExecuteGadgets: result.didExecuteGadgets,\n });\n this.logger.silly(\"LLM response details\", {\n rawResponse: result.rawResponse,\n });\n\n // Observer: LLM call complete\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onLLMCallComplete) {\n const context: ObserveLLMCompleteContext = {\n iteration: currentIteration,\n options: llmOptions,\n finishReason: result.finishReason,\n usage: result.usage,\n rawResponse: result.rawResponse,\n finalMessage: result.finalMessage,\n logger: this.logger,\n };\n await this.hooks.observers.onLLMCallComplete(context);\n }\n });\n\n // Controller: After LLM call\n let finalMessage = result.finalMessage;\n if (this.hooks.controllers?.afterLLMCall) {\n const context: AfterLLMCallControllerContext = {\n iteration: currentIteration,\n options: llmOptions,\n finishReason: result.finishReason,\n usage: result.usage,\n finalMessage: result.finalMessage,\n logger: this.logger,\n };\n const action: AfterLLMCallAction = await this.hooks.controllers.afterLLMCall(context);\n\n // Validate the action\n validateAfterLLMCallAction(action);\n\n if (action.action === \"modify_and_continue\" || action.action === \"append_and_modify\") {\n finalMessage = action.modifiedMessage;\n }\n\n if (action.action === \"append_messages\" || action.action === \"append_and_modify\") {\n for (const msg of action.messages) {\n if (msg.role === \"user\") {\n this.conversation.addUserMessage(msg.content);\n } else if (msg.role === \"assistant\") {\n this.conversation.addAssistantMessage(msg.content);\n } else if (msg.role === \"system\") {\n // System messages can't be added mid-conversation, treat as user\n this.conversation.addUserMessage(`[System] ${msg.content}`);\n }\n }\n }\n }\n\n // Add gadget results to conversation (if any were executed)\n if (result.didExecuteGadgets) {\n // If configured, wrap accompanying text as a synthetic gadget call (before actual gadgets)\n if (this.textWithGadgetsHandler) {\n const textContent = result.outputs\n .filter((output): output is { type: \"text\"; content: string } => output.type === \"text\")\n .map((output) => output.content)\n .join(\"\");\n\n if (textContent.trim()) {\n const { gadgetName, parameterMapping, resultMapping } = this.textWithGadgetsHandler;\n this.conversation.addGadgetCall(\n gadgetName,\n parameterMapping(textContent),\n resultMapping ? resultMapping(textContent) : textContent,\n );\n }\n }\n\n // Extract and add all gadget results to conversation\n for (const output of result.outputs) {\n if (output.type === \"gadget_result\") {\n const gadgetResult = output.result;\n this.conversation.addGadgetCall(\n gadgetResult.gadgetName,\n gadgetResult.parameters,\n gadgetResult.error ?? gadgetResult.result ?? \"\",\n );\n }\n }\n } else {\n // No gadgets executed - wrap text as synthetic TellUser result\n // This keeps conversation history consistent (gadget-oriented) and\n // helps LLMs stay in the \"gadget invocation\" mindset\n if (finalMessage.trim()) {\n this.conversation.addGadgetCall(\n \"TellUser\",\n { message: finalMessage, done: false, type: \"info\" },\n `ℹ️ ${finalMessage}`,\n );\n }\n // Empty responses: don't add anything, just check if we should continue\n\n // Handle text-only responses\n const shouldBreak = await this.handleTextOnlyResponse(finalMessage);\n if (shouldBreak) {\n break;\n }\n }\n\n // Check if loop should break\n if (result.shouldBreakLoop) {\n this.logger.info(\"Loop terminated by gadget or processor\");\n break;\n }\n } catch (error) {\n // Handle LLM error\n const errorHandled = await this.handleLLMError(error as Error, currentIteration);\n\n // Observer: LLM error\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onLLMCallError) {\n const context: ObserveLLMErrorContext = {\n iteration: currentIteration,\n options: {\n model: this.model,\n messages: this.conversation.getMessages(),\n temperature: this.temperature,\n maxTokens: this.defaultMaxTokens,\n },\n error: error as Error,\n recovered: errorHandled,\n logger: this.logger,\n };\n await this.hooks.observers.onLLMCallError(context);\n }\n });\n\n if (!errorHandled) {\n throw error;\n }\n }\n\n currentIteration++;\n }\n\n this.logger.info(\"Agent loop completed\", {\n totalIterations: currentIteration,\n reason: currentIteration >= this.maxIterations ? \"max_iterations\" : \"natural_completion\",\n });\n }\n\n /**\n * Handle LLM error through controller.\n */\n private async handleLLMError(error: Error, iteration: number): Promise<boolean> {\n this.logger.error(\"LLM call failed\", { error: error.message });\n\n if (this.hooks.controllers?.afterLLMError) {\n const context: LLMErrorControllerContext = {\n iteration,\n options: {\n model: this.model,\n messages: this.conversation.getMessages(),\n temperature: this.temperature,\n maxTokens: this.defaultMaxTokens,\n },\n error,\n logger: this.logger,\n };\n const action: AfterLLMErrorAction = await this.hooks.controllers.afterLLMError(context);\n\n // Validate the action\n validateAfterLLMErrorAction(action);\n\n if (action.action === \"recover\") {\n this.logger.info(\"Controller recovered from LLM error\");\n this.conversation.addAssistantMessage(action.fallbackResponse);\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Handle text-only response (no gadgets called).\n */\n private async handleTextOnlyResponse(_text: string): Promise<boolean> {\n const handler = this.textOnlyHandler;\n\n if (typeof handler === \"string\") {\n switch (handler) {\n case \"terminate\":\n this.logger.info(\"No gadgets called, ending loop\");\n return true;\n case \"acknowledge\":\n this.logger.info(\"No gadgets called, continuing loop\");\n return false;\n case \"wait_for_input\":\n this.logger.info(\"No gadgets called, waiting for input\");\n return true;\n default:\n this.logger.warn(`Unknown text-only strategy: ${handler}, defaulting to terminate`);\n return true;\n }\n }\n\n // For gadget and custom handlers, they would need to be implemented\n // This is simplified for now\n return true;\n }\n\n /**\n * Safely execute an observer, catching and logging any errors.\n */\n private async safeObserve(fn: () => void | Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (error) {\n this.logger.error(\"Observer threw error (ignoring)\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n /**\n * Resolve max tokens from model catalog.\n */\n private resolveMaxTokensFromCatalog(modelId: string): number | undefined {\n const limits = this.client.modelRegistry.getModelLimits(modelId);\n if (limits?.maxOutputTokens !== undefined) {\n return limits.maxOutputTokens;\n }\n\n const separatorIndex = modelId.indexOf(\":\");\n if (separatorIndex === -1) {\n return undefined;\n }\n\n const unprefixedModelId = modelId.slice(separatorIndex + 1).trim();\n if (!unprefixedModelId) {\n return undefined;\n }\n\n return this.client.modelRegistry.getModelLimits(unprefixedModelId)?.maxOutputTokens;\n }\n\n /**\n * Merge the output limiter interceptor into user-provided hooks.\n * The limiter runs first, then chains to any user interceptor.\n */\n private mergeOutputLimiterHook(userHooks?: AgentHooks): AgentHooks {\n if (!this.outputLimitEnabled) {\n return userHooks ?? {};\n }\n\n const limiterInterceptor = (\n result: string,\n ctx: GadgetResultInterceptorContext,\n ): string => {\n // Skip limiting for GadgetOutputViewer itself to avoid recursion\n if (ctx.gadgetName === \"GadgetOutputViewer\") {\n return result;\n }\n\n if (result.length > this.outputLimitCharLimit) {\n const id = this.outputStore.store(ctx.gadgetName, result);\n const lines = result.split(\"\\n\").length;\n const bytes = new TextEncoder().encode(result).length;\n\n this.logger.info(\"Gadget output exceeded limit, stored for browsing\", {\n gadgetName: ctx.gadgetName,\n outputId: id,\n bytes,\n lines,\n charLimit: this.outputLimitCharLimit,\n });\n\n return (\n `[Gadget \"${ctx.gadgetName}\" returned too much data: ` +\n `${bytes.toLocaleString()} bytes, ${lines.toLocaleString()} lines. ` +\n `Use GadgetOutputViewer with id \"${id}\" to read it]`\n );\n }\n\n return result;\n };\n\n // Chain with any user-provided interceptor (limiter runs first)\n const userInterceptor = userHooks?.interceptors?.interceptGadgetResult;\n const chainedInterceptor = userInterceptor\n ? (result: string, ctx: GadgetResultInterceptorContext) =>\n userInterceptor(limiterInterceptor(result, ctx), ctx)\n : limiterInterceptor;\n\n return {\n ...userHooks,\n interceptors: {\n ...userHooks?.interceptors,\n interceptGadgetResult: chainedInterceptor,\n },\n };\n }\n\n /**\n * Run agent with named event handlers (syntactic sugar).\n *\n * Instead of verbose if/else chains, use named handlers for cleaner code.\n *\n * @param handlers - Named event handlers\n *\n * @example\n * ```typescript\n * await agent.runWith({\n * onText: (text) => console.log(\"LLM:\", text),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * onGadgetCall: (call) => console.log(\"Calling:\", call.gadgetName),\n * });\n * ```\n */\n async runWith(handlers: EventHandlers): Promise<void> {\n return runWithHandlers(this.run(), handlers);\n }\n}\n","/**\n * Anthropic Claude Model Specifications\n *\n * Model data for Anthropic Claude models including Sonnet and Opus variants\n * with their specifications, pricing, and capabilities.\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const ANTHROPIC_MODELS: ModelSpec[] = [\n {\n provider: \"anthropic\",\n modelId: \"claude-sonnet-4-5-20250929\",\n displayName: \"Claude Sonnet 4.5\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 3.0,\n output: 15.0,\n cachedInput: 0.3,\n cacheWriteInput: 3.75,\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-09-29\",\n notes: \"Smartest model for complex agents and coding. Extended thinking. 1M context in beta.\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-haiku-4-5-20251001\",\n displayName: \"Claude Haiku 4.5\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 1.0,\n output: 5.0,\n cachedInput: 0.1,\n cacheWriteInput: 1.25,\n },\n knowledgeCutoff: \"2025-02\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-10-01\",\n notes:\n \"Fastest model with near-frontier intelligence. Excellent for coding (73.3% SWE-bench).\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-sonnet-4-20250514\",\n displayName: \"Claude Sonnet 4\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 3.0,\n output: 15.0,\n cachedInput: 0.3,\n cacheWriteInput: 3.75,\n },\n knowledgeCutoff: \"2025-03\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-05-14\",\n notes: \"High performance with vision and extended thinking\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-3-7-sonnet-20250219\",\n displayName: \"Claude Sonnet 3.7\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 3.0,\n output: 15.0,\n cachedInput: 0.3,\n cacheWriteInput: 3.75,\n },\n knowledgeCutoff: \"2024-11\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 3\",\n releaseDate: \"2025-02-19\",\n notes: \"Legacy model - consider upgrading to Claude 4 family\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-opus-4-1-20250805\",\n displayName: \"Claude Opus 4.1\",\n contextWindow: 200_000,\n maxOutputTokens: 32_000,\n pricing: {\n input: 15.0,\n output: 75.0,\n cachedInput: 1.5,\n cacheWriteInput: 18.75,\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-08-05\",\n notes: \"Exceptional for specialized reasoning tasks. Extended thinking support.\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-opus-4-20250514\",\n displayName: \"Claude Opus 4\",\n contextWindow: 200_000,\n maxOutputTokens: 32_000,\n pricing: {\n input: 15.0,\n output: 75.0,\n cachedInput: 1.5,\n cacheWriteInput: 18.75,\n },\n knowledgeCutoff: \"2025-03\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-05-14\",\n notes: \"Legacy Opus model - consider Opus 4.1 for improved reasoning\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-3-5-haiku-20241022\",\n displayName: \"Claude Haiku 3.5\",\n contextWindow: 200_000,\n maxOutputTokens: 8_192,\n pricing: {\n input: 0.8,\n output: 4.0,\n cachedInput: 0.08,\n cacheWriteInput: 1.0,\n },\n knowledgeCutoff: \"2024-07\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n },\n metadata: {\n family: \"Claude 3\",\n releaseDate: \"2024-10-22\",\n notes: \"Legacy model - upgrade to Haiku 4.5 for better performance\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-3-haiku-20240307\",\n displayName: \"Claude Haiku 3\",\n contextWindow: 200_000,\n maxOutputTokens: 4_096,\n pricing: {\n input: 0.25,\n output: 1.25,\n cachedInput: 0.025,\n cacheWriteInput: 0.3125,\n },\n knowledgeCutoff: \"2023-08\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n },\n metadata: {\n family: \"Claude 3\",\n releaseDate: \"2024-03-07\",\n notes: \"Legacy model - upgrade to Haiku 4.5 for better performance\",\n },\n },\n // Modern aliases (recommended by Anthropic)\n {\n provider: \"anthropic\",\n modelId: \"claude-haiku-4-5\",\n displayName: \"Claude Haiku 4.5\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 1.0,\n output: 5.0,\n cachedInput: 0.1,\n cacheWriteInput: 1.25,\n },\n knowledgeCutoff: \"2025-02\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-10-01\",\n notes: \"Alias for claude-haiku-4-5-20251001. Fastest model with near-frontier intelligence.\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-sonnet-4-5\",\n displayName: \"Claude Sonnet 4.5\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 3.0,\n output: 15.0,\n cachedInput: 0.3,\n cacheWriteInput: 3.75,\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-09-29\",\n notes: \"Alias for claude-sonnet-4-5-20250929. Smartest model for complex agents and coding.\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-opus-4-5\",\n displayName: \"Claude Opus 4.5\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 5.0,\n output: 25.0,\n cachedInput: 0.5,\n cacheWriteInput: 6.25,\n },\n knowledgeCutoff: \"2025-03\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-11-24\",\n notes: \"Alias for claude-opus-4-5-20251124. Most powerful model for coding and computer use.\",\n },\n },\n];\n","/**\n * Base Provider Adapter\n *\n * Abstract base class for provider adapters that implements the Template Method pattern.\n * This class defines the skeleton of the streaming algorithm, leaving provider-specific\n * details to be implemented by concrete subclasses.\n *\n * The streaming workflow consists of four main steps:\n * 1. Prepare messages (optional transformation for provider-specific requirements)\n * 2. Build the request payload (provider-specific formatting)\n * 3. Execute the stream request (call the provider's SDK)\n * 4. Wrap the stream (transform provider-specific chunks into universal format)\n */\n\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport type { ProviderAdapter } from \"./provider.js\";\n\nexport abstract class BaseProviderAdapter implements ProviderAdapter {\n abstract readonly providerId: string;\n\n constructor(protected readonly client: unknown) {}\n\n abstract supports(descriptor: ModelDescriptor): boolean;\n\n /**\n * Optionally provide model specifications for this provider.\n * This allows the model registry to discover available models and their capabilities.\n */\n getModelSpecs?(): ModelSpec[];\n\n /**\n * Template method that defines the skeleton of the streaming algorithm.\n * This orchestrates the four-step process without dictating provider-specific details.\n */\n async *stream(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n spec?: ModelSpec,\n ): LLMStream {\n // Step 1: Prepare messages (can be overridden for special cases like Gemini)\n const preparedMessages = this.prepareMessages(options.messages);\n\n // Step 2: Build the provider-specific request payload\n const payload = this.buildRequestPayload(options, descriptor, spec, preparedMessages);\n\n // Step 3: Execute the stream request using the provider's SDK\n const rawStream = await this.executeStreamRequest(payload);\n\n // Step 4: Transform the provider-specific stream into universal format\n yield* this.wrapStream(rawStream);\n }\n\n /**\n * Prepare messages for the request.\n * Default implementation returns messages unchanged.\n * Override this to implement provider-specific message transformations\n * (e.g., Gemini's consecutive message merging, Anthropic's system message extraction).\n *\n * @param messages - The input messages\n * @returns Prepared messages\n */\n protected prepareMessages(messages: LLMMessage[]): LLMMessage[] {\n return messages;\n }\n\n /**\n * Build the provider-specific request payload.\n * This method must be implemented by each concrete provider.\n *\n * @param options - The generation options\n * @param descriptor - The model descriptor\n * @param spec - Optional model specification with metadata\n * @param messages - The prepared messages\n * @returns Provider-specific payload ready for the API call\n */\n protected abstract buildRequestPayload(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n spec: ModelSpec | undefined,\n messages: LLMMessage[],\n ): unknown;\n\n /**\n * Execute the stream request using the provider's SDK.\n * This method must be implemented by each concrete provider.\n *\n * @param payload - The provider-specific payload\n * @returns An async iterable of provider-specific chunks\n */\n protected abstract executeStreamRequest(payload: unknown): Promise<AsyncIterable<unknown>>;\n\n /**\n * Wrap the provider-specific stream into the universal LLMStream format.\n * This method must be implemented by each concrete provider.\n *\n * @param rawStream - The provider-specific stream\n * @returns Universal LLMStream\n */\n protected abstract wrapStream(rawStream: AsyncIterable<unknown>): LLMStream;\n}\n","/**\n * Provider-specific constants and default values.\n *\n * This file centralizes magic numbers and hardcoded defaults to improve\n * maintainability and documentation. Each constant includes a comment\n * explaining its purpose and rationale.\n */\n\n/**\n * Default maximum output tokens for Anthropic models.\n *\n * Rationale: Most Anthropic models (Claude 3 Opus, Sonnet, Haiku) support\n * at least 4096 output tokens. This is used as a fallback when:\n * - The user doesn't specify maxTokens explicitly\n * - The model spec doesn't define maxOutputTokens\n *\n * Note: Anthropic's API requires the max_tokens parameter, unlike OpenAI\n * which can infer it from the context window. This default ensures the API\n * call succeeds while allowing substantial output.\n *\n * Reference: https://docs.anthropic.com/en/docs/about-claude/models\n */\nexport const ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS = 4096;\n\n/**\n * Character-to-token ratio for fallback token estimation.\n *\n * Rationale: When native token counting APIs fail, we estimate tokens using\n * a rough heuristic of 4 characters per token. This is based on empirical\n * observations across multiple LLM providers:\n * - OpenAI's GPT models average ~4 chars/token for English text\n * - Anthropic's Claude models have similar characteristics\n * - Gemini models also approximate this ratio\n *\n * This is intentionally conservative to avoid underestimating token usage.\n * While not perfectly accurate, it provides a reasonable fallback when\n * precise tokenization is unavailable.\n *\n * Reference: https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them\n */\nexport const FALLBACK_CHARS_PER_TOKEN = 4;\n\n/**\n * OpenAI message structure overhead in tokens.\n *\n * Rationale: OpenAI's chat completion format adds tokens for message\n * boundaries and structure. Each message follows the pattern:\n * <im_start>{role/name}\\n{content}<im_end>\\n\n *\n * This overhead accounts for:\n * - <im_start> token\n * - Role/name field tokens\n * - Newline and separator tokens\n * - <im_end> token\n *\n * The value of 4 tokens per message is based on OpenAI's official\n * tokenization examples and testing.\n *\n * Reference: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n */\nexport const OPENAI_MESSAGE_OVERHEAD_TOKENS = 4;\n\n/**\n * OpenAI reply priming overhead in tokens.\n *\n * Rationale: Every OpenAI assistant reply is primed with the tokens:\n * <im_start>assistant\\n\n *\n * This adds 2 tokens to the total input token count before the actual\n * response generation begins. This is part of OpenAI's message formatting\n * and must be accounted for in accurate token counting.\n *\n * Reference: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n */\nexport const OPENAI_REPLY_PRIMING_TOKENS = 2;\n\n/**\n * OpenAI name field overhead in tokens.\n *\n * Rationale: When a message includes a \"name\" field (for identifying the\n * speaker in multi-party conversations), OpenAI's format adds 1 extra\n * token beyond the name's actual token count.\n *\n * This accounts for the separator between the role and name fields.\n *\n * Reference: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n */\nexport const OPENAI_NAME_FIELD_OVERHEAD_TOKENS = 1;\n","/**\n * Common utility functions shared across provider implementations\n */\n\n/**\n * Safely read an environment variable\n * @param key - The environment variable key to read\n * @returns The value if found and valid, undefined otherwise\n */\nexport function readEnvVar(key: string): string | undefined {\n if (typeof process === \"undefined\" || typeof process.env === \"undefined\") {\n return undefined;\n }\n const value = process.env[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\n/**\n * Check if a value is a non-empty string\n * @param value - The value to check\n * @returns true if the value is a non-empty string, false otherwise\n */\nexport function isNonEmpty(value: string | undefined): value is string {\n return typeof value === \"string\" && value.trim().length > 0;\n}\n\n/**\n * Generic factory function for creating provider instances from environment variables\n * @param envVarName - Name of the environment variable containing the API key\n * @param ClientClass - Constructor for the SDK client\n * @param ProviderClass - Constructor for the provider adapter\n * @param clientOptions - Optional additional options to pass to the client constructor\n * @returns Provider instance or null if API key is not set\n */\nexport function createProviderFromEnv<TClient, TProvider>(\n envVarName: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ClientClass: new (config: any) => TClient,\n ProviderClass: new (client: TClient) => TProvider,\n clientOptions?: Record<string, unknown>,\n): TProvider | null {\n const apiKey = readEnvVar(envVarName);\n if (!isNonEmpty(apiKey)) {\n return null;\n }\n\n // Create client with API key and optional config\n const client = new ClientClass({ apiKey: apiKey.trim(), ...clientOptions });\n\n return new ProviderClass(client);\n}\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n MessageCreateParamsStreaming,\n MessageStreamEvent,\n} from \"@anthropic-ai/sdk/resources/messages\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport { ANTHROPIC_MODELS } from \"./anthropic-models.js\";\nimport { BaseProviderAdapter } from \"./base-provider.js\";\nimport { ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS, FALLBACK_CHARS_PER_TOKEN } from \"./constants.js\";\nimport { createProviderFromEnv } from \"./utils.js\";\n\nexport class AnthropicMessagesProvider extends BaseProviderAdapter {\n readonly providerId = \"anthropic\" as const;\n\n supports(descriptor: ModelDescriptor): boolean {\n return descriptor.provider === this.providerId;\n }\n\n getModelSpecs() {\n return ANTHROPIC_MODELS;\n }\n\n protected buildRequestPayload(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n spec: ModelSpec | undefined,\n messages: LLMMessage[],\n ): MessageCreateParamsStreaming {\n const systemMessages = messages.filter((message) => message.role === \"system\");\n\n // System message as array of text blocks with cache_control on last block\n // This enables Anthropic's prompt caching for the system prompt\n const system =\n systemMessages.length > 0\n ? systemMessages.map((m, index) => ({\n type: \"text\" as const,\n text: m.content,\n // Add cache_control to the LAST system message block\n ...(index === systemMessages.length - 1\n ? { cache_control: { type: \"ephemeral\" as const } }\n : {}),\n }))\n : undefined;\n\n const nonSystemMessages = messages.filter(\n (message): message is LLMMessage & { role: \"user\" | \"assistant\" } =>\n message.role !== \"system\",\n );\n\n // Find index of last user message for cache breakpoint\n const lastUserIndex = nonSystemMessages.reduce(\n (lastIdx, msg, idx) => (msg.role === \"user\" ? idx : lastIdx),\n -1,\n );\n\n // Build conversation with cache_control on the last user message\n // This caches the conversation history prefix for multi-turn efficiency\n const conversation = nonSystemMessages.map((message, index) => ({\n role: message.role,\n content: [\n {\n type: \"text\" as const,\n text: message.content,\n // Add cache_control to the LAST user message\n ...(message.role === \"user\" && index === lastUserIndex\n ? { cache_control: { type: \"ephemeral\" as const } }\n : {}),\n },\n ],\n }));\n\n // Anthropic requires max_tokens, so use a smart default if not specified\n // Use model's max from the passed spec, or fall back to the default constant\n const defaultMaxTokens = spec?.maxOutputTokens ?? ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS;\n\n const payload: MessageCreateParamsStreaming = {\n model: descriptor.name,\n system,\n messages: conversation,\n max_tokens: options.maxTokens ?? defaultMaxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: options.stopSequences,\n stream: true,\n ...options.extra,\n };\n\n return payload;\n }\n\n protected async executeStreamRequest(\n payload: MessageCreateParamsStreaming,\n ): Promise<AsyncIterable<MessageStreamEvent>> {\n const client = this.client as Anthropic;\n const stream = await client.messages.create(payload);\n return stream as unknown as AsyncIterable<MessageStreamEvent>;\n }\n\n protected async *wrapStream(iterable: AsyncIterable<unknown>): LLMStream {\n const stream = iterable as AsyncIterable<MessageStreamEvent>;\n let inputTokens = 0;\n let cachedInputTokens = 0;\n let cacheCreationInputTokens = 0;\n\n for await (const event of stream) {\n // Track and yield input tokens from message_start event\n // Anthropic returns cache_read_input_tokens and cache_creation_input_tokens\n if (event.type === \"message_start\") {\n const usage = event.message.usage as {\n input_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n // Total input tokens includes uncached + cached reads + cache writes\n cachedInputTokens = usage.cache_read_input_tokens ?? 0;\n cacheCreationInputTokens = usage.cache_creation_input_tokens ?? 0;\n inputTokens = usage.input_tokens + cachedInputTokens + cacheCreationInputTokens;\n // Yield early so hooks can access input tokens before text streams\n yield {\n text: \"\",\n usage: {\n inputTokens,\n outputTokens: 0,\n totalTokens: inputTokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n },\n rawEvent: event,\n };\n continue;\n }\n\n if (event.type === \"content_block_delta\" && event.delta.type === \"text_delta\") {\n yield { text: event.delta.text ?? \"\", rawEvent: event };\n continue;\n }\n\n if (event.type === \"message_delta\") {\n const usage = event.usage\n ? {\n inputTokens,\n outputTokens: event.usage.output_tokens,\n totalTokens: inputTokens + event.usage.output_tokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n }\n : undefined;\n\n if (event.delta.stop_reason || usage) {\n yield {\n text: \"\",\n finishReason: event.delta.stop_reason ?? undefined,\n usage,\n rawEvent: event,\n };\n }\n continue;\n }\n\n if (event.type === \"message_stop\") {\n yield { text: \"\", finishReason: \"stop\", rawEvent: event };\n }\n }\n }\n\n /**\n * Count tokens in messages using Anthropic's native token counting API.\n *\n * This method provides accurate token estimation for Anthropic models by:\n * - Using the native messages.countTokens() API\n * - Properly handling system messages and conversation structure\n * - Transforming messages to Anthropic's expected format\n *\n * @param messages - The messages to count tokens for\n * @param descriptor - Model descriptor containing the model name\n * @param _spec - Optional model specification (currently unused)\n * @returns Promise resolving to the estimated input token count\n *\n * @throws Never throws - falls back to character-based estimation (4 chars/token) on error\n *\n * @example\n * ```typescript\n * const count = await provider.countTokens(\n * [{ role: \"user\", content: \"Hello!\" }],\n * { provider: \"anthropic\", name: \"claude-3-5-sonnet-20241022\" }\n * );\n * ```\n */\n async countTokens(\n messages: LLMMessage[],\n descriptor: ModelDescriptor,\n _spec?: ModelSpec,\n ): Promise<number> {\n const client = this.client as Anthropic;\n\n // Extract system messages and conversation messages\n const systemMessages = messages.filter((message) => message.role === \"system\");\n const system =\n systemMessages.length > 0 ? systemMessages.map((m) => m.content).join(\"\\n\\n\") : undefined;\n\n const conversation = messages\n .filter(\n (message): message is LLMMessage & { role: \"user\" | \"assistant\" } =>\n message.role !== \"system\",\n )\n .map((message) => ({\n role: message.role,\n content: [\n {\n type: \"text\" as const,\n text: message.content,\n },\n ],\n }));\n\n try {\n // Use the native token counting API\n const response = await client.messages.countTokens({\n model: descriptor.name,\n messages: conversation,\n ...(system ? { system } : {}),\n });\n\n return response.input_tokens;\n } catch (error) {\n // Log the error for debugging\n console.warn(\n `Token counting failed for ${descriptor.name}, using fallback estimation:`,\n error,\n );\n // Fallback to rough estimation if API fails\n const totalChars = messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0);\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN);\n }\n }\n}\n\nexport function createAnthropicProviderFromEnv(): AnthropicMessagesProvider | null {\n return createProviderFromEnv(\"ANTHROPIC_API_KEY\", Anthropic, AnthropicMessagesProvider);\n}\n","/**\n * Google Gemini Model Specifications\n *\n * Model data for Google Gemini models including 3.0, 2.5 and 2.0 series\n * with their specifications, pricing (Standard Paid tier), and capabilities.\n *\n * Pricing source: https://ai.google.dev/gemini-api/docs/pricing\n * Last updated: 2025-11-29\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const GEMINI_MODELS: ModelSpec[] = [\n // Gemini 3 Pro (Preview)\n {\n provider: \"gemini\",\n modelId: \"gemini-3-pro-preview\",\n displayName: \"Gemini 3 Pro (Preview)\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n pricing: {\n input: 2.0, // $2.00 for prompts <= 200k, $4.00 for > 200k (using lower tier)\n output: 12.0, // $12.00 for prompts <= 200k, $18.00 for > 200k\n cachedInput: 0.2, // $0.20 for prompts <= 200k\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 3\",\n releaseDate: \"2025-11-18\",\n notes:\n \"Best model for multimodal understanding, agentic and vibe-coding. Deep Think mode available.\",\n },\n },\n\n // Gemini 2.5 Pro\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-pro\",\n displayName: \"Gemini 2.5 Pro\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n pricing: {\n input: 1.25, // $1.25 for prompts <= 200k, $2.50 for > 200k\n output: 10.0, // $10.00 for prompts <= 200k, $15.00 for > 200k\n cachedInput: 0.125, // $0.125 for prompts <= 200k\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 2.5\",\n releaseDate: \"2025-06\",\n notes: \"State-of-the-art multipurpose model. Excels at coding and complex reasoning.\",\n },\n },\n\n // Gemini 2.5 Flash\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-flash\",\n displayName: \"Gemini 2.5 Flash\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n pricing: {\n input: 0.3, // $0.30 for text/image/video, $1.00 for audio\n output: 2.5,\n cachedInput: 0.03, // $0.03 for text/image/video\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 2.5\",\n releaseDate: \"2025-06\",\n notes: \"First hybrid reasoning model with 1M context and thinking budgets.\",\n },\n },\n\n // Gemini 2.5 Flash-Lite\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-flash-lite\",\n displayName: \"Gemini 2.5 Flash-Lite\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n pricing: {\n input: 0.1, // $0.10 for text/image/video, $0.30 for audio\n output: 0.4,\n cachedInput: 0.01, // $0.01 for text/image/video\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 2.5\",\n releaseDate: \"2025-06\",\n notes: \"Smallest and most cost effective model, built for at scale usage.\",\n },\n },\n\n // Gemini 2.0 Flash\n {\n provider: \"gemini\",\n modelId: \"gemini-2.0-flash\",\n displayName: \"Gemini 2.0 Flash\",\n contextWindow: 1_048_576,\n maxOutputTokens: 8_192,\n pricing: {\n input: 0.1, // $0.10 for text/image/video, $0.70 for audio\n output: 0.4,\n cachedInput: 0.025, // $0.025 for text/image/video\n },\n knowledgeCutoff: \"2024-08\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 2.0\",\n notes: \"Balanced multimodal model with 1M context, built for the era of Agents.\",\n },\n },\n\n // Gemini 2.0 Flash-Lite\n {\n provider: \"gemini\",\n modelId: \"gemini-2.0-flash-lite\",\n displayName: \"Gemini 2.0 Flash-Lite\",\n contextWindow: 1_048_576,\n maxOutputTokens: 8_192,\n pricing: {\n input: 0.075,\n output: 0.3,\n // No context caching available for 2.0-flash-lite\n },\n knowledgeCutoff: \"2024-08\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 2.0\",\n notes: \"Smallest and most cost effective 2.0 model for at scale usage.\",\n },\n },\n];\n","import { FunctionCallingConfigMode, GoogleGenAI } from \"@google/genai\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport { BaseProviderAdapter } from \"./base-provider.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"./constants.js\";\nimport { GEMINI_MODELS } from \"./gemini-models.js\";\nimport { createProviderFromEnv } from \"./utils.js\";\n\ntype GeminiContent = {\n role: string;\n parts: Array<{ text: string }>;\n};\n\ntype GeminiChunk = {\n text?: () => string;\n candidates?: Array<{\n content?: {\n parts?: Array<{ text?: string }>;\n };\n finishReason?: string;\n }>;\n usageMetadata?: {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n totalTokenCount?: number;\n cachedContentTokenCount?: number;\n };\n};\n\nconst GEMINI_ROLE_MAP: Record<LLMMessage[\"role\"], \"user\" | \"model\"> = {\n system: \"user\",\n user: \"user\",\n assistant: \"model\",\n};\n\nexport class GeminiGenerativeProvider extends BaseProviderAdapter {\n readonly providerId = \"gemini\" as const;\n\n supports(descriptor: ModelDescriptor): boolean {\n return descriptor.provider === this.providerId;\n }\n\n getModelSpecs() {\n return GEMINI_MODELS;\n }\n\n protected buildRequestPayload(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n _spec: ModelSpec | undefined,\n messages: LLMMessage[],\n ): {\n model: string;\n contents: Array<{ role: string; parts: Array<{ text: string }> }>;\n config: Record<string, unknown>;\n } {\n // Convert messages to Gemini format (system messages become user+model exchanges)\n const contents = this.convertMessagesToContents(messages);\n const generationConfig = this.buildGenerationConfig(options);\n\n // Build the config object for the new SDK\n const config: Record<string, unknown> = {\n // Note: systemInstruction removed - it doesn't work with countTokens()\n // System messages are now included in contents as user+model exchanges\n ...(generationConfig ? { ...generationConfig } : {}),\n // Explicitly disable function calling to prevent UNEXPECTED_TOOL_CALL errors\n toolConfig: {\n functionCallingConfig: {\n mode: FunctionCallingConfigMode.NONE,\n },\n },\n ...options.extra,\n };\n\n return {\n model: descriptor.name,\n contents: this.convertContentsForNewSDK(contents),\n config,\n };\n }\n\n protected async executeStreamRequest(payload: {\n model: string;\n contents: Array<{ role: string; parts: Array<{ text: string }> }>;\n config: Record<string, unknown>;\n }): Promise<AsyncIterable<GeminiChunk>> {\n const client = this.client as GoogleGenAI;\n const streamResponse = await client.models.generateContentStream(payload);\n return streamResponse as unknown as AsyncIterable<GeminiChunk>;\n }\n\n /**\n * Convert LLM messages to Gemini contents format.\n *\n * For Gemini, we convert system messages to user+model exchanges instead of\n * using systemInstruction, because:\n * 1. systemInstruction doesn't work with countTokens() API\n * 2. This approach gives perfect token counting accuracy (0% error)\n * 3. The model receives and follows system instructions identically\n *\n * System message: \"You are a helpful assistant\"\n * Becomes:\n * - User: \"You are a helpful assistant\"\n * - Model: \"Understood.\"\n */\n private convertMessagesToContents(messages: LLMMessage[]): GeminiContent[] {\n const expandedMessages: LLMMessage[] = [];\n\n for (const message of messages) {\n if (message.role === \"system\") {\n // Convert system message to user+model exchange\n expandedMessages.push({\n role: \"user\",\n content: message.content,\n });\n expandedMessages.push({\n role: \"assistant\",\n content: \"Understood.\",\n });\n } else {\n expandedMessages.push(message);\n }\n }\n\n return this.mergeConsecutiveMessages(expandedMessages);\n }\n\n private mergeConsecutiveMessages(messages: LLMMessage[]): GeminiContent[] {\n if (messages.length === 0) {\n return [];\n }\n\n const result: GeminiContent[] = [];\n let currentGroup: GeminiContent | null = null;\n\n for (const message of messages) {\n const geminiRole = GEMINI_ROLE_MAP[message.role];\n\n if (currentGroup && currentGroup.role === geminiRole) {\n // Merge into current group\n currentGroup.parts.push({ text: message.content });\n } else {\n // Start new group\n if (currentGroup) {\n result.push(currentGroup);\n }\n currentGroup = {\n role: geminiRole,\n parts: [{ text: message.content }],\n };\n }\n }\n\n // Push the last group\n if (currentGroup) {\n result.push(currentGroup);\n }\n\n return result;\n }\n\n private convertContentsForNewSDK(\n contents: GeminiContent[],\n ): Array<{ role: string; parts: Array<{ text: string }> }> {\n // The new SDK expects a simpler format for contents\n return contents.map((content) => ({\n role: content.role,\n parts: content.parts.map((part) => ({ text: part.text })),\n }));\n }\n\n private buildGenerationConfig(options: LLMGenerationOptions) {\n const config: Record<string, unknown> = {};\n\n // Only set maxOutputTokens if explicitly provided\n // Otherwise let Gemini use \"as much as fits\" in the context window\n if (typeof options.maxTokens === \"number\") {\n config.maxOutputTokens = options.maxTokens;\n }\n\n if (typeof options.temperature === \"number\") {\n config.temperature = options.temperature;\n }\n if (typeof options.topP === \"number\") {\n config.topP = options.topP;\n }\n if (options.stopSequences?.length) {\n config.stopSequences = options.stopSequences;\n }\n\n return Object.keys(config).length > 0 ? config : null;\n }\n\n protected async *wrapStream(iterable: AsyncIterable<unknown>): LLMStream {\n const stream = iterable as AsyncIterable<GeminiChunk>;\n for await (const chunk of stream) {\n const text = this.extractText(chunk);\n if (text) {\n yield { text, rawEvent: chunk };\n }\n\n const finishReason = this.extractFinishReason(chunk);\n const usage = this.extractUsage(chunk);\n\n if (finishReason || usage) {\n yield { text: \"\", finishReason, usage, rawEvent: chunk };\n }\n }\n }\n\n private extractText(chunk: GeminiChunk): string {\n if (!chunk?.candidates) {\n return \"\";\n }\n\n return chunk.candidates\n .flatMap((candidate) => candidate.content?.parts ?? [])\n .map((part) => part.text ?? \"\")\n .join(\"\");\n }\n\n private extractFinishReason(chunk: GeminiChunk): string | null {\n const candidate = chunk?.candidates?.find((item) => item.finishReason);\n return candidate?.finishReason ?? null;\n }\n\n private extractUsage(\n chunk: GeminiChunk,\n ):\n | { inputTokens: number; outputTokens: number; totalTokens: number; cachedInputTokens?: number }\n | undefined {\n const usageMetadata = chunk?.usageMetadata;\n if (!usageMetadata) {\n return undefined;\n }\n\n return {\n inputTokens: usageMetadata.promptTokenCount ?? 0,\n outputTokens: usageMetadata.candidatesTokenCount ?? 0,\n totalTokens: usageMetadata.totalTokenCount ?? 0,\n // Gemini returns cached token count in cachedContentTokenCount\n cachedInputTokens: usageMetadata.cachedContentTokenCount ?? 0,\n };\n }\n\n /**\n * Count tokens in messages using Gemini's native token counting API.\n *\n * This method provides accurate token estimation for Gemini models by:\n * - Using the SDK's countTokens() method\n * - Converting system messages to user+model exchanges (same as in generation)\n * - This gives perfect token counting accuracy (0% error vs actual usage)\n *\n * @param messages - The messages to count tokens for\n * @param descriptor - Model descriptor containing the model name\n * @param _spec - Optional model specification (currently unused)\n * @returns Promise resolving to the estimated input token count\n *\n * @throws Never throws - falls back to character-based estimation (4 chars/token) on error\n *\n * @example\n * ```typescript\n * const count = await provider.countTokens(\n * [{ role: \"user\", content: \"Hello!\" }],\n * { provider: \"gemini\", name: \"gemini-1.5-pro\" }\n * );\n * ```\n */\n async countTokens(\n messages: LLMMessage[],\n descriptor: ModelDescriptor,\n _spec?: ModelSpec,\n ): Promise<number> {\n const client = this.client as GoogleGenAI;\n\n // Convert messages to Gemini format (same as buildRequestPayload)\n const contents = this.convertMessagesToContents(messages);\n\n try {\n // Use Gemini's count_tokens method\n const response = await client.models.countTokens({\n model: descriptor.name,\n contents: this.convertContentsForNewSDK(contents),\n // Note: systemInstruction not used - it's not supported by countTokens()\n // and would cause a 2100% token counting error\n });\n return response.totalTokens ?? 0;\n } catch (error) {\n // Log the error for debugging\n console.warn(\n `Token counting failed for ${descriptor.name}, using fallback estimation:`,\n error,\n );\n // Fallback to rough estimation if API fails\n const totalChars = messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0);\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN);\n }\n }\n}\n\nexport function createGeminiProviderFromEnv(): GeminiGenerativeProvider | null {\n return createProviderFromEnv(\"GEMINI_API_KEY\", GoogleGenAI, GeminiGenerativeProvider);\n}\n","/**\n * OpenAI Model Specifications\n *\n * Model data for OpenAI models including GPT-5, GPT-4.1, GPT-4o, and o-series\n * with their specifications, pricing (Standard tier), and capabilities.\n *\n * Pricing source: https://openai.com/api/pricing (Standard tier)\n * Last updated: 2025-11-29\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const OPENAI_MODELS: ModelSpec[] = [\n // GPT-5 Family\n {\n provider: \"openai\",\n modelId: \"gpt-5.1\",\n displayName: \"GPT-5.1\",\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 1.25,\n output: 10.0,\n cachedInput: 0.125,\n },\n knowledgeCutoff: \"2024-09-30\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-5\",\n releaseDate: \"2025-11-12\",\n notes: \"Latest GPT-5 with improved instruction following. 2-3x faster than GPT-5.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5\",\n displayName: \"GPT-5\",\n contextWindow: 272_000,\n maxOutputTokens: 128_000,\n pricing: {\n input: 1.25,\n output: 10.0,\n cachedInput: 0.125,\n },\n knowledgeCutoff: \"2024-09-30\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-5\",\n releaseDate: \"2025-08-07\",\n notes: \"Best model for coding and agentic tasks. Adaptive reasoning with 90% caching discount.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5-mini\",\n displayName: \"GPT-5 Mini\",\n contextWindow: 272_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 0.25,\n output: 2.0,\n cachedInput: 0.025,\n },\n knowledgeCutoff: \"2024-06-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-5\",\n notes: \"Fast and cost-efficient with adaptive reasoning\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5-nano\",\n displayName: \"GPT-5 Nano\",\n contextWindow: 272_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 0.05,\n output: 0.4,\n cachedInput: 0.005,\n },\n knowledgeCutoff: \"2024-05-31\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-5\",\n notes: \"Fastest, most cost-efficient version for well-defined tasks\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5-pro\",\n displayName: \"GPT-5 Pro\",\n contextWindow: 272_000,\n maxOutputTokens: 128_000,\n pricing: {\n input: 15.0,\n output: 120.0,\n // No cached input pricing for gpt-5-pro\n },\n knowledgeCutoff: \"2024-09-30\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"GPT-5\",\n notes: \"Premium tier with enhanced capabilities. Does not support prompt caching.\",\n supportsTemperature: false,\n },\n },\n\n // GPT-4.1 Family\n {\n provider: \"openai\",\n modelId: \"gpt-4.1\",\n displayName: \"GPT-4.1\",\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 2.0,\n output: 8.0,\n cachedInput: 0.5,\n },\n knowledgeCutoff: \"2024-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-4.1\",\n notes: \"Improved GPT-4 with better instruction following\",\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-4.1-mini\",\n displayName: \"GPT-4.1 Mini\",\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 0.4,\n output: 1.6,\n cachedInput: 0.1,\n },\n knowledgeCutoff: \"2024-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-4.1\",\n notes: \"Cost-efficient GPT-4.1 variant\",\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-4.1-nano\",\n displayName: \"GPT-4.1 Nano\",\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 0.1,\n output: 0.4,\n cachedInput: 0.025,\n },\n knowledgeCutoff: \"2024-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-4.1\",\n notes: \"Fastest GPT-4.1 variant for simple tasks\",\n },\n },\n\n // GPT-4o Family\n {\n provider: \"openai\",\n modelId: \"gpt-4o\",\n displayName: \"GPT-4o\",\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n pricing: {\n input: 2.5,\n output: 10.0,\n cachedInput: 1.25,\n },\n knowledgeCutoff: \"2024-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-4o\",\n notes: \"Multimodal model optimized for speed\",\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-4o-mini\",\n displayName: \"GPT-4o Mini\",\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n pricing: {\n input: 0.15,\n output: 0.6,\n cachedInput: 0.075,\n },\n knowledgeCutoff: \"2024-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-4o\",\n notes: \"Fast and affordable multimodal model\",\n },\n },\n\n // o-series (Reasoning models)\n {\n provider: \"openai\",\n modelId: \"o1\",\n displayName: \"o1\",\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n pricing: {\n input: 15.0,\n output: 60.0,\n cachedInput: 7.5,\n },\n knowledgeCutoff: \"2024-12-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"o-series\",\n notes: \"Advanced reasoning model with chain-of-thought\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"o3\",\n displayName: \"o3\",\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n pricing: {\n input: 2.0,\n output: 8.0,\n cachedInput: 0.5,\n },\n knowledgeCutoff: \"2025-01-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"o-series\",\n notes: \"Next-gen reasoning model, more efficient than o1\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"o4-mini\",\n displayName: \"o4 Mini\",\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n pricing: {\n input: 1.1,\n output: 4.4,\n cachedInput: 0.275,\n },\n knowledgeCutoff: \"2025-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"o-series\",\n notes: \"Cost-efficient reasoning model\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"o3-mini\",\n displayName: \"o3 Mini\",\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n pricing: {\n input: 1.1,\n output: 4.4,\n cachedInput: 0.55,\n },\n knowledgeCutoff: \"2025-01-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"o-series\",\n notes: \"Compact reasoning model for cost-sensitive applications\",\n supportsTemperature: false,\n },\n },\n];\n","import OpenAI from \"openai\";\nimport type { ChatCompletionChunk } from \"openai/resources/chat/completions\";\nimport { encoding_for_model, type TiktokenModel } from \"tiktoken\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport { BaseProviderAdapter } from \"./base-provider.js\";\nimport {\n FALLBACK_CHARS_PER_TOKEN,\n OPENAI_MESSAGE_OVERHEAD_TOKENS,\n OPENAI_NAME_FIELD_OVERHEAD_TOKENS,\n OPENAI_REPLY_PRIMING_TOKENS,\n} from \"./constants.js\";\nimport { OPENAI_MODELS } from \"./openai-models.js\";\nimport { createProviderFromEnv } from \"./utils.js\";\n\nconst ROLE_MAP: Record<LLMMessage[\"role\"], \"system\" | \"user\" | \"assistant\"> = {\n system: \"system\",\n user: \"user\",\n assistant: \"assistant\",\n};\n\n// Note: Temperature support is now determined from the ModelSpec passed to stream()\n// instead of being hardcoded at module level\n\nfunction sanitizeExtra(\n extra: Record<string, unknown> | undefined,\n allowTemperature: boolean,\n): Record<string, unknown> | undefined {\n if (!extra) {\n return undefined;\n }\n\n if (allowTemperature || !Object.hasOwn(extra, \"temperature\")) {\n return extra;\n }\n\n return Object.fromEntries(Object.entries(extra).filter(([key]) => key !== \"temperature\"));\n}\n\nexport class OpenAIChatProvider extends BaseProviderAdapter {\n readonly providerId = \"openai\" as const;\n\n supports(descriptor: ModelDescriptor): boolean {\n return descriptor.provider === this.providerId;\n }\n\n getModelSpecs() {\n return OPENAI_MODELS;\n }\n\n protected buildRequestPayload(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n spec: ModelSpec | undefined,\n messages: LLMMessage[],\n ): Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0] {\n const { maxTokens, temperature, topP, stopSequences, extra } = options;\n\n // Use spec metadata to determine temperature support, defaulting to true if spec is unavailable\n const supportsTemperature = spec?.metadata?.supportsTemperature !== false;\n const shouldIncludeTemperature = typeof temperature === \"number\" && supportsTemperature;\n const sanitizedExtra = sanitizeExtra(extra, shouldIncludeTemperature);\n\n return {\n model: descriptor.name,\n messages: messages.map((message) => ({\n role: ROLE_MAP[message.role],\n content: message.content,\n name: message.name,\n })),\n // Only set max_completion_tokens if explicitly provided\n // Otherwise let the API use \"as much as fits\" in the context window\n ...(maxTokens !== undefined ? { max_completion_tokens: maxTokens } : {}),\n top_p: topP,\n stop: stopSequences,\n stream: true,\n stream_options: { include_usage: true },\n ...(sanitizedExtra ?? {}),\n ...(shouldIncludeTemperature ? { temperature } : {}),\n };\n }\n\n protected async executeStreamRequest(\n payload: Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0],\n ): Promise<AsyncIterable<ChatCompletionChunk>> {\n const client = this.client as OpenAI;\n const stream = await client.chat.completions.create(payload);\n return stream as unknown as AsyncIterable<ChatCompletionChunk>;\n }\n\n protected async *wrapStream(iterable: AsyncIterable<unknown>): LLMStream {\n const stream = iterable as AsyncIterable<ChatCompletionChunk>;\n for await (const chunk of stream) {\n const text = chunk.choices.map((choice) => choice.delta?.content ?? \"\").join(\"\");\n if (text) {\n yield { text, rawEvent: chunk };\n }\n\n const finishReason = chunk.choices.find((choice) => choice.finish_reason)?.finish_reason;\n\n // Extract token usage if available (typically in the final chunk)\n // OpenAI returns cached token count in prompt_tokens_details.cached_tokens\n const usage = chunk.usage\n ? {\n inputTokens: chunk.usage.prompt_tokens,\n outputTokens: chunk.usage.completion_tokens,\n totalTokens: chunk.usage.total_tokens,\n cachedInputTokens:\n (chunk.usage as { prompt_tokens_details?: { cached_tokens?: number } })\n .prompt_tokens_details?.cached_tokens ?? 0,\n }\n : undefined;\n\n if (finishReason || usage) {\n yield { text: \"\", finishReason, usage, rawEvent: chunk };\n }\n }\n }\n\n /**\n * Count tokens in messages using OpenAI's tiktoken library.\n *\n * This method provides accurate token estimation for OpenAI models by:\n * - Using the model-specific tokenizer encoding\n * - Accounting for message formatting overhead\n * - Falling back to gpt-4o encoding for unknown models\n *\n * @param messages - The messages to count tokens for\n * @param descriptor - Model descriptor containing the model name\n * @param _spec - Optional model specification (currently unused)\n * @returns Promise resolving to the estimated input token count\n *\n * @throws Never throws - falls back to character-based estimation (4 chars/token) on error\n *\n * @example\n * ```typescript\n * const count = await provider.countTokens(\n * [{ role: \"user\", content: \"Hello!\" }],\n * { provider: \"openai\", name: \"gpt-4\" }\n * );\n * ```\n */\n async countTokens(\n messages: LLMMessage[],\n descriptor: ModelDescriptor,\n _spec?: ModelSpec,\n ): Promise<number> {\n try {\n // Map model names to tiktoken models\n // For models not directly supported, use a reasonable default\n const modelName = descriptor.name as TiktokenModel;\n let encoding;\n\n try {\n encoding = encoding_for_model(modelName);\n } catch {\n // If the specific model isn't supported, fall back to gpt-4o which uses cl100k_base\n encoding = encoding_for_model(\"gpt-4o\");\n }\n\n try {\n let tokenCount = 0;\n\n // Count tokens per message with proper formatting\n // OpenAI's format adds tokens for message boundaries and roles\n // Token overhead based on OpenAI's message formatting\n // See: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n for (const message of messages) {\n // Every message follows <im_start>{role/name}\\n{content}<im_end>\\n\n tokenCount += OPENAI_MESSAGE_OVERHEAD_TOKENS;\n\n const roleText = ROLE_MAP[message.role];\n tokenCount += encoding.encode(roleText).length;\n tokenCount += encoding.encode(message.content ?? \"\").length;\n\n if (message.name) {\n tokenCount += encoding.encode(message.name).length;\n tokenCount += OPENAI_NAME_FIELD_OVERHEAD_TOKENS;\n }\n }\n\n tokenCount += OPENAI_REPLY_PRIMING_TOKENS;\n\n return tokenCount;\n } finally {\n // Always free the encoding to prevent memory leaks\n encoding.free();\n }\n } catch (error) {\n // Log the error for debugging\n console.warn(\n `Token counting failed for ${descriptor.name}, using fallback estimation:`,\n error,\n );\n // If tiktoken fails, provide a rough estimate\n const totalChars = messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0);\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN);\n }\n }\n}\n\nexport function createOpenAIProviderFromEnv(): OpenAIChatProvider | null {\n return createProviderFromEnv(\"OPENAI_API_KEY\", OpenAI, OpenAIChatProvider);\n}\n","import { createAnthropicProviderFromEnv } from \"./anthropic.js\";\nimport { createGeminiProviderFromEnv } from \"./gemini.js\";\nimport { createOpenAIProviderFromEnv } from \"./openai.js\";\nimport type { ProviderAdapter } from \"./provider.js\";\n\nexport type ProviderDiscoverer = () => ProviderAdapter | null | undefined;\n\nconst DISCOVERERS: ProviderDiscoverer[] = [\n createOpenAIProviderFromEnv,\n createAnthropicProviderFromEnv,\n createGeminiProviderFromEnv,\n];\n\nexport function discoverProviderAdapters(): ProviderAdapter[] {\n const adapters: ProviderAdapter[] = [];\n\n for (const discover of DISCOVERERS) {\n const adapter = discover();\n if (adapter) {\n adapters.push(adapter);\n }\n }\n\n return adapters;\n}\n","/**\n * Model Registry\n *\n * Centralized registry for querying LLM model specifications,\n * validating configurations, and estimating costs.\n *\n * Model data is provided by ProviderAdapter implementations and\n * automatically populated when providers are registered.\n */\n\nimport type { ProviderAdapter } from \"../providers/provider.js\";\nimport type { CostEstimate, ModelLimits, ModelSpec } from \"./model-catalog.js\";\n\nexport class ModelRegistry {\n private modelSpecs: ModelSpec[] = [];\n private providerMap = new Map<string, ModelSpec[]>();\n\n /**\n * Register a provider and collect its model specifications\n */\n registerProvider(provider: ProviderAdapter): void {\n const specs = provider.getModelSpecs?.() ?? [];\n\n if (specs.length > 0) {\n this.modelSpecs.push(...specs);\n this.providerMap.set(provider.providerId, specs);\n }\n }\n\n /**\n * Register a custom model specification at runtime\n *\n * Use this to add models that aren't in the built-in catalog, such as:\n * - Fine-tuned models with custom pricing\n * - New models not yet supported by llmist\n * - Custom deployments with different configurations\n *\n * @param spec - Complete model specification\n * @throws {Error} If spec is missing required fields\n *\n * @example\n * ```ts\n * client.modelRegistry.registerModel({\n * provider: \"openai\",\n * modelId: \"ft:gpt-4o-2024-08-06:my-org:custom:abc123\",\n * displayName: \"My Fine-tuned GPT-4o\",\n * contextWindow: 128_000,\n * maxOutputTokens: 16_384,\n * pricing: { input: 7.5, output: 30.0 },\n * knowledgeCutoff: \"2024-08\",\n * features: { streaming: true, functionCalling: true, vision: true }\n * });\n * ```\n */\n registerModel(spec: ModelSpec): void {\n // Validate required fields\n if (!spec.modelId || !spec.provider) {\n throw new Error(\"ModelSpec must have modelId and provider\");\n }\n\n // Check for duplicates\n const existing = this.getModelSpec(spec.modelId);\n if (existing) {\n console.warn(\n `[llmist] Overwriting existing model spec for \"${spec.modelId}\". ` +\n `Previous: ${existing.displayName}, New: ${spec.displayName}`,\n );\n // Remove old spec from arrays\n const index = this.modelSpecs.findIndex((m) => m.modelId === spec.modelId);\n if (index !== -1) {\n this.modelSpecs.splice(index, 1);\n }\n // Remove from provider map\n const providerSpecs = this.providerMap.get(spec.provider);\n if (providerSpecs) {\n const providerIndex = providerSpecs.findIndex((m) => m.modelId === spec.modelId);\n if (providerIndex !== -1) {\n providerSpecs.splice(providerIndex, 1);\n }\n }\n }\n\n // Add to registry\n this.modelSpecs.push(spec);\n\n // Update provider map\n const providerSpecs = this.providerMap.get(spec.provider) ?? [];\n providerSpecs.push(spec);\n this.providerMap.set(spec.provider, providerSpecs);\n }\n\n /**\n * Register multiple custom model specifications at once\n *\n * @param specs - Array of complete model specifications\n *\n * @example\n * ```ts\n * client.modelRegistry.registerModels([\n * { provider: \"openai\", modelId: \"gpt-5\", ... },\n * { provider: \"openai\", modelId: \"gpt-5-mini\", ... }\n * ]);\n * ```\n */\n registerModels(specs: ModelSpec[]): void {\n for (const spec of specs) {\n this.registerModel(spec);\n }\n }\n\n /**\n * Get model specification by model ID\n * @param modelId - Full model identifier (e.g., 'gpt-5', 'claude-sonnet-4-5-20250929')\n * @returns ModelSpec if found, undefined otherwise\n */\n getModelSpec(modelId: string): ModelSpec | undefined {\n return this.modelSpecs.find((model) => model.modelId === modelId);\n }\n\n /**\n * List all models, optionally filtered by provider\n * @param providerId - Optional provider ID to filter by (e.g., 'openai', 'anthropic')\n * @returns Array of ModelSpec objects\n */\n listModels(providerId?: string): ModelSpec[] {\n if (!providerId) {\n return [...this.modelSpecs];\n }\n\n return this.providerMap.get(providerId) ?? [];\n }\n\n /**\n * Get context window and output limits for a model\n * @param modelId - Full model identifier\n * @returns ModelLimits if model found, undefined otherwise\n */\n getModelLimits(modelId: string): ModelLimits | undefined {\n const spec = this.getModelSpec(modelId);\n if (!spec) return undefined;\n\n return {\n contextWindow: spec.contextWindow,\n maxOutputTokens: spec.maxOutputTokens,\n };\n }\n\n /**\n * Estimate API cost for a given model and token usage\n * @param modelId - Full model identifier\n * @param inputTokens - Number of input tokens (total, including cached and cache creation)\n * @param outputTokens - Number of output tokens\n * @param cachedInputTokens - Number of cached input tokens (subset of inputTokens)\n * @param cacheCreationInputTokens - Number of cache creation tokens (subset of inputTokens, Anthropic only)\n * @returns CostEstimate if model found, undefined otherwise\n */\n estimateCost(\n modelId: string,\n inputTokens: number,\n outputTokens: number,\n cachedInputTokens = 0,\n cacheCreationInputTokens = 0,\n ): CostEstimate | undefined {\n const spec = this.getModelSpec(modelId);\n if (!spec) return undefined;\n\n // Pricing is per 1M tokens, so convert to actual cost\n // Cached tokens are charged at a lower rate (or same rate if no cached pricing)\n // Cache creation tokens are charged at a higher rate (Anthropic: 1.25x input)\n const cachedRate = spec.pricing.cachedInput ?? spec.pricing.input;\n const cacheWriteRate = spec.pricing.cacheWriteInput ?? spec.pricing.input;\n const uncachedInputTokens = inputTokens - cachedInputTokens - cacheCreationInputTokens;\n\n const uncachedInputCost = (uncachedInputTokens / 1_000_000) * spec.pricing.input;\n const cachedInputCost = (cachedInputTokens / 1_000_000) * cachedRate;\n const cacheCreationCost = (cacheCreationInputTokens / 1_000_000) * cacheWriteRate;\n const inputCost = uncachedInputCost + cachedInputCost + cacheCreationCost;\n const outputCost = (outputTokens / 1_000_000) * spec.pricing.output;\n const totalCost = inputCost + outputCost;\n\n return {\n inputCost,\n cachedInputCost,\n cacheCreationCost,\n outputCost,\n totalCost,\n currency: \"USD\",\n };\n }\n\n /**\n * Validate that requested token count fits within model limits\n * @param modelId - Full model identifier\n * @param requestedTokens - Total tokens requested (input + output)\n * @returns true if valid, false if model not found or exceeds limits\n */\n validateModelConfig(modelId: string, requestedTokens: number): boolean {\n const limits = this.getModelLimits(modelId);\n if (!limits) return false;\n\n return requestedTokens <= limits.contextWindow;\n }\n\n /**\n * Check if a model supports a specific feature\n * @param modelId - Full model identifier\n * @param feature - Feature to check ('streaming', 'functionCalling', 'vision', etc.)\n * @returns true if model supports feature, false otherwise\n */\n supportsFeature(modelId: string, feature: keyof ModelSpec[\"features\"]): boolean {\n const spec = this.getModelSpec(modelId);\n if (!spec) return false;\n\n return spec.features[feature] === true;\n }\n\n /**\n * Get all models that support a specific feature\n * @param feature - Feature to filter by\n * @param providerId - Optional provider ID to filter by\n * @returns Array of ModelSpec objects that support the feature\n */\n getModelsByFeature(feature: keyof ModelSpec[\"features\"], providerId?: string): ModelSpec[] {\n const models = this.listModels(providerId);\n return models.filter((model) => model.features[feature] === true);\n }\n\n /**\n * Get the most cost-effective model for a given provider and token budget\n * @param inputTokens - Expected input tokens\n * @param outputTokens - Expected output tokens\n * @param providerId - Optional provider ID to filter by\n * @returns ModelSpec with lowest total cost, or undefined if no models found\n */\n getCheapestModel(\n inputTokens: number,\n outputTokens: number,\n providerId?: string,\n ): ModelSpec | undefined {\n const models = this.listModels(providerId);\n if (models.length === 0) return undefined;\n\n let cheapest: { model: ModelSpec; cost: number } | undefined;\n\n for (const model of models) {\n const estimate = this.estimateCost(model.modelId, inputTokens, outputTokens);\n if (!estimate) continue;\n\n if (!cheapest || estimate.totalCost < cheapest.cost) {\n cheapest = { model, cost: estimate.totalCost };\n }\n }\n\n return cheapest?.model;\n }\n}\n","import type { LLMMessage } from \"./messages.js\";\n\nexport interface LLMGenerationOptions {\n model: string;\n messages: LLMMessage[];\n maxTokens?: number;\n temperature?: number;\n topP?: number;\n stopSequences?: string[];\n responseFormat?: \"text\";\n metadata?: Record<string, unknown>;\n extra?: Record<string, unknown>;\n}\n\nexport interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n /** Number of input tokens served from cache (subset of inputTokens) */\n cachedInputTokens?: number;\n /** Number of input tokens written to cache (subset of inputTokens, Anthropic only) */\n cacheCreationInputTokens?: number;\n}\n\nexport interface LLMStreamChunk {\n text: string;\n /**\n * Indicates that the provider has finished producing output and includes the reason if available.\n */\n finishReason?: string | null;\n /**\n * Token usage information, typically available in the final chunk when the stream completes.\n */\n usage?: TokenUsage;\n /**\n * Provider specific payload emitted at the same time as the text chunk. This is useful for debugging and tests.\n */\n rawEvent?: unknown;\n}\n\nexport interface LLMStream extends AsyncIterable<LLMStreamChunk> {}\n\nexport type ProviderIdentifier = string;\n\nexport interface ModelDescriptor {\n provider: string;\n name: string;\n}\n\nexport class ModelIdentifierParser {\n constructor(private readonly defaultProvider: string = \"openai\") {}\n\n parse(identifier: string): ModelDescriptor {\n const trimmed = identifier.trim();\n if (!trimmed) {\n throw new Error(\"Model identifier cannot be empty\");\n }\n\n const [maybeProvider, ...rest] = trimmed.split(\":\");\n if (rest.length === 0) {\n return { provider: this.defaultProvider, name: maybeProvider };\n }\n\n const provider = maybeProvider;\n const name = rest.join(\":\");\n if (!name) {\n throw new Error(\"Model name cannot be empty\");\n }\n\n return { provider, name };\n }\n}\n","/**\n * Quick execution methods for simple use cases.\n *\n * These methods provide convenient shortcuts for common operations\n * without requiring full agent setup.\n *\n * @example\n * ```typescript\n * // Quick completion\n * const answer = await llmist.complete(\"What is 2+2?\");\n *\n * // Quick streaming\n * for await (const chunk of llmist.stream(\"Tell me a story\")) {\n * process.stdout.write(chunk);\n * }\n * ```\n */\n\nimport type { LLMist } from \"./client.js\";\nimport { LLMMessageBuilder } from \"./messages.js\";\nimport { resolveModel } from \"./model-shortcuts.js\";\n\n/**\n * Options for quick execution methods.\n */\nexport interface QuickOptions {\n /** Model to use (supports aliases like \"gpt4\", \"sonnet\", \"flash\") */\n model?: string;\n\n /** Temperature (0-1) */\n temperature?: number;\n\n /** System prompt */\n systemPrompt?: string;\n\n /** Max tokens to generate */\n maxTokens?: number;\n}\n\n/**\n * Quick completion - returns final text response.\n *\n * @param client - LLMist client instance\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Complete text response\n *\n * @example\n * ```typescript\n * const client = new LLMist();\n * const answer = await complete(client, \"What is 2+2?\");\n * console.log(answer); // \"4\" or \"2+2 equals 4\"\n * ```\n */\nexport async function complete(\n client: LLMist,\n prompt: string,\n options: QuickOptions = {},\n): Promise<string> {\n const model = resolveModel(options.model ?? \"gpt-5-nano\");\n\n const builder = new LLMMessageBuilder();\n if (options.systemPrompt) {\n builder.addSystem(options.systemPrompt);\n }\n builder.addUser(prompt);\n\n let fullResponse = \"\";\n for await (const chunk of client.stream({\n model,\n messages: builder.build(),\n temperature: options.temperature,\n maxTokens: options.maxTokens,\n })) {\n fullResponse += chunk.text;\n }\n\n return fullResponse.trim();\n}\n\n/**\n * Quick streaming - returns async generator of text chunks.\n *\n * @param client - LLMist client instance\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Async generator yielding text chunks\n *\n * @example\n * ```typescript\n * const client = new LLMist();\n *\n * for await (const chunk of stream(client, \"Tell me a story\")) {\n * process.stdout.write(chunk);\n * }\n * ```\n */\nexport async function* stream(\n client: LLMist,\n prompt: string,\n options: QuickOptions = {},\n): AsyncGenerator<string> {\n const model = resolveModel(options.model ?? \"gpt-5-nano\");\n\n const builder = new LLMMessageBuilder();\n if (options.systemPrompt) {\n builder.addSystem(options.systemPrompt);\n }\n builder.addUser(prompt);\n\n for await (const chunk of client.stream({\n model,\n messages: builder.build(),\n temperature: options.temperature,\n maxTokens: options.maxTokens,\n })) {\n yield chunk.text;\n }\n}\n","import { AgentBuilder } from \"../agent/builder.js\";\nimport { discoverProviderAdapters } from \"../providers/discovery.js\";\nimport type { ProviderAdapter } from \"../providers/provider.js\";\nimport type { LLMMessage } from \"./messages.js\";\nimport type { ModelSpec } from \"./model-catalog.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"./options.js\";\nimport { ModelIdentifierParser } from \"./options.js\";\nimport {\n complete as completeHelper,\n type QuickOptions,\n stream as streamHelper,\n} from \"./quick-methods.js\";\n\nexport interface LLMistOptions {\n /**\n * Provider adapters to register manually.\n */\n adapters?: ProviderAdapter[];\n /**\n * Default provider prefix applied when a model identifier omits it.\n */\n defaultProvider?: string;\n /**\n * Automatically discover built-in providers based on environment configuration.\n * Enabled by default.\n */\n autoDiscoverProviders?: boolean;\n /**\n * Custom model specifications to register at initialization.\n * Use this to define models not in the built-in catalog, such as:\n * - Fine-tuned models with custom pricing\n * - New models not yet supported by llmist\n * - Custom deployments with different configurations\n *\n * @example\n * ```ts\n * new LLMist({\n * customModels: [{\n * provider: \"openai\",\n * modelId: \"ft:gpt-4o-2024-08-06:my-org:custom:abc123\",\n * displayName: \"My Fine-tuned GPT-4o\",\n * contextWindow: 128_000,\n * maxOutputTokens: 16_384,\n * pricing: { input: 7.5, output: 30.0 },\n * knowledgeCutoff: \"2024-08\",\n * features: { streaming: true, functionCalling: true, vision: true }\n * }]\n * });\n * ```\n */\n customModels?: ModelSpec[];\n}\n\nexport class LLMist {\n private readonly parser: ModelIdentifierParser;\n readonly modelRegistry: ModelRegistry;\n private readonly adapters: ProviderAdapter[];\n\n constructor();\n constructor(adapters: ProviderAdapter[]);\n constructor(adapters: ProviderAdapter[], defaultProvider: string);\n constructor(options: LLMistOptions);\n constructor(...args: [] | [ProviderAdapter[]] | [ProviderAdapter[], string] | [LLMistOptions]) {\n let adapters: ProviderAdapter[] = [];\n let defaultProvider: string | undefined;\n let autoDiscoverProviders = true;\n let customModels: ModelSpec[] = [];\n\n if (args.length === 0) {\n // Use defaults\n } else if (Array.isArray(args[0])) {\n adapters = args[0];\n if (args.length > 1) {\n defaultProvider = args[1];\n }\n } else if (typeof args[0] === \"object\" && args[0] !== null) {\n const options = args[0];\n adapters = options.adapters ?? [];\n defaultProvider = options.defaultProvider;\n customModels = options.customModels ?? [];\n if (typeof options.autoDiscoverProviders === \"boolean\") {\n autoDiscoverProviders = options.autoDiscoverProviders;\n }\n }\n\n const discoveredAdapters = autoDiscoverProviders ? discoverProviderAdapters() : [];\n const combinedAdapters: ProviderAdapter[] = [...adapters];\n for (const adapter of discoveredAdapters) {\n if (!combinedAdapters.some((existing) => existing.providerId === adapter.providerId)) {\n combinedAdapters.push(adapter);\n }\n }\n\n if (combinedAdapters.length === 0) {\n throw new Error(\n \"No LLM providers available. Provide adapters explicitly or set provider API keys in the environment.\",\n );\n }\n\n const resolvedDefaultProvider = defaultProvider ?? combinedAdapters[0]?.providerId ?? \"openai\";\n\n // Sort by priority (descending: higher priority first)\n // Use stable sort to preserve order for equal priorities\n this.adapters = [...combinedAdapters].sort((a, b) => {\n const priorityA = a.priority ?? 0;\n const priorityB = b.priority ?? 0;\n return priorityB - priorityA;\n });\n this.parser = new ModelIdentifierParser(resolvedDefaultProvider);\n this.modelRegistry = new ModelRegistry();\n\n // Register all providers with the model registry\n for (const adapter of this.adapters) {\n this.modelRegistry.registerProvider(adapter);\n }\n\n // Register custom models if provided\n if (customModels.length > 0) {\n this.modelRegistry.registerModels(customModels);\n }\n }\n\n stream(options: LLMGenerationOptions): LLMStream {\n const descriptor = this.parser.parse(options.model);\n const spec = this.modelRegistry.getModelSpec(descriptor.name);\n const adapter = this.resolveAdapter(descriptor);\n return adapter.stream(options, descriptor, spec);\n }\n\n /**\n * Count tokens in messages for a given model.\n *\n * Uses provider-specific token counting methods for accurate estimation:\n * - OpenAI: tiktoken library with model-specific encodings\n * - Anthropic: Native messages.countTokens() API\n * - Gemini: SDK's countTokens() method\n *\n * Falls back to character-based estimation (4 chars/token) if the provider\n * doesn't support native token counting or if counting fails.\n *\n * This is useful for:\n * - Pre-request cost estimation\n * - Context window management\n * - Request batching optimization\n *\n * @param model - Model identifier (e.g., \"openai:gpt-4\", \"anthropic:claude-3-5-sonnet-20241022\")\n * @param messages - Array of messages to count tokens for\n * @returns Promise resolving to the estimated input token count\n *\n * @example\n * ```typescript\n * const client = new LLMist();\n * const messages = [\n * { role: 'system', content: 'You are a helpful assistant.' },\n * { role: 'user', content: 'Hello!' }\n * ];\n *\n * const tokenCount = await client.countTokens('openai:gpt-4', messages);\n * console.log(`Estimated tokens: ${tokenCount}`);\n * ```\n */\n async countTokens(model: string, messages: LLMMessage[]): Promise<number> {\n const descriptor = this.parser.parse(model);\n const spec = this.modelRegistry.getModelSpec(descriptor.name);\n const adapter = this.resolveAdapter(descriptor);\n\n // Check if the provider supports token counting\n if (adapter.countTokens) {\n return adapter.countTokens(messages, descriptor, spec);\n }\n\n // Fallback: rough character-based estimation (4 chars per token)\n const totalChars = messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0);\n return Math.ceil(totalChars / 4);\n }\n\n private resolveAdapter(descriptor: ModelDescriptor): ProviderAdapter {\n const adapter = this.adapters.find((item) => item.supports(descriptor));\n if (!adapter) {\n throw new Error(`No adapter registered for provider ${descriptor.provider}`);\n }\n\n return adapter;\n }\n\n /**\n * Quick completion - returns final text response.\n * Convenient for simple queries without needing agent setup.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Complete text response\n *\n * @example\n * ```typescript\n * const answer = await LLMist.complete(\"What is 2+2?\");\n * console.log(answer); // \"4\" or \"2+2 equals 4\"\n *\n * const answer = await LLMist.complete(\"Tell me a joke\", {\n * model: \"sonnet\",\n * temperature: 0.9\n * });\n * ```\n */\n static async complete(prompt: string, options?: QuickOptions): Promise<string> {\n const client = new LLMist();\n return completeHelper(client, prompt, options);\n }\n\n /**\n * Quick streaming - returns async generator of text chunks.\n * Convenient for streaming responses without needing agent setup.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Async generator yielding text chunks\n *\n * @example\n * ```typescript\n * for await (const chunk of LLMist.stream(\"Tell me a story\")) {\n * process.stdout.write(chunk);\n * }\n *\n * // With options\n * for await (const chunk of LLMist.stream(\"Generate code\", {\n * model: \"gpt4\",\n * systemPrompt: \"You are a coding assistant\"\n * })) {\n * process.stdout.write(chunk);\n * }\n * ```\n */\n static stream(prompt: string, options?: QuickOptions): AsyncGenerator<string> {\n const client = new LLMist();\n return streamHelper(client, prompt, options);\n }\n\n /**\n * Instance method: Quick completion using this client instance.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Complete text response\n */\n async complete(prompt: string, options?: QuickOptions): Promise<string> {\n return completeHelper(this, prompt, options);\n }\n\n /**\n * Instance method: Quick streaming using this client instance.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Async generator yielding text chunks\n */\n streamText(prompt: string, options?: QuickOptions): AsyncGenerator<string> {\n return streamHelper(this, prompt, options);\n }\n\n /**\n * Create a fluent agent builder.\n * Provides a chainable API for configuring and creating agents.\n *\n * @returns AgentBuilder instance for chaining\n *\n * @example\n * ```typescript\n * const agent = LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withSystem(\"You are a helpful assistant\")\n * .withGadgets(Calculator, Weather)\n * .ask(\"What's the weather in Paris?\");\n *\n * for await (const event of agent.run()) {\n * // handle events\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Quick one-liner for simple queries\n * const answer = await LLMist.createAgent()\n * .withModel(\"gpt4-mini\")\n * .askAndCollect(\"What is 2+2?\");\n * ```\n */\n static createAgent(): AgentBuilder {\n return new AgentBuilder();\n }\n\n /**\n * Create agent builder with this client instance.\n * Useful when you want to reuse a configured client.\n *\n * @returns AgentBuilder instance using this client\n *\n * @example\n * ```typescript\n * const client = new LLMist({ ... });\n *\n * const agent = client.createAgent()\n * .withModel(\"sonnet\")\n * .ask(\"Hello\");\n * ```\n */\n createAgent(): AgentBuilder {\n return new AgentBuilder(this);\n }\n}\n","/**\n * Fluent builder for creating agents with delightful DX.\n *\n * @example\n * ```typescript\n * const agent = await LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withSystem(\"You are a helpful assistant\")\n * .withGadgets(Calculator, Weather)\n * .withMaxIterations(10)\n * .ask(\"What's the weather in Paris?\");\n *\n * for await (const event of agent.run()) {\n * // process events\n * }\n * ```\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { PromptConfig } from \"../core/prompt-config.js\";\nimport type { GadgetOrClass } from \"../gadgets/registry.js\";\nimport { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { TextOnlyHandler } from \"../gadgets/types.js\";\nimport { Agent, type AgentOptions } from \"./agent.js\";\nimport { AGENT_INTERNAL_KEY } from \"./agent-internal-key.js\";\nimport { collectText, type EventHandlers } from \"./event-handlers.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n/**\n * Message for conversation history.\n */\nexport type HistoryMessage = { user: string } | { assistant: string } | { system: string };\n\n/**\n * Fluent builder for creating agents.\n *\n * Provides a chainable API for configuring and creating agents,\n * making the code more expressive and easier to read.\n */\nexport class AgentBuilder {\n private client?: LLMist;\n private model?: string;\n private systemPrompt?: string;\n private temperature?: number;\n private maxIterations?: number;\n private logger?: Logger<ILogObj>;\n private hooks?: AgentHooks;\n private promptConfig?: PromptConfig;\n private gadgets: GadgetOrClass[] = [];\n private initialMessages: Array<{\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n }> = [];\n private onHumanInputRequired?: (question: string) => Promise<string>;\n private gadgetStartPrefix?: string;\n private gadgetEndPrefix?: string;\n private gadgetArgPrefix?: string;\n private textOnlyHandler?: TextOnlyHandler;\n private textWithGadgetsHandler?: {\n gadgetName: string;\n parameterMapping: (text: string) => Record<string, unknown>;\n resultMapping?: (text: string) => string;\n };\n private stopOnGadgetError?: boolean;\n private shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n private defaultGadgetTimeoutMs?: number;\n private gadgetOutputLimit?: boolean;\n private gadgetOutputLimitPercent?: number;\n\n constructor(client?: LLMist) {\n this.client = client;\n }\n\n /**\n * Set the model to use.\n * Supports aliases like \"gpt4\", \"sonnet\", \"flash\".\n *\n * @param model - Model name or alias\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withModel(\"sonnet\") // Alias\n * .withModel(\"gpt-5-nano\") // Auto-detects provider\n * .withModel(\"openai:gpt-5\") // Explicit provider\n * ```\n */\n withModel(model: string): this {\n this.model = resolveModel(model);\n return this;\n }\n\n /**\n * Set the system prompt.\n *\n * @param prompt - System prompt\n * @returns This builder for chaining\n */\n withSystem(prompt: string): this {\n this.systemPrompt = prompt;\n return this;\n }\n\n /**\n * Set the temperature (0-1).\n *\n * @param temperature - Temperature value\n * @returns This builder for chaining\n */\n withTemperature(temperature: number): this {\n this.temperature = temperature;\n return this;\n }\n\n /**\n * Set maximum iterations.\n *\n * @param max - Maximum number of iterations\n * @returns This builder for chaining\n */\n withMaxIterations(max: number): this {\n this.maxIterations = max;\n return this;\n }\n\n /**\n * Set logger instance.\n *\n * @param logger - Logger instance\n * @returns This builder for chaining\n */\n withLogger(logger: Logger<ILogObj>): this {\n this.logger = logger;\n return this;\n }\n\n /**\n * Add hooks for agent lifecycle events.\n *\n * @param hooks - Agent hooks configuration\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * import { HookPresets } from 'llmist/hooks';\n *\n * .withHooks(HookPresets.logging())\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing()\n * ))\n * ```\n */\n withHooks(hooks: AgentHooks): this {\n this.hooks = hooks;\n return this;\n }\n\n /**\n * Configure custom prompts for gadget system messages.\n *\n * @param config - Prompt configuration object\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withPromptConfig({\n * mainInstruction: \"Use the gadget markers below:\",\n * rules: [\"Always use markers\", \"Never use function calling\"]\n * })\n * ```\n */\n withPromptConfig(config: PromptConfig): this {\n this.promptConfig = config;\n return this;\n }\n\n /**\n * Add gadgets (classes or instances).\n * Can be called multiple times to add more gadgets.\n *\n * @param gadgets - Gadget classes or instances\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgets(Calculator, Weather, Email)\n * .withGadgets(new Calculator(), new Weather())\n * .withGadgets(createGadget({ ... }))\n * ```\n */\n withGadgets(...gadgets: GadgetOrClass[]): this {\n this.gadgets.push(...gadgets);\n return this;\n }\n\n /**\n * Add conversation history messages.\n * Useful for continuing previous conversations.\n *\n * @param messages - Array of history messages\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withHistory([\n * { user: \"Hello\" },\n * { assistant: \"Hi there!\" },\n * { user: \"How are you?\" },\n * { assistant: \"I'm doing well, thanks!\" }\n * ])\n * ```\n */\n withHistory(messages: HistoryMessage[]): this {\n for (const msg of messages) {\n if (\"user\" in msg) {\n this.initialMessages.push({ role: \"user\", content: msg.user });\n } else if (\"assistant\" in msg) {\n this.initialMessages.push({ role: \"assistant\", content: msg.assistant });\n } else if (\"system\" in msg) {\n this.initialMessages.push({ role: \"system\", content: msg.system });\n }\n }\n return this;\n }\n\n /**\n * Add a single message to the conversation history.\n *\n * @param message - Single history message\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .addMessage({ user: \"Hello\" })\n * .addMessage({ assistant: \"Hi there!\" })\n * ```\n */\n addMessage(message: HistoryMessage): this {\n return this.withHistory([message]);\n }\n\n /**\n * Set the human input handler for interactive conversations.\n *\n * @param handler - Function to handle human input requests\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .onHumanInput(async (question) => {\n * return await promptUser(question);\n * })\n * ```\n */\n onHumanInput(handler: (question: string) => Promise<string>): this {\n this.onHumanInputRequired = handler;\n return this;\n }\n\n /**\n * Set custom gadget marker prefix.\n *\n * @param prefix - Custom start prefix for gadget markers\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetStartPrefix(\"<<GADGET_START>>\")\n * ```\n */\n withGadgetStartPrefix(prefix: string): this {\n this.gadgetStartPrefix = prefix;\n return this;\n }\n\n /**\n * Set custom gadget marker suffix.\n *\n * @param suffix - Custom end suffix for gadget markers\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetEndPrefix(\"<<GADGET_END>>\")\n * ```\n */\n withGadgetEndPrefix(suffix: string): this {\n this.gadgetEndPrefix = suffix;\n return this;\n }\n\n /**\n * Set custom argument prefix for block format parameters.\n *\n * @param prefix - Custom prefix for argument markers (default: \"!!!ARG:\")\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetArgPrefix(\"<<ARG>>\")\n * ```\n */\n withGadgetArgPrefix(prefix: string): this {\n this.gadgetArgPrefix = prefix;\n return this;\n }\n\n /**\n * Set the text-only handler strategy.\n *\n * Controls what happens when the LLM returns text without calling any gadgets:\n * - \"terminate\": End the agent loop (default)\n * - \"acknowledge\": Continue the loop for another iteration\n * - \"wait_for_input\": Wait for human input\n * - Custom handler: Provide a function for dynamic behavior\n *\n * @param handler - Text-only handler strategy or custom handler\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Simple strategy\n * .withTextOnlyHandler(\"acknowledge\")\n *\n * // Custom handler\n * .withTextOnlyHandler({\n * type: \"custom\",\n * handler: async (context) => {\n * if (context.text.includes(\"?\")) {\n * return { action: \"wait_for_input\", question: context.text };\n * }\n * return { action: \"continue\" };\n * }\n * })\n * ```\n */\n withTextOnlyHandler(handler: TextOnlyHandler): this {\n this.textOnlyHandler = handler;\n return this;\n }\n\n /**\n * Set the handler for text content that appears alongside gadget calls.\n *\n * When set, text accompanying gadget responses will be wrapped as a\n * synthetic gadget call before the actual gadget results in the\n * conversation history.\n *\n * @param handler - Configuration for wrapping text\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Wrap text as TellUser gadget\n * .withTextWithGadgetsHandler({\n * gadgetName: \"TellUser\",\n * parameterMapping: (text) => ({ message: text, done: false, type: \"info\" }),\n * resultMapping: (text) => `ℹ️ ${text}`,\n * })\n * ```\n */\n withTextWithGadgetsHandler(handler: {\n gadgetName: string;\n parameterMapping: (text: string) => Record<string, unknown>;\n resultMapping?: (text: string) => string;\n }): this {\n this.textWithGadgetsHandler = handler;\n return this;\n }\n\n /**\n * Set whether to stop gadget execution on first error.\n *\n * When true (default), if a gadget fails:\n * - Subsequent gadgets in the same response are skipped\n * - LLM stream is cancelled to save costs\n * - Agent loop continues with error in context\n *\n * When false:\n * - All gadgets in the response still execute\n * - LLM stream continues to completion\n *\n * @param stop - Whether to stop on gadget error\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withStopOnGadgetError(false)\n * ```\n */\n withStopOnGadgetError(stop: boolean): this {\n this.stopOnGadgetError = stop;\n return this;\n }\n\n /**\n * Set custom error handling logic.\n *\n * Provides fine-grained control over whether to continue after different types of errors.\n * Overrides `stopOnGadgetError` when provided.\n *\n * **Note:** This builder method configures the underlying `shouldContinueAfterError` option\n * in `AgentOptions`. The method is named `withErrorHandler` for better developer experience,\n * but maps to the `shouldContinueAfterError` property internally.\n *\n * @param handler - Function that decides whether to continue after an error.\n * Return `true` to continue execution, `false` to stop.\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withErrorHandler((context) => {\n * // Stop on parse errors, continue on validation/execution errors\n * if (context.errorType === \"parse\") {\n * return false;\n * }\n * if (context.error.includes(\"CRITICAL\")) {\n * return false;\n * }\n * return true;\n * })\n * ```\n */\n withErrorHandler(\n handler: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>,\n ): this {\n this.shouldContinueAfterError = handler;\n return this;\n }\n\n /**\n * Set default timeout for gadget execution.\n *\n * @param timeoutMs - Timeout in milliseconds (must be non-negative)\n * @returns This builder for chaining\n * @throws {Error} If timeout is negative\n *\n * @example\n * ```typescript\n * .withDefaultGadgetTimeout(5000) // 5 second timeout\n * ```\n */\n withDefaultGadgetTimeout(timeoutMs: number): this {\n if (timeoutMs < 0) {\n throw new Error(\"Timeout must be a non-negative number\");\n }\n this.defaultGadgetTimeoutMs = timeoutMs;\n return this;\n }\n\n /**\n * Enable or disable gadget output limiting.\n *\n * When enabled, gadget outputs exceeding the configured limit are stored\n * and can be browsed using the GadgetOutputViewer gadget.\n *\n * @param enabled - Whether to enable output limiting (default: true)\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetOutputLimit(false) // Disable output limiting\n * ```\n */\n withGadgetOutputLimit(enabled: boolean): this {\n this.gadgetOutputLimit = enabled;\n return this;\n }\n\n /**\n * Set the maximum gadget output as a percentage of the model's context window.\n *\n * Outputs exceeding this limit are stored for later browsing with GadgetOutputViewer.\n *\n * @param percent - Percentage of context window (1-100, default: 15)\n * @returns This builder for chaining\n * @throws {Error} If percent is not between 1 and 100\n *\n * @example\n * ```typescript\n * .withGadgetOutputLimitPercent(25) // 25% of context window\n * ```\n */\n withGadgetOutputLimitPercent(percent: number): this {\n if (percent < 1 || percent > 100) {\n throw new Error(\"Output limit percent must be between 1 and 100\");\n }\n this.gadgetOutputLimitPercent = percent;\n return this;\n }\n\n /**\n * Add a synthetic gadget call to the conversation history.\n *\n * This is useful for in-context learning - showing the LLM what \"past self\"\n * did correctly so it mimics the pattern. The call is formatted with proper\n * markers and parameter format.\n *\n * @param gadgetName - Name of the gadget\n * @param parameters - Parameters passed to the gadget\n * @param result - Result returned by the gadget\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withSyntheticGadgetCall(\n * 'TellUser',\n * {\n * message: '👋 Hello!\\n\\nHere\\'s what I can do:\\n- Analyze code\\n- Run commands',\n * done: false,\n * type: 'info'\n * },\n * 'ℹ️ 👋 Hello!\\n\\nHere\\'s what I can do:\\n- Analyze code\\n- Run commands'\n * )\n * ```\n */\n withSyntheticGadgetCall(\n gadgetName: string,\n parameters: Record<string, unknown>,\n result: string,\n ): this {\n const startPrefix = this.gadgetStartPrefix ?? GADGET_START_PREFIX;\n const endPrefix = this.gadgetEndPrefix ?? GADGET_END_PREFIX;\n\n const paramStr = this.formatBlockParameters(parameters, \"\");\n\n // Assistant message with gadget call\n this.initialMessages.push({\n role: \"assistant\",\n content: `${startPrefix}${gadgetName}\\n${paramStr}\\n${endPrefix}`,\n });\n\n // User message with result\n this.initialMessages.push({\n role: \"user\",\n content: `Result: ${result}`,\n });\n\n return this;\n }\n\n /**\n * Format parameters as block format with JSON Pointer paths.\n */\n private formatBlockParameters(params: Record<string, unknown>, prefix: string): string {\n const lines: string[] = [];\n const argPrefix = this.gadgetArgPrefix ?? GADGET_ARG_PREFIX;\n\n for (const [key, value] of Object.entries(params)) {\n const fullPath = prefix ? `${prefix}/${key}` : key;\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n const itemPath = `${fullPath}/${index}`;\n if (typeof item === \"object\" && item !== null) {\n lines.push(this.formatBlockParameters(item as Record<string, unknown>, itemPath));\n } else {\n lines.push(`${argPrefix}${itemPath}`);\n lines.push(String(item));\n }\n });\n } else if (typeof value === \"object\" && value !== null) {\n lines.push(this.formatBlockParameters(value as Record<string, unknown>, fullPath));\n } else {\n lines.push(`${argPrefix}${fullPath}`);\n lines.push(String(value));\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n /**\n * Build and create the agent with the given user prompt.\n * Returns the Agent instance ready to run.\n *\n * @param userPrompt - User's question or request\n * @returns Configured Agent instance\n *\n * @example\n * ```typescript\n * const agent = await LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator)\n * .ask(\"What is 2+2?\");\n *\n * for await (const event of agent.run()) {\n * // handle events\n * }\n * ```\n */\n ask(userPrompt: string): Agent {\n // Lazy import to avoid circular dependency\n if (!this.client) {\n const { LLMist: LLMistClass } =\n require(\"../core/client.js\") as typeof import(\"../core/client.js\");\n this.client = new LLMistClass();\n }\n const registry = GadgetRegistry.from(this.gadgets);\n\n const options: AgentOptions = {\n client: this.client,\n model: this.model ?? \"openai:gpt-5-nano\",\n systemPrompt: this.systemPrompt,\n userPrompt,\n registry,\n maxIterations: this.maxIterations,\n temperature: this.temperature,\n logger: this.logger,\n hooks: this.hooks,\n promptConfig: this.promptConfig,\n initialMessages: this.initialMessages,\n onHumanInputRequired: this.onHumanInputRequired,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n textOnlyHandler: this.textOnlyHandler,\n textWithGadgetsHandler: this.textWithGadgetsHandler,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinueAfterError: this.shouldContinueAfterError,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n gadgetOutputLimit: this.gadgetOutputLimit,\n gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,\n };\n\n return new Agent(AGENT_INTERNAL_KEY, options);\n }\n\n /**\n * Build, run, and collect only the text response.\n * Convenient for simple queries where you just want the final answer.\n *\n * @param userPrompt - User's question or request\n * @returns Promise resolving to the complete text response\n *\n * @example\n * ```typescript\n * const answer = await LLMist.createAgent()\n * .withModel(\"gpt4-mini\")\n * .withGadgets(Calculator)\n * .askAndCollect(\"What is 42 * 7?\");\n *\n * console.log(answer); // \"294\"\n * ```\n */\n async askAndCollect(userPrompt: string): Promise<string> {\n const agent = this.ask(userPrompt);\n return collectText(agent.run());\n }\n\n /**\n * Build and run with event handlers.\n * Combines agent creation and event handling in one call.\n *\n * @param userPrompt - User's question or request\n * @param handlers - Event handlers\n *\n * @example\n * ```typescript\n * await LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator)\n * .askWith(\"What is 2+2?\", {\n * onText: (text) => console.log(\"LLM:\", text),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\n async askWith(userPrompt: string, handlers: EventHandlers): Promise<void> {\n const agent = this.ask(userPrompt);\n await agent.runWith(handlers);\n }\n\n /**\n * Build the agent without a user prompt.\n *\n * Returns an Agent instance that can be inspected (e.g., check registered gadgets)\n * but cannot be run without first calling .ask(prompt).\n *\n * This is useful for:\n * - Testing: Inspect the registry, configuration, etc.\n * - Advanced use cases: Build agent configuration separately from execution\n *\n * @returns Configured Agent instance (without user prompt)\n *\n * @example\n * ```typescript\n * // Build agent for inspection\n * const agent = new AgentBuilder()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator, Weather)\n * .build();\n *\n * // Inspect registered gadgets\n * console.log(agent.getRegistry().getNames()); // ['Calculator', 'Weather']\n *\n * // Note: Calling agent.run() will throw an error\n * // Use .ask(prompt) instead if you want to run the agent\n * ```\n */\n build(): Agent {\n // Lazy import to avoid circular dependency\n if (!this.client) {\n const { LLMist: LLMistClass } =\n require(\"../core/client.js\") as typeof import(\"../core/client.js\");\n this.client = new LLMistClass();\n }\n const registry = GadgetRegistry.from(this.gadgets);\n\n const options: AgentOptions = {\n client: this.client,\n model: this.model ?? \"openai:gpt-5-nano\",\n systemPrompt: this.systemPrompt,\n // No userPrompt - agent.run() will throw if called directly\n registry,\n maxIterations: this.maxIterations,\n temperature: this.temperature,\n logger: this.logger,\n hooks: this.hooks,\n promptConfig: this.promptConfig,\n initialMessages: this.initialMessages,\n onHumanInputRequired: this.onHumanInputRequired,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n textOnlyHandler: this.textOnlyHandler,\n textWithGadgetsHandler: this.textWithGadgetsHandler,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinueAfterError: this.shouldContinueAfterError,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n gadgetOutputLimit: this.gadgetOutputLimit,\n gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,\n };\n\n return new Agent(AGENT_INTERNAL_KEY, options);\n }\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 gadget: \"gadget\",\n} as const;\n\n/** Valid log level names */\nexport const LOG_LEVELS = [\"silly\", \"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"] as const;\nexport type LogLevelName = (typeof LOG_LEVELS)[number];\n\n/** Default model used when --model is not specified */\nexport const DEFAULT_MODEL = \"openai:gpt-5-nano\";\n\n/** Command-line option flags */\nexport const OPTION_FLAGS = {\n model: \"-m, --model <identifier>\",\n systemPrompt: \"-s, --system <prompt>\",\n temperature: \"-t, --temperature <value>\",\n maxTokens: \"--max-tokens <count>\",\n maxIterations: \"-i, --max-iterations <count>\",\n gadgetModule: \"-g, --gadget <module>\",\n logLevel: \"--log-level <level>\",\n logFile: \"--log-file <path>\",\n logReset: \"--log-reset\",\n logLlmRequests: \"--log-llm-requests [dir]\",\n logLlmResponses: \"--log-llm-responses [dir]\",\n noBuiltins: \"--no-builtins\",\n noBuiltinInteraction: \"--no-builtin-interaction\",\n quiet: \"-q, --quiet\",\n} as const;\n\n/** Human-readable descriptions for command-line options */\nexport const OPTION_DESCRIPTIONS = {\n model: \"Model identifier, e.g. openai:gpt-5-nano or anthropic:claude-sonnet-4-5.\",\n systemPrompt: \"Optional system prompt prepended to the conversation.\",\n temperature: \"Sampling temperature between 0 and 2.\",\n maxTokens: \"Maximum number of output tokens requested from the model.\",\n maxIterations: \"Maximum number of agent loop iterations before exiting.\",\n gadgetModule:\n \"Path or module specifier for a gadget export. Repeat to register multiple gadgets.\",\n logLevel: \"Log level: silly, trace, debug, info, warn, error, fatal.\",\n logFile: \"Path to log file. When set, logs are written to file instead of stderr.\",\n logReset: \"Reset (truncate) the log file at session start instead of appending.\",\n logLlmRequests: \"Save raw LLM requests as plain text. Optional dir, defaults to ~/.llmist/logs/requests/\",\n logLlmResponses: \"Save raw LLM responses as plain text. Optional dir, defaults to ~/.llmist/logs/responses/\",\n noBuiltins: \"Disable built-in gadgets (AskUser, TellUser).\",\n noBuiltinInteraction: \"Disable interactive gadgets (AskUser) while keeping TellUser.\",\n quiet: \"Suppress all output except content (text and TellUser messages).\",\n} as const;\n\n/** Prefix for summary output written to stderr */\nexport const SUMMARY_PREFIX = \"[llmist]\";\n","import { Command, InvalidArgumentError } from \"commander\";\n\nimport packageJson from \"../../package.json\";\n\nimport { registerAgentCommand } from \"./agent-command.js\";\nimport { registerCompleteCommand } from \"./complete-command.js\";\nimport {\n type CLIConfig,\n type CustomCommandConfig,\n getCustomCommandNames,\n loadConfig,\n} from \"./config.js\";\nimport { registerGadgetCommand } from \"./gadget-command.js\";\nimport { registerModelsCommand } from \"./models-command.js\";\nimport { registerCustomCommand } from \"./custom-command.js\";\nimport {\n CLI_DESCRIPTION,\n CLI_NAME,\n LOG_LEVELS,\n type LogLevelName,\n OPTION_DESCRIPTIONS,\n OPTION_FLAGS,\n} from \"./constants.js\";\nimport type { CLIEnvironment, CLILoggerConfig } from \"./environment.js\";\nimport { createDefaultEnvironment } from \"./environment.js\";\n\n/**\n * Parses and validates the log level option value.\n */\nfunction parseLogLevel(value: string): LogLevelName {\n const normalized = value.toLowerCase() as LogLevelName;\n if (!LOG_LEVELS.includes(normalized)) {\n throw new InvalidArgumentError(`Log level must be one of: ${LOG_LEVELS.join(\", \")}`);\n }\n return normalized;\n}\n\n/**\n * Global CLI options that apply to all commands.\n */\ninterface GlobalOptions {\n logLevel?: LogLevelName;\n logFile?: string;\n logReset?: boolean;\n}\n\n/**\n * Creates and configures the CLI program with complete and agent commands.\n *\n * @param env - CLI environment configuration for I/O and dependencies\n * @param config - Optional CLI configuration loaded from config file\n * @returns Configured Commander program ready for parsing\n */\nexport function createProgram(env: CLIEnvironment, config?: CLIConfig): Command {\n const program = new Command();\n\n program\n .name(CLI_NAME)\n .description(CLI_DESCRIPTION)\n .version(packageJson.version)\n .option(OPTION_FLAGS.logLevel, OPTION_DESCRIPTIONS.logLevel, parseLogLevel)\n .option(OPTION_FLAGS.logFile, OPTION_DESCRIPTIONS.logFile)\n .option(OPTION_FLAGS.logReset, OPTION_DESCRIPTIONS.logReset)\n .configureOutput({\n writeOut: (str) => env.stdout.write(str),\n writeErr: (str) => env.stderr.write(str),\n });\n\n // Register built-in commands with config defaults\n registerCompleteCommand(program, env, config?.complete);\n registerAgentCommand(program, env, config?.agent);\n registerModelsCommand(program, env);\n registerGadgetCommand(program, env);\n\n // Register custom commands from config\n if (config) {\n const customNames = getCustomCommandNames(config);\n for (const name of customNames) {\n const cmdConfig = config[name] as CustomCommandConfig;\n registerCustomCommand(program, name, cmdConfig, env);\n }\n }\n\n return program;\n}\n\n/**\n * Options for runCLI function.\n */\nexport interface RunCLIOptions {\n /** Environment overrides for testing or customization */\n env?: Partial<CLIEnvironment>;\n /** Config override - if provided, skips loading from file. Use {} to disable config. */\n config?: CLIConfig;\n}\n\n/**\n * Main entry point for running the CLI.\n * Creates environment, parses arguments, and executes the appropriate command.\n *\n * @param overrides - Optional environment overrides or options object\n */\nexport async function runCLI(\n overrides: Partial<CLIEnvironment> | RunCLIOptions = {},\n): Promise<void> {\n // Handle both old signature (Partial<CLIEnvironment>) and new signature (RunCLIOptions)\n const opts: RunCLIOptions =\n \"env\" in overrides || \"config\" in overrides\n ? (overrides as RunCLIOptions)\n : { env: overrides as Partial<CLIEnvironment> };\n\n // Load config early (before program creation) - errors here should fail fast\n // If config is provided in options, use it instead of loading from file\n const config = opts.config !== undefined ? opts.config : loadConfig();\n const envOverrides = opts.env ?? {};\n\n // First pass: parse global options only (skip if help requested)\n const preParser = new Command();\n preParser\n .option(OPTION_FLAGS.logLevel, OPTION_DESCRIPTIONS.logLevel, parseLogLevel)\n .option(OPTION_FLAGS.logFile, OPTION_DESCRIPTIONS.logFile)\n .option(OPTION_FLAGS.logReset, OPTION_DESCRIPTIONS.logReset)\n .allowUnknownOption()\n .allowExcessArguments()\n .helpOption(false); // Don't intercept --help\n\n preParser.parse(process.argv);\n const globalOpts = preParser.opts<GlobalOptions>();\n\n // Create environment with logger config from global options\n // Priority: CLI flags > config file > defaults\n const loggerConfig: CLILoggerConfig = {\n logLevel: globalOpts.logLevel ?? config.global?.[\"log-level\"],\n logFile: globalOpts.logFile ?? config.global?.[\"log-file\"],\n logReset: globalOpts.logReset ?? config.global?.[\"log-reset\"],\n };\n\n const defaultEnv = createDefaultEnvironment(loggerConfig);\n const env: CLIEnvironment = { ...defaultEnv, ...envOverrides };\n const program = createProgram(env, config);\n await program.parseAsync(env.argv);\n}\n","{\n \"name\": \"llmist\",\n \"version\": \"1.1.0\",\n \"description\": \"Universal TypeScript LLM client with streaming-first agent framework. Works with any model - no structured outputs or native tool calling required. Implements its own flexible grammar for function calling.\",\n \"type\": \"module\",\n \"main\": \"dist/index.cjs\",\n \"module\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./testing\": {\n \"import\": {\n \"types\": \"./dist/testing/index.d.ts\",\n \"default\": \"./dist/testing/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/testing/index.d.cts\",\n \"default\": \"./dist/testing/index.cjs\"\n }\n }\n },\n \"scripts\": {\n \"cli\": \"bun run scripts/cli-runner.ts\",\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"biome lint .\",\n \"format\": \"biome format --write .\",\n \"check\": \"biome check --write .\",\n \"test\": \"bun test\",\n \"test:unit\": \"bun test src/agent src/core src/gadgets src/providers src/testing\",\n \"test:watch\": \"bun test --watch\",\n \"test:e2e\": \"bun test src/e2e --timeout 60000 --bail 1\",\n \"test:e2e:watch\": \"bun test src/e2e --watch --timeout 60000\",\n \"test:all\": \"bun run test && bun run test:e2e\",\n \"clean\": \"rimraf dist\",\n \"prepare\": \"node scripts/install-hooks.js || true\",\n \"release:dry\": \"bunx semantic-release --dry-run\"\n },\n \"bin\": {\n \"llmist\": \"dist/cli.js\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/zbigniewsobiecki/llmist.git\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"files\": [\n \"dist\"\n ],\n \"keywords\": [\n \"llm\",\n \"ai\",\n \"agent\",\n \"agents\",\n \"openai\",\n \"anthropic\",\n \"claude\",\n \"gemini\",\n \"gpt\",\n \"streaming\",\n \"function-calling\",\n \"tool-calling\",\n \"typescript\",\n \"universal-client\",\n \"multi-provider\",\n \"hooks\",\n \"gadgets\"\n ],\n \"author\": \"\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@anthropic-ai/sdk\": \"^0.69.0\",\n \"@google/genai\": \"^1.27.0\",\n \"chalk\": \"^5.6.2\",\n \"commander\": \"^12.1.0\",\n \"eta\": \"^4.4.1\",\n \"js-toml\": \"^1.0.2\",\n \"js-yaml\": \"^4.1.0\",\n \"marked\": \"^15.0.12\",\n \"marked-terminal\": \"^7.3.0\",\n \"openai\": \"^6.0.0\",\n \"tiktoken\": \"^1.0.22\",\n \"tslog\": \"^4.10.2\",\n \"zod\": \"^4.1.12\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.3.2\",\n \"@commitlint/cli\": \"^20.1.0\",\n \"@commitlint/config-conventional\": \"^20.0.0\",\n \"@semantic-release/changelog\": \"^6.0.3\",\n \"@semantic-release/git\": \"^10.0.1\",\n \"@types/js-yaml\": \"^4.0.9\",\n \"@types/marked-terminal\": \"^6.1.1\",\n \"@types/node\": \"^20.12.7\",\n \"bun-types\": \"^1.3.2\",\n \"dotenv\": \"^17.2.3\",\n \"rimraf\": \"^5.0.5\",\n \"semantic-release\": \"^25.0.2\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.4.5\"\n }\n}\n","import { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport type { Command } from \"commander\";\nimport { AgentBuilder } from \"../agent/builder.js\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { TokenUsage } from \"../core/options.js\";\nimport { GadgetRegistry } from \"../gadgets/registry.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"../providers/constants.js\";\nimport { builtinGadgets } from \"./builtin-gadgets.js\";\nimport type { AgentConfig } from \"./config.js\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { loadGadgets } from \"./gadgets.js\";\nimport { formatLlmRequest, resolveLogDir, writeLogFile } from \"./llm-logging.js\";\nimport { addAgentOptions, type AgentCommandOptions } from \"./option-helpers.js\";\nimport {\n executeAction,\n isInteractive,\n renderSummary,\n resolvePrompt,\n StreamPrinter,\n StreamProgress,\n} from \"./utils.js\";\nimport {\n formatGadgetSummary,\n renderMarkdownWithSeparators,\n renderOverallSummary,\n} from \"./ui/formatters.js\";\n\n/**\n * Prompts the user for approval with optional rejection feedback.\n * Used by the gating controller to approve dangerous gadget executions.\n *\n * SHOWCASE: This demonstrates how to build approval workflows using llmist's\n * controller hooks. The CLI gates RunCommand executions, but the pattern\n * can be applied to any gadget that needs user approval.\n *\n * @param env - CLI environment for I/O operations\n * @param prompt - The prompt to display to the user\n * @returns The user's input (empty string or \"y\" = approved, anything else = rejection reason)\n */\nasync function promptApproval(env: CLIEnvironment, prompt: string): Promise<string> {\n const rl = createInterface({ input: env.stdin, output: env.stderr });\n try {\n const answer = await rl.question(prompt);\n return answer.trim();\n } finally {\n rl.close();\n }\n}\n\n/**\n * Creates a human input handler for interactive mode.\n * Only returns a handler if stdin is a TTY (terminal), not a pipe.\n *\n * @param env - CLI environment\n * @param progress - Progress indicator to pause during input\n * @returns Human input handler function or undefined if not interactive\n */\nfunction createHumanInputHandler(\n env: CLIEnvironment,\n progress: StreamProgress,\n): ((question: string) => Promise<string>) | undefined {\n const stdout = env.stdout as NodeJS.WriteStream;\n if (!isInteractive(env.stdin) || typeof stdout.isTTY !== \"boolean\" || !stdout.isTTY) {\n return undefined;\n }\n\n return async (question: string): Promise<string> => {\n progress.pause(); // Pause progress indicator during human input\n const rl = createInterface({ input: env.stdin, output: env.stdout });\n try {\n // Display question on first prompt only (with markdown rendering and separators)\n const questionLine = question.trim() ? `\\n${renderMarkdownWithSeparators(question.trim())}` : \"\";\n let isFirst = true;\n\n // Loop until non-empty input (like a REPL)\n while (true) {\n const statsPrompt = progress.formatPrompt();\n const prompt = isFirst ? `${questionLine}\\n${statsPrompt}` : statsPrompt;\n isFirst = false;\n\n const answer = await rl.question(prompt);\n const trimmed = answer.trim();\n if (trimmed) {\n return trimmed;\n }\n // Empty input - show prompt again (no question repeat)\n }\n } finally {\n rl.close();\n }\n };\n}\n\n// formatGadgetSummary is now imported from ./ui/formatters.js\n// This demonstrates clean code organization and reusability\n\n/**\n * Executes the agent command.\n *\n * SHOWCASE: This function demonstrates how to build a production-grade CLI\n * on top of llmist's core capabilities:\n *\n * 1. **Dynamic gadget loading** - GadgetRegistry for plugin-like extensibility\n * 2. **Observer hooks** - Custom progress tracking and real-time UI updates\n * 3. **Event-driven execution** - React to agent events (text, gadget results)\n * 4. **ModelRegistry integration** - Automatic cost estimation and tracking\n * 5. **Streaming support** - Display LLM output as it's generated\n * 6. **Human-in-the-loop** - Interactive prompts during agent execution\n * 7. **Clean separation** - stdout for content, stderr for metrics/progress\n *\n * The implementation showcases llmist's flexibility: from simple scripts to\n * polished CLIs with spinners, cost tracking, and real-time feedback.\n *\n * @param promptArg - User prompt from command line argument (optional if using stdin)\n * @param options - Agent command options (model, gadgets, max iterations, etc.)\n * @param env - CLI environment for I/O operations\n */\nexport async function executeAgent(\n promptArg: string | undefined,\n options: AgentCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const prompt = await resolvePrompt(promptArg, env);\n const client = env.createClient();\n\n // SHOWCASE: llmist's GadgetRegistry for dynamic tool loading\n // This demonstrates how to build extensible CLIs with plugin-like functionality\n const registry = new GadgetRegistry();\n\n // Register built-in gadgets for basic agent interaction\n // SHOWCASE: Built-in gadgets enable conversation without any custom tools\n //\n // AskUser: Prompts user for input during agent execution\n // TellUser: Displays formatted messages and optionally ends the loop\n //\n // Flags control built-in behavior:\n // --no-builtins: Exclude all built-in gadgets\n // --no-builtin-interaction: Exclude only AskUser (keeps TellUser for output)\n //\n // AskUser is also auto-excluded when stdin is not interactive (piped input)\n const stdinIsInteractive = isInteractive(env.stdin);\n if (options.builtins !== false) {\n for (const gadget of builtinGadgets) {\n // Skip AskUser if:\n // 1. --no-builtin-interaction is set, OR\n // 2. stdin is not interactive (piped input) - AskUser can't work anyway\n if (gadget.name === \"AskUser\" && (options.builtinInteraction === false || !stdinIsInteractive)) {\n continue;\n }\n registry.registerByClass(gadget);\n }\n }\n\n // Load user-provided gadgets from file paths\n // SHOWCASE: Dynamic gadget loading enables custom tools without recompiling\n // Users can provide gadgets via -g/--gadget flag, supporting any TypeScript class\n const gadgetSpecifiers = options.gadget ?? [];\n if (gadgetSpecifiers.length > 0) {\n const gadgets = await loadGadgets(gadgetSpecifiers, process.cwd());\n for (const gadget of gadgets) {\n // Later registrations can override earlier ones\n // This allows users to customize built-in behavior\n registry.registerByClass(gadget);\n }\n }\n\n const printer = new StreamPrinter(env.stdout);\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n const progress = new StreamProgress(env.stderr, stderrTTY, client.modelRegistry);\n\n let usage: TokenUsage | undefined;\n let iterations = 0;\n\n // Resolve LLM debug log directories (if enabled)\n const llmRequestsDir = resolveLogDir(options.logLlmRequests, \"requests\");\n const llmResponsesDir = resolveLogDir(options.logLlmResponses, \"responses\");\n let llmCallCounter = 0;\n\n // Count tokens accurately using provider-specific methods\n const countMessagesTokens = async (model: string, messages: LLMMessage[]): Promise<number> => {\n try {\n return await client.countTokens(model, messages);\n } catch {\n // Fallback to character-based estimation if counting fails\n const totalChars = messages.reduce((sum, m) => sum + (m.content?.length ?? 0), 0);\n return Math.round(totalChars / FALLBACK_CHARS_PER_TOKEN);\n }\n };\n\n // Count tokens for gadget output text\n const countGadgetOutputTokens = async (output: string | undefined): Promise<number | undefined> => {\n if (!output) return undefined;\n try {\n // Wrap gadget output as assistant message for accurate token counting\n const messages: LLMMessage[] = [{ role: \"assistant\", content: output }];\n return await client.countTokens(options.model, messages);\n } catch {\n // Fallback: return undefined to trigger byte count fallback in formatter\n return undefined;\n }\n };\n\n // Build the agent with hooks for progress tracking\n // SHOWCASE: This demonstrates llmist's observer pattern for building custom UIs\n //\n // For simpler use cases, use HookPresets.progressTracking() instead:\n // .withHooks(HookPresets.progressTracking({\n // modelRegistry: client.modelRegistry,\n // onProgress: (stats) => { /* update your UI */ }\n // }))\n //\n // The CLI uses custom hooks for fine-grained control over the spinner animation\n // and real-time updates, showcasing llmist's flexibility for building polished UIs.\n const builder = new AgentBuilder(client)\n .withModel(options.model)\n .withLogger(env.createLogger(\"llmist:cli:agent\"))\n .withHooks({\n observers: {\n // onLLMCallStart: Start progress indicator for each LLM call\n // This showcases how to react to agent lifecycle events\n onLLMCallStart: async (context) => {\n llmCallCounter++;\n\n // Count input tokens accurately using provider-specific methods\n // This ensures we never show ~ for input tokens\n const inputTokens = await countMessagesTokens(\n context.options.model,\n context.options.messages,\n );\n progress.startCall(context.options.model, inputTokens);\n // Mark input tokens as accurate (not estimated)\n progress.setInputTokens(inputTokens, false);\n\n // Write LLM request to debug log if enabled\n if (llmRequestsDir) {\n const filename = `${Date.now()}_call_${llmCallCounter}.request.txt`;\n const content = formatLlmRequest(context.options.messages);\n await writeLogFile(llmRequestsDir, filename, content);\n }\n },\n // onStreamChunk: Real-time updates as LLM generates tokens\n // This enables responsive UIs that show progress during generation\n onStreamChunk: async (context) => {\n // Update estimated output tokens from accumulated text length\n progress.update(context.accumulatedText.length);\n\n // Use exact token counts when available from streaming response\n // SHOWCASE: Provider responses include token usage for accurate tracking\n if (context.usage) {\n if (context.usage.inputTokens) {\n progress.setInputTokens(context.usage.inputTokens, false);\n }\n if (context.usage.outputTokens) {\n progress.setOutputTokens(context.usage.outputTokens, false);\n }\n // Update cached token counts for live cost estimation\n progress.setCachedTokens(\n context.usage.cachedInputTokens ?? 0,\n context.usage.cacheCreationInputTokens ?? 0,\n );\n }\n },\n\n // onLLMCallComplete: Finalize metrics after each LLM call\n // This is where you'd typically log metrics or update dashboards\n onLLMCallComplete: async (context) => {\n // Capture completion metadata for final summary\n usage = context.usage;\n iterations = Math.max(iterations, context.iteration + 1);\n\n // Update with final exact token counts from provider\n // SHOWCASE: llmist normalizes token usage across all providers\n if (context.usage) {\n if (context.usage.inputTokens) {\n progress.setInputTokens(context.usage.inputTokens, false);\n }\n if (context.usage.outputTokens) {\n progress.setOutputTokens(context.usage.outputTokens, false);\n }\n }\n\n // Calculate per-call cost for the summary (accounting for cached tokens)\n // Use context.options.model (resolved) instead of options.model (raw CLI input)\n // This ensures aliases like \"sonnet\" are resolved to \"claude-sonnet-4-5\"\n let callCost: number | undefined;\n if (context.usage && client.modelRegistry) {\n try {\n const modelName = context.options.model.includes(\":\")\n ? context.options.model.split(\":\")[1]\n : context.options.model;\n const costResult = client.modelRegistry.estimateCost(\n modelName,\n context.usage.inputTokens,\n context.usage.outputTokens,\n context.usage.cachedInputTokens ?? 0,\n context.usage.cacheCreationInputTokens ?? 0,\n );\n if (costResult) callCost = costResult.totalCost;\n } catch {\n // Ignore cost calculation errors\n }\n }\n\n // Get per-call elapsed time before endCall resets it\n const callElapsed = progress.getCallElapsedSeconds();\n\n // End this call's progress tracking and switch to cumulative mode\n progress.endCall(context.usage);\n\n // SHOWCASE: Print per-call summary after each LLM call\n // This gives users visibility into each iteration's metrics\n // Skip summaries in quiet mode\n if (!options.quiet) {\n const summary = renderSummary({\n iterations: context.iteration + 1,\n model: options.model,\n usage: context.usage,\n elapsedSeconds: callElapsed,\n cost: callCost,\n finishReason: context.finishReason,\n });\n if (summary) {\n env.stderr.write(`${summary}\\n`);\n }\n }\n\n // Write LLM response to debug log if enabled\n if (llmResponsesDir) {\n const filename = `${Date.now()}_call_${llmCallCounter}.response.txt`;\n await writeLogFile(llmResponsesDir, filename, context.rawResponse);\n }\n },\n },\n\n // SHOWCASE: Controller-based approval gating for dangerous gadgets\n //\n // This demonstrates how to add safety layers WITHOUT modifying gadgets.\n // The RunCommand gadget is simple - it just executes commands. The CLI\n // adds the approval flow externally via beforeGadgetExecution controller.\n //\n // This pattern is composable: you can apply the same gating logic to\n // any gadget (DeleteFile, SendEmail, etc.) without changing the gadgets.\n controllers: {\n beforeGadgetExecution: async (ctx) => {\n // Only gate RunCommand - let other gadgets through\n if (ctx.gadgetName !== \"RunCommand\") {\n return { action: \"proceed\" };\n }\n\n // Only prompt for approval in interactive mode\n const stdinTTY = isInteractive(env.stdin);\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n if (!stdinTTY || !stderrTTY) {\n // Non-interactive mode: deny by default for safety\n return {\n action: \"skip\",\n syntheticResult:\n \"status=denied\\n\\nRunCommand requires interactive approval. Run in a terminal to approve commands.\",\n };\n }\n\n const command = ctx.parameters.command as string;\n\n // Pause progress indicator and prompt for approval\n progress.pause();\n env.stderr.write(`\\n🔒 Execute: ${chalk.cyan(command)}\\n`);\n\n const response = await promptApproval(env, \" ⏎ approve, or type to reject: \");\n\n // Empty input or \"y\"/\"Y\" = approved\n const isApproved = response === \"\" || response.toLowerCase() === \"y\";\n\n if (!isApproved) {\n env.stderr.write(` ${chalk.red(\"✗ Denied\")}\\n\\n`);\n return {\n action: \"skip\",\n syntheticResult: `status=denied\\n\\nCommand rejected by user with message: \"${response}\"`,\n };\n }\n\n env.stderr.write(` ${chalk.green(\"✓ Approved\")}\\n`);\n return { action: \"proceed\" };\n },\n },\n });\n\n // Add optional configurations\n if (options.system) {\n builder.withSystem(options.system);\n }\n if (options.maxIterations !== undefined) {\n builder.withMaxIterations(options.maxIterations);\n }\n if (options.temperature !== undefined) {\n builder.withTemperature(options.temperature);\n }\n\n const humanInputHandler = createHumanInputHandler(env, progress);\n if (humanInputHandler) {\n builder.onHumanInput(humanInputHandler);\n }\n\n // Add gadgets from the registry\n const gadgets = registry.getAll();\n if (gadgets.length > 0) {\n builder.withGadgets(...gadgets);\n }\n\n // Set custom gadget markers if configured, otherwise use library defaults\n if (options.gadgetStartPrefix) {\n builder.withGadgetStartPrefix(options.gadgetStartPrefix);\n }\n if (options.gadgetEndPrefix) {\n builder.withGadgetEndPrefix(options.gadgetEndPrefix);\n }\n if (options.gadgetArgPrefix) {\n builder.withGadgetArgPrefix(options.gadgetArgPrefix);\n }\n\n // Inject synthetic heredoc example for in-context learning\n // This teaches the LLM to use heredoc syntax (<<<EOF...EOF) for multiline strings\n // by showing what \"past self\" did correctly. LLMs mimic patterns in conversation history.\n builder.withSyntheticGadgetCall(\n \"TellUser\",\n {\n message:\n \"👋 Hello! I'm ready to help.\\n\\nHere's what I can do:\\n- Analyze your codebase\\n- Execute commands\\n- Answer questions\\n\\nWhat would you like me to work on?\",\n done: false,\n type: \"info\",\n },\n \"ℹ️ 👋 Hello! I'm ready to help.\\n\\nHere's what I can do:\\n- Analyze your codebase\\n- Execute commands\\n- Answer questions\\n\\nWhat would you like me to work on?\",\n );\n\n // Continue looping when LLM responds with just text (no gadget calls)\n // This allows multi-turn conversations where the LLM may explain before acting\n builder.withTextOnlyHandler(\"acknowledge\");\n\n // Wrap text that accompanies gadget calls as TellUser gadget calls\n // This keeps conversation history consistent and gadget-oriented\n builder.withTextWithGadgetsHandler({\n gadgetName: \"TellUser\",\n parameterMapping: (text) => ({ message: text, done: false, type: \"info\" }),\n resultMapping: (text) => `ℹ️ ${text}`,\n });\n\n // Build and start the agent\n const agent = builder.ask(prompt);\n\n // SHOWCASE: llmist's event-driven agent execution\n // The agent emits events as it runs, enabling reactive UIs\n //\n // Event types:\n // - \"text\": LLM-generated text chunks (streaming or complete)\n // - \"gadget_result\": Results from gadget/tool executions\n // - \"human_input_required\": Agent needs user input (handled via callback)\n //\n // This pattern allows building:\n // - Real-time streaming UIs\n // - Progress indicators during tool execution\n // - Separation of business logic (agent) from presentation (UI)\n\n // Buffer for accumulating text chunks - markdown rendering requires complete content\n let textBuffer = \"\";\n const flushTextBuffer = () => {\n if (textBuffer) {\n // Use separators in normal mode, plain text in quiet mode\n const output = options.quiet ? textBuffer : renderMarkdownWithSeparators(textBuffer);\n printer.write(output);\n textBuffer = \"\";\n }\n };\n\n for await (const event of agent.run()) {\n if (event.type === \"text\") {\n // Accumulate text chunks - we'll render markdown when complete\n progress.pause();\n textBuffer += event.content;\n } else if (event.type === \"gadget_result\") {\n // Flush any accumulated text before showing gadget result\n flushTextBuffer();\n // Show gadget execution feedback on stderr\n progress.pause();\n\n if (options.quiet) {\n // In quiet mode, only output TellUser messages (to stdout, plain unrendered text)\n if (event.result.gadgetName === \"TellUser\" && event.result.parameters?.message) {\n const message = String(event.result.parameters.message);\n env.stdout.write(`${message}\\n`);\n }\n } else {\n // Normal mode: show full gadget summary on stderr\n const tokenCount = await countGadgetOutputTokens(event.result.result);\n env.stderr.write(`${formatGadgetSummary({ ...event.result, tokenCount })}\\n`);\n }\n // Progress automatically resumes on next LLM call (via onLLMCallStart hook)\n }\n // Note: human_input_required handled by callback (see createHumanInputHandler)\n }\n\n // Flush any remaining buffered text with markdown rendering\n flushTextBuffer();\n\n progress.complete();\n printer.ensureNewline();\n\n // SHOWCASE: Show overall summary only if there were multiple iterations\n // Single-iteration runs already showed per-call summary, no need to repeat\n // Skip summaries in quiet mode\n if (!options.quiet && iterations > 1) {\n // Separator line to distinguish from per-call summaries\n env.stderr.write(`${chalk.dim(\"─\".repeat(40))}\\n`);\n\n const summary = renderOverallSummary({\n totalTokens: usage?.totalTokens,\n iterations,\n elapsedSeconds: progress.getTotalElapsedSeconds(),\n cost: progress.getTotalCost(),\n });\n if (summary) {\n env.stderr.write(`${summary}\\n`);\n }\n }\n}\n\n/**\n * Registers the agent command with the CLI program.\n * Configures options for model, gadgets, max iterations, temperature, and parameter format.\n *\n * @param program - Commander program to register the command with\n * @param env - CLI environment for dependencies and I/O\n * @param config - Optional configuration defaults from config file\n */\nexport function registerAgentCommand(\n program: Command,\n env: CLIEnvironment,\n config?: AgentConfig,\n): void {\n const cmd = program\n .command(COMMANDS.agent)\n .description(\"Run the llmist agent loop with optional gadgets.\")\n .argument(\"[prompt]\", \"Prompt for the agent loop. Falls back to stdin when available.\");\n\n addAgentOptions(cmd, config);\n\n cmd.action((prompt, options) =>\n executeAction(() => executeAgent(prompt, options as AgentCommandOptions, env), env),\n );\n}\n","/**\n * Built-in gadgets for CLI agent command.\n * These gadgets provide basic communication capabilities out-of-the-box.\n */\nimport { z } from \"zod\";\n\nimport { createGadget } from \"../gadgets/create-gadget.js\";\nimport {\n BreakLoopException,\n HumanInputException,\n} from \"../gadgets/exceptions.js\";\n\n/**\n * AskUser gadget - Asks the user a question and waits for their response.\n *\n * Use this when you need more information or clarification from the user.\n */\nexport const askUser = createGadget({\n name: \"AskUser\",\n description:\n \"Ask the user a question when you need more information or clarification. The user's response will be provided back to you.\",\n schema: z.object({\n question: z\n .string()\n .describe(\"The question to ask the user in plain-text or Markdown\"),\n }),\n examples: [\n {\n comment: \"Ask for clarification about the task\",\n params: { question: \"Which file would you like me to modify?\" },\n },\n {\n comment: \"Ask user to choose between options\",\n params: {\n question:\n \"I found multiple matches. Which one should I use?\\n- src/utils/helper.ts\\n- src/lib/helper.ts\",\n },\n },\n ],\n execute: ({ question }) => {\n throw new HumanInputException(question);\n },\n});\n\n/**\n * TellUser gadget - Outputs a message to the user and optionally ends the conversation.\n *\n * Use this for key results, warnings, or structured output that should stand out\n * from regular streamed text. Set done=true when the task is complete.\n */\nexport const tellUser = createGadget({\n name: \"TellUser\",\n description:\n \"Tell the user something important. Set done=true when your work is complete and you want to end the conversation.\",\n schema: z.object({\n message: z\n .string()\n .optional()\n .describe(\"The message to display to the user in Markdown\"),\n done: z\n .boolean()\n .default(false)\n .describe(\"Set to true to end the conversation, false to continue\"),\n type: z\n .enum([\"info\", \"success\", \"warning\", \"error\"])\n .default(\"info\")\n .describe(\"Message type: info, success, warning, or error\"),\n }),\n examples: [\n {\n comment: \"Report successful completion and end the conversation\",\n params: {\n message: \"I've completed the refactoring. All tests pass.\",\n done: true,\n type: \"success\",\n },\n },\n {\n comment: \"Warn the user about something without ending\",\n params: {\n message: \"Found 3 files with potential issues. Continuing analysis...\",\n done: false,\n type: \"warning\",\n },\n },\n {\n comment: \"Share detailed analysis with bullet points (use heredoc for multiline)\",\n params: {\n message:\n \"Here's what I found in the codebase:\\n\\n1. **Main entry point**: `src/index.ts` exports all public APIs\\n2. **Core logic**: Located in `src/core/` with 5 modules\\n3. **Tests**: Good coverage in `src/__tests__/`\\n\\nI'll continue exploring the core modules.\",\n done: false,\n type: \"info\",\n },\n },\n ],\n execute: ({ message, done, type }) => {\n // Handle empty or missing message gracefully\n // This happens when LLM sends malformed parameters that fail to parse the message field\n if (!message || message.trim() === \"\") {\n return \"⚠️ TellUser was called without a message. Please provide content in the 'message' field.\";\n }\n\n // Format message for display, but return plain text for LLM context\n // This prevents ANSI color codes from polluting the conversation\n const prefixes = {\n info: \"ℹ️ \",\n success: \"✅ \",\n warning: \"⚠️ \",\n error: \"❌ \",\n };\n const plainResult = prefixes[type] + message;\n\n if (done) {\n throw new BreakLoopException(plainResult);\n }\n return plainResult;\n },\n});\n\n/**\n * All built-in gadgets as an array for easy registration.\n */\nexport const builtinGadgets = [askUser, tellUser];\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { BaseGadget } from \"../gadgets/gadget.js\";\n\n/**\n * Function type for importing modules dynamically.\n */\nexport type GadgetImportFunction = (specifier: string) => Promise<unknown>;\n\nconst PATH_PREFIXES = [\".\", \"/\", \"~\"];\n\n/**\n * Duck-type check if a value looks like a Gadget instance.\n * This avoids instanceof issues when gadgets are loaded from external files\n * that import from the 'llmist' npm package (different class instance).\n */\nfunction isGadgetLike(value: unknown): value is BaseGadget {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n const obj = value as Record<string, unknown>;\n return (\n typeof obj.execute === \"function\" &&\n typeof obj.description === \"string\" &&\n (\"parameterSchema\" in obj || \"schema\" in obj)\n );\n}\n\n/**\n * Type guard to check if a value is a Gadget constructor.\n *\n * @param value - Value to check\n * @returns True if value is a Gadget constructor\n */\nfunction isGadgetConstructor(value: unknown): value is new () => BaseGadget {\n if (typeof value !== \"function\") {\n return false;\n }\n\n const prototype = value.prototype as unknown;\n // Use duck typing for prototype check too\n return Boolean(prototype) && (prototype instanceof BaseGadget || isGadgetLike(prototype));\n}\n\n/**\n * Expands ~ to the user's home directory.\n *\n * @param input - Path that may start with ~\n * @returns Expanded path with HOME directory\n */\nfunction expandHomePath(input: string): string {\n if (!input.startsWith(\"~\")) {\n return input;\n }\n\n const home = process.env.HOME;\n if (!home) {\n return input;\n }\n\n return path.join(home, input.slice(1));\n}\n\n/**\n * Determines if a specifier is a file path vs npm module name.\n * File paths start with ., /, ~ or contain path separators.\n *\n * @param specifier - Module specifier to check\n * @returns True if specifier represents a file path\n */\nfunction isFileLikeSpecifier(specifier: string): boolean {\n return (\n PATH_PREFIXES.some((prefix) => specifier.startsWith(prefix)) || specifier.includes(path.sep)\n );\n}\n\n/**\n * Resolves a gadget specifier to either a file URL or npm module name.\n * File paths are resolved relative to cwd and converted to file:// URLs.\n *\n * @param specifier - Original gadget specifier (file path or module name)\n * @param cwd - Current working directory for resolving relative paths\n * @returns Resolved specifier (file:// URL for files, module name for packages)\n * @throws Error if file path doesn't exist\n */\nexport function resolveGadgetSpecifier(specifier: string, cwd: string): string {\n if (!isFileLikeSpecifier(specifier)) {\n return specifier;\n }\n\n const expanded = expandHomePath(specifier);\n const resolvedPath = path.resolve(cwd, expanded);\n if (!fs.existsSync(resolvedPath)) {\n throw new Error(`Gadget module not found at ${resolvedPath}`);\n }\n return pathToFileURL(resolvedPath).href;\n}\n\n/**\n * Recursively extracts all Gadget instances and classes from a module's exports.\n * Searches default export, named exports, nested objects, and arrays.\n * Automatically instantiates Gadget classes.\n *\n * @param moduleExports - Module exports object to search\n * @returns Array of Gadget instances found in exports\n */\nexport function extractGadgetsFromModule(moduleExports: unknown): BaseGadget[] {\n const results: BaseGadget[] = [];\n const visited = new Set<unknown>();\n\n const visit = (value: unknown) => {\n if (value === undefined || value === null) {\n return;\n }\n\n if (visited.has(value)) {\n return;\n }\n visited.add(value);\n\n // Use duck typing to handle gadgets from external packages\n if (value instanceof BaseGadget || isGadgetLike(value)) {\n results.push(value as BaseGadget);\n return;\n }\n\n if (isGadgetConstructor(value)) {\n results.push(new value());\n return;\n }\n\n if (Array.isArray(value)) {\n for (const entry of value) {\n visit(entry);\n }\n return;\n }\n\n if (typeof value === \"object\") {\n for (const entry of Object.values(value as Record<string, unknown>)) {\n visit(entry);\n }\n }\n };\n\n visit(moduleExports);\n return results;\n}\n\n/**\n * Loads gadgets from one or more file paths or npm module names.\n * Resolves paths, imports modules, and extracts gadgets.\n *\n * @param specifiers - Array of gadget specifiers (file paths or module names)\n * @param cwd - Current working directory for resolving relative paths\n * @param importer - Function to dynamically import modules (default: native import)\n * @returns Array of loaded Gadget instances\n * @throws Error if module fails to load, contains no gadgets, or initialization fails\n */\nexport async function loadGadgets(\n specifiers: string[],\n cwd: string,\n importer: GadgetImportFunction = (specifier) => import(specifier),\n): Promise<BaseGadget[]> {\n const gadgets: BaseGadget[] = [];\n\n for (const specifier of specifiers) {\n const resolved = resolveGadgetSpecifier(specifier, cwd);\n let exports: unknown;\n try {\n exports = await importer(resolved);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to load gadget module '${specifier}': ${message}`);\n }\n\n let extracted: BaseGadget[];\n try {\n extracted = extractGadgetsFromModule(exports);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to initialize gadgets from module '${specifier}': ${message}`);\n }\n if (extracted.length === 0) {\n throw new Error(`Module '${specifier}' does not export any Gadget instances.`);\n }\n gadgets.push(...extracted);\n }\n\n return gadgets;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport type { LLMMessage } from \"../core/messages.js\";\n\n/**\n * Default directory for LLM debug logs.\n */\nexport const DEFAULT_LLM_LOG_DIR = join(homedir(), \".llmist\", \"logs\");\n\n/**\n * Resolves the log directory from a boolean or string option.\n * - true: use default directory with subdir\n * - string: use the provided path\n * - undefined/false: disabled\n */\nexport function resolveLogDir(option: string | boolean | undefined, subdir: string): string | undefined {\n if (option === true) {\n return join(DEFAULT_LLM_LOG_DIR, subdir);\n }\n if (typeof option === \"string\") {\n return option;\n }\n return undefined;\n}\n\n/**\n * Formats LLM messages as plain text for debugging.\n */\nexport function formatLlmRequest(messages: LLMMessage[]): string {\n const lines: string[] = [];\n for (const msg of messages) {\n lines.push(`=== ${msg.role.toUpperCase()} ===`);\n lines.push(msg.content ?? \"\");\n lines.push(\"\");\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Writes a debug log file, creating the directory if needed.\n */\nexport async function writeLogFile(dir: string, filename: string, content: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n await writeFile(join(dir, filename), content, \"utf-8\");\n}\n","import chalk from \"chalk\";\nimport { InvalidArgumentError } from \"commander\";\n\nimport type { ModelRegistry } from \"../core/model-registry.js\";\nimport type { TokenUsage } from \"../core/options.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"../providers/constants.js\";\nimport type { CLIEnvironment, TTYStream } from \"./environment.js\";\n\n/**\n * Options for creating a numeric value parser.\n */\nexport interface NumericParserOptions {\n label: string;\n integer?: boolean;\n min?: number;\n max?: number;\n}\n\n/**\n * Creates a parser function for numeric command-line options with validation.\n * Validates that values are numbers, optionally integers, and within min/max bounds.\n *\n * @param options - Parser configuration (label, integer, min, max)\n * @returns Parser function that validates and returns the numeric value\n * @throws InvalidArgumentError if validation fails\n */\nexport function createNumericParser({\n label,\n integer = false,\n min,\n max,\n}: NumericParserOptions): (value: string) => number {\n return (value: string) => {\n const parsed = Number(value);\n if (Number.isNaN(parsed)) {\n throw new InvalidArgumentError(`${label} must be a number.`);\n }\n\n if (integer && !Number.isInteger(parsed)) {\n throw new InvalidArgumentError(`${label} must be an integer.`);\n }\n\n if (min !== undefined && parsed < min) {\n throw new InvalidArgumentError(`${label} must be greater than or equal to ${min}.`);\n }\n\n if (max !== undefined && parsed > max) {\n throw new InvalidArgumentError(`${label} must be less than or equal to ${max}.`);\n }\n\n return parsed;\n };\n}\n\n/**\n * Helper class for writing text to a stream while tracking newline state.\n * Ensures output ends with a newline for proper terminal formatting.\n */\nexport class StreamPrinter {\n private endedWithNewline = true;\n\n constructor(private readonly target: NodeJS.WritableStream) {}\n\n /**\n * Writes text to the target stream and tracks newline state.\n *\n * @param text - Text to write\n */\n write(text: string): void {\n if (!text) {\n return;\n }\n this.target.write(text);\n this.endedWithNewline = text.endsWith(\"\\n\");\n }\n\n /**\n * Ensures output ends with a newline by writing one if needed.\n */\n ensureNewline(): void {\n if (!this.endedWithNewline) {\n this.target.write(\"\\n\");\n this.endedWithNewline = true;\n }\n }\n}\n\n/**\n * Checks if a stream is a TTY (terminal) for interactive input.\n *\n * @param stream - Stream to check\n * @returns True if stream is a TTY\n */\nexport function isInteractive(stream: TTYStream): boolean {\n return Boolean(stream.isTTY);\n}\n\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\nconst SPINNER_DELAY_MS = 500; // Don't show spinner for fast responses\n\ntype ProgressMode = \"streaming\" | \"cumulative\";\n\n// Import formatters from centralized formatting module\n// This showcases llmist's clean code organization\nimport { formatTokens, formatCost } from \"./ui/formatters.js\";\n\n/**\n * Progress indicator shown while waiting for LLM response.\n * Two modes:\n * - streaming: Shows current LLM call stats (out/in tokens, call time)\n * - cumulative: Shows total stats across all calls (total tokens, iterations, total time)\n * Only displays on TTY (interactive terminal), silent when piped.\n */\nexport class StreamProgress {\n // Animation state\n private frameIndex = 0;\n private interval: ReturnType<typeof setInterval> | null = null;\n private delayTimeout: ReturnType<typeof setTimeout> | null = null;\n private isRunning = false;\n private hasRendered = false;\n\n // Current call stats (streaming mode)\n private mode: ProgressMode = \"cumulative\";\n private model = \"\";\n private callStartTime = Date.now();\n private callInputTokens = 0;\n private callInputTokensEstimated = true;\n private callOutputTokens = 0;\n private callOutputTokensEstimated = true;\n private callOutputChars = 0;\n private isStreaming = false;\n // Cache token tracking for live cost estimation during streaming\n private callCachedInputTokens = 0;\n private callCacheCreationInputTokens = 0;\n\n // Cumulative stats (cumulative mode)\n private totalStartTime = Date.now();\n private totalTokens = 0;\n private totalCost = 0;\n private iterations = 0;\n private currentIteration = 0;\n\n constructor(\n private readonly target: NodeJS.WritableStream,\n private readonly isTTY: boolean,\n private readonly modelRegistry?: ModelRegistry,\n ) {}\n\n /**\n * Starts a new LLM call. Switches to streaming mode.\n * @param model - Model name being used\n * @param estimatedInputTokens - Initial input token count. Should come from\n * client.countTokens() for accuracy (provider-specific counting), not\n * character-based estimation. Will be updated with provider-returned counts\n * via setInputTokens() during streaming if available.\n */\n startCall(model: string, estimatedInputTokens?: number): void {\n this.mode = \"streaming\";\n this.model = model;\n this.callStartTime = Date.now();\n this.currentIteration++;\n this.callInputTokens = estimatedInputTokens ?? 0;\n this.callInputTokensEstimated = true;\n this.callOutputTokens = 0;\n this.callOutputTokensEstimated = true;\n this.callOutputChars = 0;\n this.isStreaming = false;\n // Reset cache tracking for new call\n this.callCachedInputTokens = 0;\n this.callCacheCreationInputTokens = 0;\n this.start();\n }\n\n /**\n * Ends the current LLM call. Updates cumulative stats and switches to cumulative mode.\n * @param usage - Final token usage from the call (including cached tokens if available)\n */\n endCall(usage?: TokenUsage): void {\n this.iterations++;\n if (usage) {\n this.totalTokens += usage.totalTokens;\n\n // Calculate and accumulate cost if model registry is available\n if (this.modelRegistry && this.model) {\n try {\n // Strip provider prefix if present (e.g., \"openai:gpt-5-nano\" -> \"gpt-5-nano\")\n const modelName = this.model.includes(\":\")\n ? this.model.split(\":\")[1]\n : this.model;\n\n const cost = this.modelRegistry.estimateCost(\n modelName,\n usage.inputTokens,\n usage.outputTokens,\n usage.cachedInputTokens ?? 0,\n usage.cacheCreationInputTokens ?? 0,\n );\n if (cost) {\n this.totalCost += cost.totalCost;\n }\n } catch {\n // Ignore errors (e.g., unknown model) - just don't add to cost\n }\n }\n }\n this.pause();\n this.mode = \"cumulative\";\n }\n\n /**\n * Sets the input token count for current call (from stream metadata).\n * @param tokens - Token count from provider or client.countTokens()\n * @param estimated - If true, this is a fallback estimate (character-based).\n * If false, this is an accurate count from the provider API or client.countTokens().\n * Display shows ~ prefix only when estimated=true.\n */\n setInputTokens(tokens: number, estimated = false): void {\n // Don't overwrite actual count with a new estimate\n if (estimated && !this.callInputTokensEstimated) {\n return;\n }\n this.callInputTokens = tokens;\n this.callInputTokensEstimated = estimated;\n }\n\n /**\n * Sets the output token count for current call (from stream metadata).\n * @param tokens - Token count from provider streaming response\n * @param estimated - If true, this is a fallback estimate (character-based).\n * If false, this is an accurate count from the provider's streaming metadata.\n * Display shows ~ prefix only when estimated=true.\n */\n setOutputTokens(tokens: number, estimated = false): void {\n // Don't overwrite actual count with a new estimate\n if (estimated && !this.callOutputTokensEstimated) {\n return;\n }\n this.callOutputTokens = tokens;\n this.callOutputTokensEstimated = estimated;\n }\n\n /**\n * Sets cached token counts for the current call (from stream metadata).\n * Used for live cost estimation during streaming.\n * @param cachedInputTokens - Number of tokens read from cache (cheaper)\n * @param cacheCreationInputTokens - Number of tokens written to cache (more expensive)\n */\n setCachedTokens(cachedInputTokens: number, cacheCreationInputTokens: number): void {\n this.callCachedInputTokens = cachedInputTokens;\n this.callCacheCreationInputTokens = cacheCreationInputTokens;\n }\n\n /**\n * Get total elapsed time in seconds since the first call started.\n * @returns Elapsed time in seconds with 1 decimal place\n */\n getTotalElapsedSeconds(): number {\n if (this.totalStartTime === 0) return 0;\n return Number(((Date.now() - this.totalStartTime) / 1000).toFixed(1));\n }\n\n /**\n * Get elapsed time in seconds for the current call.\n * @returns Elapsed time in seconds with 1 decimal place\n */\n getCallElapsedSeconds(): number {\n return Number(((Date.now() - this.callStartTime) / 1000).toFixed(1));\n }\n\n /**\n * Starts the progress indicator animation after a brief delay.\n */\n start(): void {\n if (!this.isTTY || this.isRunning) return;\n this.isRunning = true;\n\n // Delay showing spinner to avoid flicker for fast responses\n this.delayTimeout = setTimeout(() => {\n if (this.isRunning) {\n this.interval = setInterval(() => this.render(), 80);\n this.render();\n }\n }, SPINNER_DELAY_MS);\n }\n\n /**\n * Updates output character count for current call and marks streaming as active.\n * @param totalChars - Total accumulated character count\n */\n update(totalChars: number): void {\n this.callOutputChars = totalChars;\n this.isStreaming = true;\n }\n\n private render(): void {\n const spinner = SPINNER_FRAMES[this.frameIndex++ % SPINNER_FRAMES.length];\n\n if (this.mode === \"streaming\") {\n this.renderStreamingMode(spinner);\n } else {\n this.renderCumulativeMode(spinner);\n }\n this.hasRendered = true;\n }\n\n private renderStreamingMode(spinner: string): void {\n const elapsed = ((Date.now() - this.callStartTime) / 1000).toFixed(1);\n\n // Output tokens: use actual if available, otherwise estimate from chars\n const outTokens = this.callOutputTokensEstimated\n ? Math.round(this.callOutputChars / FALLBACK_CHARS_PER_TOKEN)\n : this.callOutputTokens;\n\n // Build status parts: #N model | ↑ in │ ↓ out │ time | cost\n const parts: string[] = [];\n\n // #N model (iteration number + model name)\n const iterPart = chalk.cyan(`#${this.currentIteration}`);\n if (this.model) {\n parts.push(`${iterPart} ${chalk.magenta(this.model)}`);\n } else {\n parts.push(iterPart);\n }\n\n // ↑ input tokens\n if (this.callInputTokens > 0) {\n const prefix = this.callInputTokensEstimated ? \"~\" : \"\";\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${prefix}${formatTokens(this.callInputTokens)}`));\n }\n\n // ↓ output tokens\n if (this.isStreaming || outTokens > 0) {\n const prefix = this.callOutputTokensEstimated ? \"~\" : \"\";\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${prefix}${formatTokens(outTokens)}`));\n }\n\n // Time\n parts.push(chalk.dim(`${elapsed}s`));\n\n // Live cost estimate for current call (updates as tokens stream in)\n const callCost = this.calculateCurrentCallCost(outTokens);\n if (callCost > 0) {\n parts.push(chalk.cyan(`$${formatCost(callCost)}`));\n }\n\n this.target.write(`\\r${parts.join(chalk.dim(\" | \"))} ${chalk.cyan(spinner)}`);\n }\n\n /**\n * Calculates live cost estimate for the current streaming call.\n * Uses current input/output tokens and cached token counts.\n */\n private calculateCurrentCallCost(outputTokens: number): number {\n if (!this.modelRegistry || !this.model) return 0;\n\n try {\n // Strip provider prefix if present (e.g., \"anthropic:claude-sonnet-4-5\" -> \"claude-sonnet-4-5\")\n const modelName = this.model.includes(\":\") ? this.model.split(\":\")[1] : this.model;\n\n const cost = this.modelRegistry.estimateCost(\n modelName,\n this.callInputTokens,\n outputTokens,\n this.callCachedInputTokens,\n this.callCacheCreationInputTokens,\n );\n\n return cost?.totalCost ?? 0;\n } catch {\n return 0;\n }\n }\n\n private renderCumulativeMode(spinner: string): void {\n const elapsed = ((Date.now() - this.totalStartTime) / 1000).toFixed(1);\n\n // Build status parts: model, total tokens, iterations, cost, total time\n const parts: string[] = [];\n if (this.model) {\n parts.push(chalk.cyan(this.model));\n }\n if (this.totalTokens > 0) {\n parts.push(chalk.dim(\"total:\") + chalk.magenta(` ${this.totalTokens}`));\n }\n if (this.iterations > 0) {\n parts.push(chalk.dim(\"iter:\") + chalk.blue(` ${this.iterations}`));\n }\n if (this.totalCost > 0) {\n parts.push(chalk.dim(\"cost:\") + chalk.cyan(` $${formatCost(this.totalCost)}`));\n }\n parts.push(chalk.dim(`${elapsed}s`));\n\n this.target.write(`\\r${parts.join(chalk.dim(\" | \"))} ${chalk.cyan(spinner)}`);\n }\n\n /**\n * Pauses the progress indicator and clears the line.\n * Can be resumed with start().\n */\n pause(): void {\n if (!this.isTTY || !this.isRunning) return;\n\n if (this.delayTimeout) {\n clearTimeout(this.delayTimeout);\n this.delayTimeout = null;\n }\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n this.isRunning = false;\n\n // Only clear the line if we actually rendered something\n if (this.hasRendered) {\n // Clear spinner line and ensure cursor is at column 0\n // \\r = carriage return (go to column 0)\n // \\x1b[K = clear from cursor to end of line\n // \\x1b[0G = move cursor to column 0 (ensures we're at start even after clear)\n this.target.write(\"\\r\\x1b[K\\x1b[0G\");\n this.hasRendered = false;\n }\n }\n\n /**\n * Completes the progress indicator and clears the line.\n */\n complete(): void {\n this.pause();\n }\n\n /**\n * Returns the total accumulated cost across all calls.\n */\n getTotalCost(): number {\n return this.totalCost;\n }\n\n /**\n * Returns a formatted prompt string with stats (like bash PS1).\n * Shows current call stats during streaming, cumulative stats otherwise.\n * Format: \"out: 1.2k │ in: ~300 │ 5s > \" or \"3.6k │ i2 │ 34s > \"\n */\n formatPrompt(): string {\n const parts: string[] = [];\n\n if (this.mode === \"streaming\") {\n // During a call: show current call stats\n const elapsed = Math.round((Date.now() - this.callStartTime) / 1000);\n\n // Output tokens: use actual if available, otherwise estimate from chars\n const outTokens = this.callOutputTokensEstimated\n ? Math.round(this.callOutputChars / FALLBACK_CHARS_PER_TOKEN)\n : this.callOutputTokens;\n const outEstimated = this.callOutputTokensEstimated;\n\n if (this.callInputTokens > 0) {\n const prefix = this.callInputTokensEstimated ? \"~\" : \"\";\n parts.push(\n chalk.dim(\"↑\") + chalk.yellow(` ${prefix}${formatTokens(this.callInputTokens)}`),\n );\n }\n if (outTokens > 0) {\n const prefix = outEstimated ? \"~\" : \"\";\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${prefix}${formatTokens(outTokens)}`));\n }\n parts.push(chalk.dim(`${elapsed}s`));\n } else {\n // Between calls: show cumulative stats\n const elapsed = Math.round((Date.now() - this.totalStartTime) / 1000);\n\n if (this.totalTokens > 0) {\n parts.push(chalk.magenta(formatTokens(this.totalTokens)));\n }\n if (this.iterations > 0) {\n parts.push(chalk.blue(`i${this.iterations}`));\n }\n if (this.totalCost > 0) {\n parts.push(chalk.cyan(`$${formatCost(this.totalCost)}`));\n }\n parts.push(chalk.dim(`${elapsed}s`));\n }\n\n return `${parts.join(chalk.dim(\" | \"))} ${chalk.green(\">\")} `;\n }\n}\n\n/**\n * Reads all data from a readable stream into a string.\n *\n * @param stream - Stream to read from\n * @returns Complete stream contents as string\n */\nasync function readStream(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: string[] = [];\n for await (const chunk of stream) {\n if (typeof chunk === \"string\") {\n chunks.push(chunk);\n } else {\n chunks.push(chunk.toString(\"utf8\"));\n }\n }\n return chunks.join(\"\");\n}\n\n/**\n * Normalizes a prompt by trimming whitespace.\n *\n * @param value - Prompt to normalize\n * @returns Trimmed prompt\n */\nfunction normalizePrompt(value: string): string {\n return value.trim();\n}\n\n/**\n * Resolves the user prompt from either command-line argument or stdin.\n * Priority: 1) promptArg if provided, 2) stdin if piped, 3) error if neither.\n *\n * @param promptArg - Optional prompt from command-line argument\n * @param env - CLI environment for accessing stdin\n * @returns Resolved and normalized prompt\n * @throws Error if no prompt available or stdin is empty\n */\nexport async function resolvePrompt(\n promptArg: string | undefined,\n env: CLIEnvironment,\n): Promise<string> {\n if (promptArg?.trim()) {\n return normalizePrompt(promptArg);\n }\n\n if (isInteractive(env.stdin)) {\n throw new Error(\"Prompt is required. Provide an argument or pipe content via stdin.\");\n }\n\n const pipedInput = normalizePrompt(await readStream(env.stdin));\n if (!pipedInput) {\n throw new Error(\"Received empty stdin payload. Provide a prompt to continue.\");\n }\n\n return pipedInput;\n}\n\n// Re-export summary rendering from formatters module\n// This maintains backward compatibility while organizing code better\nexport { renderSummary, type SummaryMetadata } from \"./ui/formatters.js\";\n\n/**\n * Executes a CLI action with error handling.\n * Catches errors, writes to stderr, and sets exit code 1 on failure.\n *\n * @param action - Async action to execute\n * @param env - CLI environment for error output and exit code\n */\nexport async function executeAction(\n action: () => Promise<void>,\n env: CLIEnvironment,\n): Promise<void> {\n try {\n await action();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n env.stderr.write(`${chalk.red.bold(\"Error:\")} ${message}\\n`);\n env.setExitCode(1);\n }\n}\n","/**\n * CLI output formatting utilities.\n *\n * This module provides formatting functions for displaying metrics, summaries,\n * and gadget results in a clean, consistent format across the llmist CLI.\n *\n * **Design principles:**\n * - Consistent formatting across all commands (agent, complete, models)\n * - Human-readable output with appropriate precision\n * - Color-coded for visual clarity (using chalk)\n * - Compact format optimized for terminal display\n *\n * **SHOWCASE:** Demonstrates how to build a polished CLI on top of llmist's core.\n */\n\nimport chalk from \"chalk\";\nimport { marked, type MarkedExtension } from \"marked\";\nimport { markedTerminal } from \"marked-terminal\";\nimport type { TokenUsage } from \"../../core/options.js\";\n\n/**\n * Lazy-initialized flag for marked-terminal configuration.\n *\n * We defer `marked.use(markedTerminal())` until first render because:\n * - markedTerminal() captures chalk's color level at call time\n * - At module import time, TTY detection may not be complete\n * - Lazy init ensures colors work in interactive terminals\n */\nlet markedConfigured = false;\n\n/**\n * Configure marked for terminal output (lazy initialization).\n *\n * Uses marked-terminal to convert markdown to ANSI-styled terminal output.\n * This enables rich formatting in TellUser messages and AskUser questions.\n *\n * We override marked-terminal's style functions with our own chalk instance\n * because marked-terminal bundles its own chalk that detects colors at module\n * load time. Bun's broken TTY detection causes that bundled chalk to detect\n * level 0 (no colors). See: https://github.com/oven-sh/bun/issues/1322\n *\n * By forcing `chalk.level = 3` on our imported chalk and passing custom style\n * functions, we ensure colors work regardless of TTY detection.\n *\n * Respects the NO_COLOR environment variable for accessibility.\n *\n * Note: Type assertion needed due to @types/marked-terminal lag behind the runtime API.\n */\nfunction ensureMarkedConfigured(): void {\n if (!markedConfigured) {\n // Respect NO_COLOR env var, otherwise force truecolor (level 3)\n chalk.level = process.env.NO_COLOR ? 0 : 3;\n\n // Override marked-terminal's style functions with our chalk instance\n // to work around Bun's broken TTY detection\n marked.use(\n markedTerminal({\n // Text styling\n strong: chalk.bold,\n em: chalk.italic,\n del: chalk.dim.gray.strikethrough,\n\n // Code styling\n code: chalk.yellow,\n codespan: chalk.yellow,\n\n // Headings\n heading: chalk.green.bold,\n firstHeading: chalk.magenta.underline.bold,\n\n // Links\n link: chalk.blue,\n href: chalk.blue.underline,\n\n // Block elements\n blockquote: chalk.gray.italic,\n\n // List formatting - reduce indentation and add bullet styling\n tab: 2, // Reduce from default 4 to 2 spaces\n listitem: chalk.reset, // Keep items readable (no dim)\n }) as unknown as MarkedExtension,\n );\n markedConfigured = true;\n }\n}\n\n/**\n * Renders markdown text as styled terminal output.\n *\n * Converts markdown syntax to ANSI escape codes for terminal display:\n * - **bold** and *italic* text\n * - `inline code` and code blocks\n * - Lists (bulleted and numbered)\n * - Headers\n * - Links (clickable in supported terminals)\n *\n * @param text - Markdown text to render\n * @returns ANSI-styled string for terminal output\n *\n * @example\n * ```typescript\n * renderMarkdown(\"**Important:** Check the `config.json` file\");\n * // Returns styled text with bold \"Important:\" and code-styled \"config.json\"\n * ```\n */\nexport function renderMarkdown(text: string): string {\n ensureMarkedConfigured();\n let rendered = marked.parse(text) as string;\n\n // Workaround for marked-terminal bug: inline markdown in list items\n // is not processed. Post-process to handle **bold** and *italic*.\n // See: https://github.com/mikaelbr/marked-terminal/issues\n rendered = rendered\n .replace(/\\*\\*(.+?)\\*\\*/g, (_, content) => chalk.bold(content))\n // Italic: require non-space after * to avoid matching bullet points ( * )\n .replace(/(?<!\\*)\\*(\\S[^*]*)\\*(?!\\*)/g, (_, content) => chalk.italic(content));\n\n // Remove trailing newlines that marked adds\n return rendered.trimEnd();\n}\n\n/**\n * Creates a rainbow-colored horizontal line for visual emphasis.\n * Cycles through colors for each character segment.\n * Uses the full terminal width for a complete visual separator.\n *\n * @returns Rainbow-colored separator string spanning the terminal width\n */\nfunction createRainbowSeparator(): string {\n const colors = [chalk.red, chalk.yellow, chalk.green, chalk.cyan, chalk.blue, chalk.magenta];\n const char = \"─\";\n // Use terminal width, fallback to 80 if not available (e.g., piped output)\n const width = process.stdout.columns || 80;\n let result = \"\";\n for (let i = 0; i < width; i++) {\n result += colors[i % colors.length](char);\n }\n return result;\n}\n\n/**\n * Renders markdown with colorful rainbow horizontal line separators above and below.\n * Use this for prominent markdown content that should stand out visually.\n *\n * @param text - Markdown text to render\n * @returns Rendered markdown with rainbow separators\n *\n * @example\n * ```typescript\n * renderMarkdownWithSeparators(\"**Hello** world!\");\n * // Returns rainbow line + styled markdown + rainbow line\n * ```\n */\nexport function renderMarkdownWithSeparators(text: string): string {\n const rendered = renderMarkdown(text);\n const separator = createRainbowSeparator();\n return `\\n${separator}\\n${rendered}\\n${separator}\\n`;\n}\n\n/**\n * Formats token count with 'k' suffix for thousands.\n *\n * Uses compact notation to save terminal space while maintaining readability.\n * Numbers below 1000 are shown as-is, larger numbers use 'k' suffix with one decimal.\n *\n * @param tokens - Number of tokens\n * @returns Formatted string (e.g., \"896\" or \"11.5k\")\n *\n * @example\n * ```typescript\n * formatTokens(896) // \"896\"\n * formatTokens(11500) // \"11.5k\"\n * formatTokens(1234) // \"1.2k\"\n * ```\n */\nexport function formatTokens(tokens: number): string {\n return tokens >= 1000 ? `${(tokens / 1000).toFixed(1)}k` : `${tokens}`;\n}\n\n/**\n * Formats cost with appropriate precision based on magnitude.\n *\n * Uses variable precision to balance readability and accuracy:\n * - Very small costs (<$0.001): 5 decimal places to show meaningful value\n * - Small costs (<$0.01): 4 decimal places for precision\n * - Medium costs (<$1): 3 decimal places for clarity\n * - Larger costs (≥$1): 2 decimal places (standard currency format)\n *\n * @param cost - Cost in USD\n * @returns Formatted cost string without currency symbol (e.g., \"0.0123\")\n *\n * @example\n * ```typescript\n * formatCost(0.00012) // \"0.00012\"\n * formatCost(0.0056) // \"0.0056\"\n * formatCost(0.123) // \"0.123\"\n * formatCost(1.5) // \"1.50\"\n * ```\n */\nexport function formatCost(cost: number): string {\n if (cost < 0.001) {\n return cost.toFixed(5);\n }\n if (cost < 0.01) {\n return cost.toFixed(4);\n }\n if (cost < 1) {\n return cost.toFixed(3);\n }\n return cost.toFixed(2);\n}\n\n/**\n * Metadata for generating execution summaries.\n *\n * Contains optional metrics collected during agent/LLM execution.\n * All fields are optional to allow partial summaries when data isn't available.\n */\nexport interface SummaryMetadata {\n /** LLM finish reason (e.g., \"stop\", \"length\", \"tool_calls\") */\n finishReason?: string | null;\n\n /** Token usage statistics from LLM provider */\n usage?: TokenUsage;\n\n /** Number of agent iterations (LLM calls) */\n iterations?: number;\n\n /** Model name/ID being used */\n model?: string;\n\n /** Total cost in USD (calculated via ModelRegistry) */\n cost?: number;\n\n /** Elapsed time in seconds */\n elapsedSeconds?: number;\n}\n\n/**\n * Renders execution metadata as a compact, color-coded summary line.\n *\n * Formats agent/LLM execution metrics in a consistent format used across CLI commands.\n * Only includes fields that have values, making the output clean and concise.\n *\n * **Format:** `#N | ↑ input │ ↓ output │ time | cost | finish`\n *\n * **Color scheme:**\n * - Cyan: Iteration number and cost (highlights key metrics)\n * - Yellow: Input tokens (shows what you sent)\n * - Green: Output tokens (shows what you received)\n * - Dim: Separators and finish reason (de-emphasize metadata)\n *\n * @param metadata - Summary metadata to format\n * @returns Formatted summary string, or null if no fields are populated\n *\n * @example\n * ```typescript\n * // Full summary with all fields (including cached tokens)\n * renderSummary({\n * iterations: 3,\n * usage: { inputTokens: 896, outputTokens: 11500, totalTokens: 12396, cachedInputTokens: 500 },\n * elapsedSeconds: 9,\n * cost: 0.0123,\n * finishReason: \"stop\"\n * });\n * // Output: \"#3 | ↑ 896 | ⟳ 500 | ↓ 11.5k | 9s | $0.0123 | stop\"\n *\n * // Partial summary (only tokens, no cache hit)\n * renderSummary({\n * usage: { inputTokens: 500, outputTokens: 200, totalTokens: 700 }\n * });\n * // Output: \"↑ 500 | ↓ 200\"\n * ```\n */\nexport function renderSummary(metadata: SummaryMetadata): string | null {\n const parts: string[] = [];\n\n // Iteration number and model (#N modelname) - shown first for context\n if (metadata.iterations !== undefined) {\n const iterPart = chalk.cyan(`#${metadata.iterations}`);\n if (metadata.model) {\n parts.push(`${iterPart} ${chalk.magenta(metadata.model)}`);\n } else {\n parts.push(iterPart);\n }\n } else if (metadata.model) {\n // Model without iteration number\n parts.push(chalk.magenta(metadata.model));\n }\n\n // Token usage (↑ input │ ⟳ cached │ ✎ cache-write │ ↓ output) - core metrics\n if (metadata.usage) {\n const { inputTokens, outputTokens, cachedInputTokens, cacheCreationInputTokens } =\n metadata.usage;\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${formatTokens(inputTokens)}`));\n // Show cached tokens if present (indicates prompt caching hit - 0.1x cost)\n if (cachedInputTokens && cachedInputTokens > 0) {\n parts.push(chalk.dim(\"⟳\") + chalk.blue(` ${formatTokens(cachedInputTokens)}`));\n }\n // Show cache creation tokens if present (Anthropic cache writes - 1.25x cost)\n if (cacheCreationInputTokens && cacheCreationInputTokens > 0) {\n parts.push(chalk.dim(\"✎\") + chalk.magenta(` ${formatTokens(cacheCreationInputTokens)}`));\n }\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${formatTokens(outputTokens)}`));\n }\n\n // Elapsed time - performance metric\n if (metadata.elapsedSeconds !== undefined && metadata.elapsedSeconds > 0) {\n parts.push(chalk.dim(`${metadata.elapsedSeconds}s`));\n }\n\n // Cost - financial tracking (showcases ModelRegistry integration)\n if (metadata.cost !== undefined && metadata.cost > 0) {\n parts.push(chalk.cyan(`$${formatCost(metadata.cost)}`));\n }\n\n // Finish reason - completion status (shown last for context)\n if (metadata.finishReason) {\n parts.push(chalk.dim(metadata.finishReason));\n }\n\n // Return null if no fields populated (cleaner than empty string)\n if (parts.length === 0) {\n return null;\n }\n\n // Join with \" | \" separator for visual clarity\n return parts.join(chalk.dim(\" | \"));\n}\n\n/**\n * Metadata for generating overall execution summaries.\n *\n * Used for the final accumulated summary at the end of agent execution.\n */\nexport interface OverallSummaryMetadata {\n /** Total tokens across all calls */\n totalTokens?: number;\n\n /** Number of agent iterations (LLM calls) */\n iterations?: number;\n\n /** Total elapsed time in seconds */\n elapsedSeconds?: number;\n\n /** Total cost in USD */\n cost?: number;\n}\n\n/**\n * Renders overall accumulated execution summary as a distinct styled line.\n *\n * This is displayed at the end of agent execution to show total metrics.\n * Uses a \"total:\" prefix to distinguish from per-call summaries.\n *\n * **Format:** `total: 3.5k | #2 | 19s | $0.0021`\n *\n * @param metadata - Overall summary metadata\n * @returns Formatted summary string, or null if no fields are populated\n *\n * @example\n * ```typescript\n * renderOverallSummary({\n * totalTokens: 3500,\n * iterations: 2,\n * elapsedSeconds: 19,\n * cost: 0.0021\n * });\n * // Output: \"total: 3.5k | #2 | 19s | $0.0021\"\n * ```\n */\nexport function renderOverallSummary(metadata: OverallSummaryMetadata): string | null {\n const parts: string[] = [];\n\n // Total tokens - primary metric for overall summary\n if (metadata.totalTokens !== undefined && metadata.totalTokens > 0) {\n parts.push(chalk.dim(\"total:\") + chalk.magenta(` ${formatTokens(metadata.totalTokens)}`));\n }\n\n // Iteration count (#N)\n if (metadata.iterations !== undefined && metadata.iterations > 0) {\n parts.push(chalk.cyan(`#${metadata.iterations}`));\n }\n\n // Total elapsed time\n if (metadata.elapsedSeconds !== undefined && metadata.elapsedSeconds > 0) {\n parts.push(chalk.dim(`${metadata.elapsedSeconds}s`));\n }\n\n // Total cost\n if (metadata.cost !== undefined && metadata.cost > 0) {\n parts.push(chalk.cyan(`$${formatCost(metadata.cost)}`));\n }\n\n if (parts.length === 0) {\n return null;\n }\n\n return parts.join(chalk.dim(\" | \"));\n}\n\n/**\n * Gadget execution result for formatting.\n *\n * Contains metadata about a single gadget invocation during agent execution.\n */\nexport interface GadgetResult {\n /** Name of the gadget that was executed */\n gadgetName: string;\n\n /** Execution time in milliseconds */\n executionTimeMs: number;\n\n /** Error message if gadget failed */\n error?: string;\n\n /** Result value from successful gadget execution */\n result?: string;\n\n /** Whether this gadget execution ended the agent loop */\n breaksLoop?: boolean;\n\n /** Parameters passed to the gadget */\n parameters?: Record<string, unknown>;\n\n /** Token count for output (calculated via provider API) */\n tokenCount?: number;\n}\n\n/**\n * Formats a gadget execution result as a compact one-liner for stderr output.\n *\n * Provides visual feedback for gadget execution during agent runs. Different\n * icons and colors indicate success, error, or completion states.\n *\n * **Format:**\n * - Success: `✓ GadgetName(param=value, ...) → 248 tokens 123ms`\n * - Error: `✗ GadgetName(param=value) error: message 123ms`\n * - Completion: `⏹ GadgetName(param=value) → 2.5k tokens 123ms`\n *\n * **Design:**\n * - All parameters shown inline (truncated if too long)\n * - Output shown as token count (via provider API) or bytes as fallback\n * - Execution time always shown at the end\n *\n * @param result - Gadget execution result with timing and output info\n * @returns Formatted one-liner string with ANSI colors\n *\n * @example\n * ```typescript\n * // Successful gadget execution with token count\n * formatGadgetSummary({\n * gadgetName: \"ListDirectory\",\n * executionTimeMs: 4,\n * parameters: { path: \".\", recursive: true },\n * result: \"Type | Name | Size...\",\n * tokenCount: 248\n * });\n * // Output: \"✓ ListDirectory(path=., recursive=true) → 248 tokens 4ms\"\n *\n * // Error case\n * formatGadgetSummary({\n * gadgetName: \"ReadFile\",\n * executionTimeMs: 2,\n * parameters: { path: \"/missing.txt\" },\n * error: \"File not found\"\n * });\n * // Output: \"✗ ReadFile(path=/missing.txt) error: File not found 2ms\"\n * ```\n */\n/**\n * Formats parameters as a compact inline string with color-coded keys and values.\n *\n * @param params - Parameter key-value pairs\n * @returns Formatted string with dim keys and cyan values, e.g., \"path=., recursive=true\"\n */\nfunction formatParametersInline(params: Record<string, unknown> | undefined): string {\n if (!params || Object.keys(params).length === 0) {\n return \"\";\n }\n\n return Object.entries(params)\n .map(([key, value]) => {\n // Format value compactly\n let formatted: string;\n if (typeof value === \"string\") {\n // Truncate long strings\n formatted = value.length > 30 ? `${value.slice(0, 30)}…` : value;\n } else if (typeof value === \"boolean\" || typeof value === \"number\") {\n formatted = String(value);\n } else {\n // For arrays/objects, show compact JSON\n const json = JSON.stringify(value);\n formatted = json.length > 30 ? `${json.slice(0, 30)}…` : json;\n }\n // Color: dim key, = sign, cyan value\n return `${chalk.dim(key)}${chalk.dim(\"=\")}${chalk.cyan(formatted)}`;\n })\n .join(chalk.dim(\", \"));\n}\n\n/**\n * Formats byte count in human-readable form.\n *\n * @param bytes - Number of bytes\n * @returns Formatted string like \"245 bytes\" or \"1.2 KB\"\n */\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} bytes`;\n }\n if (bytes < 1024 * 1024) {\n return `${(bytes / 1024).toFixed(1)} KB`;\n }\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nexport function formatGadgetSummary(result: GadgetResult): string {\n // Format gadget name and execution time\n const gadgetLabel = chalk.magenta.bold(result.gadgetName);\n const timeLabel = chalk.dim(`${Math.round(result.executionTimeMs)}ms`);\n\n // Format parameters inline (parentheses are dim, content is color-coded)\n const paramsStr = formatParametersInline(result.parameters);\n const paramsLabel = paramsStr ? `${chalk.dim(\"(\")}${paramsStr}${chalk.dim(\")\")}` : \"\";\n\n // Error case - show error message in red (one-liner)\n if (result.error) {\n const errorMsg = result.error.length > 50 ? `${result.error.slice(0, 50)}…` : result.error;\n return `${chalk.red(\"✗\")} ${gadgetLabel}${paramsLabel} ${chalk.red(\"error:\")} ${errorMsg} ${timeLabel}`;\n }\n\n // Format output size: prefer token count if available, fallback to bytes\n let outputLabel: string;\n if (result.tokenCount !== undefined && result.tokenCount > 0) {\n outputLabel = chalk.green(`${formatTokens(result.tokenCount)} tokens`);\n } else if (result.result) {\n const outputBytes = Buffer.byteLength(result.result, \"utf-8\");\n outputLabel = outputBytes > 0 ? chalk.green(formatBytes(outputBytes)) : chalk.dim(\"no output\");\n } else {\n outputLabel = chalk.dim(\"no output\");\n }\n\n // Build the summary line\n const icon = result.breaksLoop ? chalk.yellow(\"⏹\") : chalk.green(\"✓\");\n const summaryLine = `${icon} ${gadgetLabel}${paramsLabel} ${chalk.dim(\"→\")} ${outputLabel} ${timeLabel}`;\n\n // TellUser gadget: display full message content below the summary (with markdown and separators)\n if (result.gadgetName === \"TellUser\" && result.parameters?.message) {\n const message = String(result.parameters.message);\n const rendered = renderMarkdownWithSeparators(message);\n return `${summaryLine}\\n${rendered}`;\n }\n\n return summaryLine;\n}\n","import type { Command } from \"commander\";\nimport type { AgentConfig, CompleteConfig, CustomCommandConfig } from \"./config.js\";\nimport { DEFAULT_MODEL, OPTION_DESCRIPTIONS, OPTION_FLAGS } from \"./constants.js\";\nimport { createNumericParser } from \"./utils.js\";\n\n/**\n * Options for the complete command (camelCase, matching Commander output).\n */\nexport interface CompleteCommandOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxTokens?: number;\n quiet?: boolean;\n logLlmRequests?: string | boolean;\n logLlmResponses?: string | boolean;\n}\n\n/**\n * Options for the agent command (camelCase, matching Commander output).\n */\nexport interface AgentCommandOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxIterations?: number;\n gadget?: string[];\n builtins: boolean;\n builtinInteraction: boolean;\n gadgetStartPrefix?: string;\n gadgetEndPrefix?: string;\n gadgetArgPrefix?: string;\n quiet?: boolean;\n logLlmRequests?: string | boolean;\n logLlmResponses?: string | boolean;\n}\n\n/**\n * Adds complete command options to a Commander command.\n *\n * @param cmd - Command to add options to\n * @param defaults - Optional defaults from config file\n * @returns The command with options added\n */\nexport function addCompleteOptions(cmd: Command, defaults?: CompleteConfig): Command {\n return cmd\n .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, defaults?.model ?? DEFAULT_MODEL)\n .option(OPTION_FLAGS.systemPrompt, OPTION_DESCRIPTIONS.systemPrompt, defaults?.system)\n .option(\n OPTION_FLAGS.temperature,\n OPTION_DESCRIPTIONS.temperature,\n createNumericParser({ label: \"Temperature\", min: 0, max: 2 }),\n defaults?.temperature,\n )\n .option(\n OPTION_FLAGS.maxTokens,\n OPTION_DESCRIPTIONS.maxTokens,\n createNumericParser({ label: \"Max tokens\", integer: true, min: 1 }),\n defaults?.[\"max-tokens\"],\n )\n .option(OPTION_FLAGS.quiet, OPTION_DESCRIPTIONS.quiet, defaults?.quiet)\n .option(OPTION_FLAGS.logLlmRequests, OPTION_DESCRIPTIONS.logLlmRequests, defaults?.[\"log-llm-requests\"])\n .option(OPTION_FLAGS.logLlmResponses, OPTION_DESCRIPTIONS.logLlmResponses, defaults?.[\"log-llm-responses\"]);\n}\n\n/**\n * Adds agent command options to a Commander command.\n *\n * @param cmd - Command to add options to\n * @param defaults - Optional defaults from config file\n * @returns The command with options added\n */\nexport function addAgentOptions(cmd: Command, defaults?: AgentConfig): Command {\n // Gadget accumulator needs special handling for defaults\n const gadgetAccumulator = (value: string, previous: string[] = []): string[] => [\n ...previous,\n value,\n ];\n const defaultGadgets = defaults?.gadget ?? [];\n\n return cmd\n .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, defaults?.model ?? DEFAULT_MODEL)\n .option(OPTION_FLAGS.systemPrompt, OPTION_DESCRIPTIONS.systemPrompt, defaults?.system)\n .option(\n OPTION_FLAGS.temperature,\n OPTION_DESCRIPTIONS.temperature,\n createNumericParser({ label: \"Temperature\", min: 0, max: 2 }),\n defaults?.temperature,\n )\n .option(\n OPTION_FLAGS.maxIterations,\n OPTION_DESCRIPTIONS.maxIterations,\n createNumericParser({ label: \"Max iterations\", integer: true, min: 1 }),\n defaults?.[\"max-iterations\"],\n )\n .option(OPTION_FLAGS.gadgetModule, OPTION_DESCRIPTIONS.gadgetModule, gadgetAccumulator, [\n ...defaultGadgets,\n ])\n .option(OPTION_FLAGS.noBuiltins, OPTION_DESCRIPTIONS.noBuiltins, defaults?.builtins !== false)\n .option(\n OPTION_FLAGS.noBuiltinInteraction,\n OPTION_DESCRIPTIONS.noBuiltinInteraction,\n defaults?.[\"builtin-interaction\"] !== false,\n )\n .option(OPTION_FLAGS.quiet, OPTION_DESCRIPTIONS.quiet, defaults?.quiet)\n .option(OPTION_FLAGS.logLlmRequests, OPTION_DESCRIPTIONS.logLlmRequests, defaults?.[\"log-llm-requests\"])\n .option(OPTION_FLAGS.logLlmResponses, OPTION_DESCRIPTIONS.logLlmResponses, defaults?.[\"log-llm-responses\"]);\n}\n\n/**\n * Converts kebab-case config to camelCase command options for complete command.\n */\nexport function configToCompleteOptions(config: CustomCommandConfig): Partial<CompleteCommandOptions> {\n const result: Partial<CompleteCommandOptions> = {};\n if (config.model !== undefined) result.model = config.model;\n if (config.system !== undefined) result.system = config.system;\n if (config.temperature !== undefined) result.temperature = config.temperature;\n if (config[\"max-tokens\"] !== undefined) result.maxTokens = config[\"max-tokens\"];\n if (config.quiet !== undefined) result.quiet = config.quiet;\n if (config[\"log-llm-requests\"] !== undefined) result.logLlmRequests = config[\"log-llm-requests\"];\n if (config[\"log-llm-responses\"] !== undefined) result.logLlmResponses = config[\"log-llm-responses\"];\n return result;\n}\n\n/**\n * Converts kebab-case config to camelCase command options for agent command.\n */\nexport function configToAgentOptions(config: CustomCommandConfig): Partial<AgentCommandOptions> {\n const result: Partial<AgentCommandOptions> = {};\n if (config.model !== undefined) result.model = config.model;\n if (config.system !== undefined) result.system = config.system;\n if (config.temperature !== undefined) result.temperature = config.temperature;\n if (config[\"max-iterations\"] !== undefined) result.maxIterations = config[\"max-iterations\"];\n if (config.gadget !== undefined) result.gadget = config.gadget;\n if (config.builtins !== undefined) result.builtins = config.builtins;\n if (config[\"builtin-interaction\"] !== undefined)\n result.builtinInteraction = config[\"builtin-interaction\"];\n if (config[\"gadget-start-prefix\"] !== undefined)\n result.gadgetStartPrefix = config[\"gadget-start-prefix\"];\n if (config[\"gadget-end-prefix\"] !== undefined)\n result.gadgetEndPrefix = config[\"gadget-end-prefix\"];\n if (config[\"gadget-arg-prefix\"] !== undefined)\n result.gadgetArgPrefix = config[\"gadget-arg-prefix\"];\n if (config.quiet !== undefined) result.quiet = config.quiet;\n if (config[\"log-llm-requests\"] !== undefined) result.logLlmRequests = config[\"log-llm-requests\"];\n if (config[\"log-llm-responses\"] !== undefined) result.logLlmResponses = config[\"log-llm-responses\"];\n return result;\n}\n","import type { Command } from \"commander\";\n\nimport { LLMMessageBuilder } from \"../core/messages.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { TokenUsage } from \"../core/options.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"../providers/constants.js\";\nimport type { CompleteConfig } from \"./config.js\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { formatLlmRequest, resolveLogDir, writeLogFile } from \"./llm-logging.js\";\nimport {\n addCompleteOptions,\n type CompleteCommandOptions,\n} from \"./option-helpers.js\";\nimport {\n executeAction,\n renderSummary,\n resolvePrompt,\n StreamPrinter,\n StreamProgress,\n} from \"./utils.js\";\n\n/**\n * Executes the complete command.\n * Streams a single LLM response without agent loop or gadgets.\n *\n * @param promptArg - User prompt from command line argument (optional if using stdin)\n * @param options - Complete command options (model, system prompt, temperature, etc.)\n * @param env - CLI environment for I/O operations\n */\nexport async function executeComplete(\n promptArg: string | undefined,\n options: CompleteCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const prompt = await resolvePrompt(promptArg, env);\n const client = env.createClient();\n const model = resolveModel(options.model);\n\n const builder = new LLMMessageBuilder();\n if (options.system) {\n builder.addSystem(options.system);\n }\n builder.addUser(prompt);\n\n const messages = builder.build();\n\n // Resolve LLM debug log directories (if enabled)\n const llmRequestsDir = resolveLogDir(options.logLlmRequests, \"requests\");\n const llmResponsesDir = resolveLogDir(options.logLlmResponses, \"responses\");\n const timestamp = Date.now();\n\n // Log request before streaming\n if (llmRequestsDir) {\n const filename = `${timestamp}_complete.request.txt`;\n const content = formatLlmRequest(messages);\n await writeLogFile(llmRequestsDir, filename, content);\n }\n\n const stream = client.stream({\n model,\n messages,\n temperature: options.temperature,\n maxTokens: options.maxTokens,\n });\n\n const printer = new StreamPrinter(env.stdout);\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n const progress = new StreamProgress(env.stderr, stderrTTY, client.modelRegistry);\n\n // Start call with model and estimate based on prompt length\n const estimatedInputTokens = Math.round(prompt.length / FALLBACK_CHARS_PER_TOKEN);\n progress.startCall(model, estimatedInputTokens);\n\n let finishReason: string | null | undefined;\n let usage: TokenUsage | undefined;\n let accumulatedResponse = \"\";\n\n for await (const chunk of stream) {\n // Capture actual usage from stream\n if (chunk.usage) {\n usage = chunk.usage;\n if (chunk.usage.inputTokens) {\n progress.setInputTokens(chunk.usage.inputTokens, false);\n }\n if (chunk.usage.outputTokens) {\n progress.setOutputTokens(chunk.usage.outputTokens, false);\n }\n }\n if (chunk.text) {\n progress.pause(); // Must pause to avoid stderr/stdout interleaving\n accumulatedResponse += chunk.text;\n progress.update(accumulatedResponse.length); // Update token estimate from chars\n printer.write(chunk.text);\n }\n if (chunk.finishReason !== undefined) {\n finishReason = chunk.finishReason;\n }\n }\n\n progress.endCall(usage); // Calculate cost before completing\n progress.complete();\n printer.ensureNewline();\n\n // Log response after streaming\n if (llmResponsesDir) {\n const filename = `${timestamp}_complete.response.txt`;\n await writeLogFile(llmResponsesDir, filename, accumulatedResponse);\n }\n\n // Only show summary if stderr is a TTY (not redirected) and not in quiet mode\n if (stderrTTY && !options.quiet) {\n const summary = renderSummary({ finishReason, usage, cost: progress.getTotalCost() });\n if (summary) {\n env.stderr.write(`${summary}\\n`);\n }\n }\n}\n\n/**\n * Registers the complete command with the CLI program.\n * Configures options for model, system prompt, temperature, and max tokens.\n *\n * @param program - Commander program to register the command with\n * @param env - CLI environment for dependencies and I/O\n * @param config - Optional configuration defaults from config file\n */\nexport function registerCompleteCommand(\n program: Command,\n env: CLIEnvironment,\n config?: CompleteConfig,\n): void {\n const cmd = program\n .command(COMMANDS.complete)\n .description(\"Stream a single completion from a specified model.\")\n .argument(\"[prompt]\", \"Prompt to send to the LLM. If omitted, stdin is used when available.\");\n\n addCompleteOptions(cmd, config);\n\n cmd.action((prompt, options) =>\n executeAction(() => executeComplete(prompt, options as CompleteCommandOptions, env), env),\n );\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { load as parseToml } from \"js-toml\";\nimport {\n type PromptsConfig,\n TemplateError,\n createTemplateEngine,\n hasTemplateSyntax,\n resolveTemplate,\n validateEnvVars,\n validatePrompts,\n} from \"./templates.js\";\n\n// Re-export PromptsConfig for consumers\nexport type { PromptsConfig } from \"./templates.js\";\n\n/**\n * Valid log level names.\n */\nexport type LogLevel = \"silly\" | \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n\n/**\n * Global CLI options that apply to all commands.\n */\nexport interface GlobalConfig {\n \"log-level\"?: LogLevel;\n \"log-file\"?: string;\n \"log-reset\"?: boolean;\n}\n\n/**\n * Base options shared by both complete and agent command configurations.\n */\nexport interface BaseCommandConfig {\n model?: string;\n system?: string;\n temperature?: number;\n inherits?: string | string[];\n}\n\n/**\n * Configuration for the complete command.\n */\nexport interface CompleteConfig extends BaseCommandConfig {\n \"max-tokens\"?: number;\n quiet?: boolean;\n \"log-level\"?: LogLevel;\n \"log-file\"?: string;\n \"log-reset\"?: boolean;\n \"log-llm-requests\"?: string | boolean;\n \"log-llm-responses\"?: string | boolean;\n}\n\n/**\n * Configuration for the agent command.\n */\nexport interface AgentConfig extends BaseCommandConfig {\n \"max-iterations\"?: number;\n gadget?: string[];\n builtins?: boolean;\n \"builtin-interaction\"?: boolean;\n \"gadget-start-prefix\"?: string;\n \"gadget-end-prefix\"?: string;\n \"gadget-arg-prefix\"?: string;\n quiet?: boolean;\n \"log-level\"?: LogLevel;\n \"log-file\"?: string;\n \"log-reset\"?: boolean;\n \"log-llm-requests\"?: string | boolean;\n \"log-llm-responses\"?: string | boolean;\n}\n\n/**\n * Command type determines execution behavior.\n */\nexport type CommandType = \"agent\" | \"complete\";\n\n/**\n * Custom command configuration from config file.\n * Extends both agent and complete configs, with type determining behavior.\n */\nexport interface CustomCommandConfig extends AgentConfig, CompleteConfig {\n type?: CommandType;\n description?: string;\n}\n\n/**\n * Root configuration structure matching ~/.llmist/cli.toml.\n */\nexport interface CLIConfig {\n global?: GlobalConfig;\n complete?: CompleteConfig;\n agent?: AgentConfig;\n prompts?: PromptsConfig;\n [customCommand: string]:\n | CustomCommandConfig\n | CompleteConfig\n | AgentConfig\n | GlobalConfig\n | PromptsConfig\n | undefined;\n}\n\n/** Valid keys for global config */\nconst GLOBAL_CONFIG_KEYS = new Set([\"log-level\", \"log-file\", \"log-reset\"]);\n\n/** Valid log levels */\nconst VALID_LOG_LEVELS: LogLevel[] = [\"silly\", \"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"];\n\n/** Valid keys for complete command config */\nconst COMPLETE_CONFIG_KEYS = new Set([\n \"model\",\n \"system\",\n \"temperature\",\n \"max-tokens\",\n \"quiet\",\n \"inherits\",\n \"log-level\",\n \"log-file\",\n \"log-reset\",\n \"log-llm-requests\",\n \"log-llm-responses\",\n \"type\", // Allowed for inheritance compatibility, ignored for built-in commands\n]);\n\n/** Valid keys for agent command config */\nconst AGENT_CONFIG_KEYS = new Set([\n \"model\",\n \"system\",\n \"temperature\",\n \"max-iterations\",\n \"gadget\",\n \"builtins\",\n \"builtin-interaction\",\n \"gadget-start-prefix\",\n \"gadget-end-prefix\",\n \"gadget-arg-prefix\",\n \"quiet\",\n \"inherits\",\n \"log-level\",\n \"log-file\",\n \"log-reset\",\n \"log-llm-requests\",\n \"log-llm-responses\",\n \"type\", // Allowed for inheritance compatibility, ignored for built-in commands\n]);\n\n/** Valid keys for custom command config (union of complete + agent + type + description) */\nconst CUSTOM_CONFIG_KEYS = new Set([\n ...COMPLETE_CONFIG_KEYS,\n ...AGENT_CONFIG_KEYS,\n \"type\",\n \"description\",\n]);\n\n/**\n * Returns the default config file path: ~/.llmist/cli.toml\n */\nexport function getConfigPath(): string {\n return join(homedir(), \".llmist\", \"cli.toml\");\n}\n\n/**\n * Configuration validation error.\n */\nexport class ConfigError extends Error {\n constructor(\n message: string,\n public readonly path?: string,\n ) {\n super(path ? `${path}: ${message}` : message);\n this.name = \"ConfigError\";\n }\n}\n\n/**\n * Validates that a value is a string.\n */\nfunction validateString(value: unknown, key: string, section: string): string {\n if (typeof value !== \"string\") {\n throw new ConfigError(`[${section}].${key} must be a string`);\n }\n return value;\n}\n\n/**\n * Validates that a value is a number within optional bounds.\n */\nfunction validateNumber(\n value: unknown,\n key: string,\n section: string,\n opts?: { min?: number; max?: number; integer?: boolean },\n): number {\n if (typeof value !== \"number\") {\n throw new ConfigError(`[${section}].${key} must be a number`);\n }\n if (opts?.integer && !Number.isInteger(value)) {\n throw new ConfigError(`[${section}].${key} must be an integer`);\n }\n if (opts?.min !== undefined && value < opts.min) {\n throw new ConfigError(`[${section}].${key} must be >= ${opts.min}`);\n }\n if (opts?.max !== undefined && value > opts.max) {\n throw new ConfigError(`[${section}].${key} must be <= ${opts.max}`);\n }\n return value;\n}\n\n/**\n * Validates that a value is a boolean.\n */\nfunction validateBoolean(value: unknown, key: string, section: string): boolean {\n if (typeof value !== \"boolean\") {\n throw new ConfigError(`[${section}].${key} must be a boolean`);\n }\n return value;\n}\n\n/**\n * Validates that a value is an array of strings.\n */\nfunction validateStringArray(value: unknown, key: string, section: string): string[] {\n if (!Array.isArray(value)) {\n throw new ConfigError(`[${section}].${key} must be an array`);\n }\n for (let i = 0; i < value.length; i++) {\n if (typeof value[i] !== \"string\") {\n throw new ConfigError(`[${section}].${key}[${i}] must be a string`);\n }\n }\n return value as string[];\n}\n\n/**\n * Validates that a value is a string or array of strings (for inherits field).\n */\nfunction validateInherits(value: unknown, section: string): string | string[] {\n if (typeof value === \"string\") {\n return value;\n }\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n if (typeof value[i] !== \"string\") {\n throw new ConfigError(`[${section}].inherits[${i}] must be a string`);\n }\n }\n return value as string[];\n }\n throw new ConfigError(`[${section}].inherits must be a string or array of strings`);\n}\n\n/**\n * Validates and extracts logging config fields from a raw object.\n */\nfunction validateLoggingConfig(\n raw: Record<string, unknown>,\n section: string,\n): { \"log-level\"?: LogLevel; \"log-file\"?: string; \"log-reset\"?: boolean } {\n const result: { \"log-level\"?: LogLevel; \"log-file\"?: string; \"log-reset\"?: boolean } = {};\n\n if (\"log-level\" in raw) {\n const level = validateString(raw[\"log-level\"], \"log-level\", section);\n if (!VALID_LOG_LEVELS.includes(level as LogLevel)) {\n throw new ConfigError(\n `[${section}].log-level must be one of: ${VALID_LOG_LEVELS.join(\", \")}`,\n );\n }\n result[\"log-level\"] = level as LogLevel;\n }\n if (\"log-file\" in raw) {\n result[\"log-file\"] = validateString(raw[\"log-file\"], \"log-file\", section);\n }\n if (\"log-reset\" in raw) {\n result[\"log-reset\"] = validateBoolean(raw[\"log-reset\"], \"log-reset\", section);\n }\n\n return result;\n}\n\n/**\n * Validates and extracts base command config fields.\n */\nfunction validateBaseConfig(\n raw: Record<string, unknown>,\n section: string,\n): Partial<BaseCommandConfig> {\n const result: Partial<BaseCommandConfig> = {};\n\n if (\"model\" in raw) {\n result.model = validateString(raw.model, \"model\", section);\n }\n if (\"system\" in raw) {\n result.system = validateString(raw.system, \"system\", section);\n }\n if (\"temperature\" in raw) {\n result.temperature = validateNumber(raw.temperature, \"temperature\", section, {\n min: 0,\n max: 2,\n });\n }\n if (\"inherits\" in raw) {\n result.inherits = validateInherits(raw.inherits, section);\n }\n\n return result;\n}\n\n/**\n * Validates the global config section.\n */\nfunction validateGlobalConfig(raw: unknown, section: string): GlobalConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!GLOBAL_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n return validateLoggingConfig(rawObj, section);\n}\n\n/**\n * Validates a complete command config section.\n */\nfunction validateCompleteConfig(raw: unknown, section: string): CompleteConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!COMPLETE_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n const result: CompleteConfig = {\n ...validateBaseConfig(rawObj, section),\n ...validateLoggingConfig(rawObj, section),\n };\n\n if (\"max-tokens\" in rawObj) {\n result[\"max-tokens\"] = validateNumber(rawObj[\"max-tokens\"], \"max-tokens\", section, {\n integer: true,\n min: 1,\n });\n }\n if (\"quiet\" in rawObj) {\n result.quiet = validateBoolean(rawObj.quiet, \"quiet\", section);\n }\n if (\"log-llm-requests\" in rawObj) {\n result[\"log-llm-requests\"] = validateStringOrBoolean(\n rawObj[\"log-llm-requests\"],\n \"log-llm-requests\",\n section,\n );\n }\n if (\"log-llm-responses\" in rawObj) {\n result[\"log-llm-responses\"] = validateStringOrBoolean(\n rawObj[\"log-llm-responses\"],\n \"log-llm-responses\",\n section,\n );\n }\n\n return result;\n}\n\n/**\n * Validates an agent command config section.\n */\nfunction validateAgentConfig(raw: unknown, section: string): AgentConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!AGENT_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n const result: AgentConfig = {\n ...validateBaseConfig(rawObj, section),\n ...validateLoggingConfig(rawObj, section),\n };\n\n if (\"max-iterations\" in rawObj) {\n result[\"max-iterations\"] = validateNumber(rawObj[\"max-iterations\"], \"max-iterations\", section, {\n integer: true,\n min: 1,\n });\n }\n if (\"gadget\" in rawObj) {\n result.gadget = validateStringArray(rawObj.gadget, \"gadget\", section);\n }\n if (\"builtins\" in rawObj) {\n result.builtins = validateBoolean(rawObj.builtins, \"builtins\", section);\n }\n if (\"builtin-interaction\" in rawObj) {\n result[\"builtin-interaction\"] = validateBoolean(\n rawObj[\"builtin-interaction\"],\n \"builtin-interaction\",\n section,\n );\n }\n if (\"gadget-start-prefix\" in rawObj) {\n result[\"gadget-start-prefix\"] = validateString(\n rawObj[\"gadget-start-prefix\"],\n \"gadget-start-prefix\",\n section,\n );\n }\n if (\"gadget-end-prefix\" in rawObj) {\n result[\"gadget-end-prefix\"] = validateString(\n rawObj[\"gadget-end-prefix\"],\n \"gadget-end-prefix\",\n section,\n );\n }\n if (\"gadget-arg-prefix\" in rawObj) {\n result[\"gadget-arg-prefix\"] = validateString(\n rawObj[\"gadget-arg-prefix\"],\n \"gadget-arg-prefix\",\n section,\n );\n }\n if (\"quiet\" in rawObj) {\n result.quiet = validateBoolean(rawObj.quiet, \"quiet\", section);\n }\n if (\"log-llm-requests\" in rawObj) {\n result[\"log-llm-requests\"] = validateStringOrBoolean(\n rawObj[\"log-llm-requests\"],\n \"log-llm-requests\",\n section,\n );\n }\n if (\"log-llm-responses\" in rawObj) {\n result[\"log-llm-responses\"] = validateStringOrBoolean(\n rawObj[\"log-llm-responses\"],\n \"log-llm-responses\",\n section,\n );\n }\n\n return result;\n}\n\n/**\n * Validates a value is either a string or boolean.\n */\nfunction validateStringOrBoolean(value: unknown, field: string, section: string): string | boolean {\n if (typeof value === \"string\" || typeof value === \"boolean\") {\n return value;\n }\n throw new ConfigError(`[${section}].${field} must be a string or boolean`);\n}\n\n/**\n * Validates a custom command config section.\n */\nfunction validateCustomConfig(raw: unknown, section: string): CustomCommandConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!CUSTOM_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n // Get the type first to validate properly\n let type: CommandType = \"agent\"; // Default\n if (\"type\" in rawObj) {\n const typeValue = validateString(rawObj.type, \"type\", section);\n if (typeValue !== \"agent\" && typeValue !== \"complete\") {\n throw new ConfigError(`[${section}].type must be \"agent\" or \"complete\"`);\n }\n type = typeValue;\n }\n\n // Validate base fields + type-specific fields\n const result: CustomCommandConfig = {\n ...validateBaseConfig(rawObj, section),\n type,\n };\n\n if (\"description\" in rawObj) {\n result.description = validateString(rawObj.description, \"description\", section);\n }\n\n // Always allow agent-specific fields (they'll be ignored for complete type)\n if (\"max-iterations\" in rawObj) {\n result[\"max-iterations\"] = validateNumber(rawObj[\"max-iterations\"], \"max-iterations\", section, {\n integer: true,\n min: 1,\n });\n }\n if (\"gadget\" in rawObj) {\n result.gadget = validateStringArray(rawObj.gadget, \"gadget\", section);\n }\n if (\"builtins\" in rawObj) {\n result.builtins = validateBoolean(rawObj.builtins, \"builtins\", section);\n }\n if (\"builtin-interaction\" in rawObj) {\n result[\"builtin-interaction\"] = validateBoolean(\n rawObj[\"builtin-interaction\"],\n \"builtin-interaction\",\n section,\n );\n }\n if (\"gadget-start-prefix\" in rawObj) {\n result[\"gadget-start-prefix\"] = validateString(\n rawObj[\"gadget-start-prefix\"],\n \"gadget-start-prefix\",\n section,\n );\n }\n if (\"gadget-end-prefix\" in rawObj) {\n result[\"gadget-end-prefix\"] = validateString(\n rawObj[\"gadget-end-prefix\"],\n \"gadget-end-prefix\",\n section,\n );\n }\n if (\"gadget-arg-prefix\" in rawObj) {\n result[\"gadget-arg-prefix\"] = validateString(\n rawObj[\"gadget-arg-prefix\"],\n \"gadget-arg-prefix\",\n section,\n );\n }\n\n // Complete-specific fields\n if (\"max-tokens\" in rawObj) {\n result[\"max-tokens\"] = validateNumber(rawObj[\"max-tokens\"], \"max-tokens\", section, {\n integer: true,\n min: 1,\n });\n }\n\n // Shared fields\n if (\"quiet\" in rawObj) {\n result.quiet = validateBoolean(rawObj.quiet, \"quiet\", section);\n }\n\n // Logging options\n Object.assign(result, validateLoggingConfig(rawObj, section));\n\n return result;\n}\n\n/**\n * Validates the prompts config section.\n * Each key must be a string (prompt name) and each value must be a string (template).\n */\nfunction validatePromptsConfig(raw: unknown, section: string): PromptsConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const result: PromptsConfig = {};\n for (const [key, value] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof value !== \"string\") {\n throw new ConfigError(`[${section}].${key} must be a string`);\n }\n result[key] = value;\n }\n return result;\n}\n\n/**\n * Validates and normalizes raw TOML object to CLIConfig.\n *\n * @throws ConfigError if validation fails\n */\nexport function validateConfig(raw: unknown, configPath?: string): CLIConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(\"Config must be a TOML table\", configPath);\n }\n\n const rawObj = raw as Record<string, unknown>;\n const result: CLIConfig = {};\n\n for (const [key, value] of Object.entries(rawObj)) {\n try {\n if (key === \"global\") {\n result.global = validateGlobalConfig(value, key);\n } else if (key === \"complete\") {\n result.complete = validateCompleteConfig(value, key);\n } else if (key === \"agent\") {\n result.agent = validateAgentConfig(value, key);\n } else if (key === \"prompts\") {\n result.prompts = validatePromptsConfig(value, key);\n } else {\n // Custom command section\n result[key] = validateCustomConfig(value, key);\n }\n } catch (error) {\n if (error instanceof ConfigError) {\n throw new ConfigError(error.message, configPath);\n }\n throw error;\n }\n }\n\n return result;\n}\n\n/**\n * Loads configuration from the default path (~/.llmist/cli.toml).\n * Returns empty config if file doesn't exist.\n *\n * @throws ConfigError if file exists but has invalid syntax or unknown fields\n */\nexport function loadConfig(): CLIConfig {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n return {};\n }\n\n let content: string;\n try {\n content = readFileSync(configPath, \"utf-8\");\n } catch (error) {\n throw new ConfigError(\n `Failed to read config file: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n configPath,\n );\n }\n\n let raw: unknown;\n try {\n raw = parseToml(content);\n } catch (error) {\n throw new ConfigError(\n `Invalid TOML syntax: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n configPath,\n );\n }\n\n const validated = validateConfig(raw, configPath);\n const inherited = resolveInheritance(validated, configPath);\n return resolveTemplatesInConfig(inherited, configPath);\n}\n\n/**\n * Gets list of custom command names from config (excludes built-in sections).\n */\nexport function getCustomCommandNames(config: CLIConfig): string[] {\n const reserved = new Set([\"global\", \"complete\", \"agent\", \"prompts\"]);\n return Object.keys(config).filter((key) => !reserved.has(key));\n}\n\n/**\n * Resolves Eta templates in system prompts throughout the config.\n * Templates are resolved using the [prompts] section as named partials.\n *\n * @param config - Config with inheritance already resolved\n * @param configPath - Path to config file for error messages\n * @returns Config with all templates resolved in system prompts\n * @throws ConfigError if template resolution fails\n */\nexport function resolveTemplatesInConfig(config: CLIConfig, configPath?: string): CLIConfig {\n const prompts = config.prompts ?? {};\n\n // If no prompts and no templates used, return as-is\n const hasPrompts = Object.keys(prompts).length > 0;\n\n // Check if any section uses template syntax\n let hasTemplates = false;\n for (const [sectionName, section] of Object.entries(config)) {\n if (sectionName === \"global\" || sectionName === \"prompts\") continue;\n if (!section || typeof section !== \"object\") continue;\n\n const sectionObj = section as Record<string, unknown>;\n if (typeof sectionObj.system === \"string\" && hasTemplateSyntax(sectionObj.system)) {\n hasTemplates = true;\n break;\n }\n }\n\n // Also check prompts for template syntax (they may reference each other)\n for (const template of Object.values(prompts)) {\n if (hasTemplateSyntax(template)) {\n hasTemplates = true;\n break;\n }\n }\n\n // Quick return if nothing to do\n if (!hasPrompts && !hasTemplates) {\n return config;\n }\n\n // Validate all prompts compile correctly and env vars exist\n try {\n validatePrompts(prompts, configPath);\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(error.message, configPath);\n }\n throw error;\n }\n\n // Validate environment variables in all prompts\n for (const [name, template] of Object.entries(prompts)) {\n try {\n validateEnvVars(template, name, configPath);\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(error.message, configPath);\n }\n throw error;\n }\n }\n\n // Create template engine with all prompts registered\n const eta = createTemplateEngine(prompts, configPath);\n const result = { ...config };\n\n // Resolve templates in all sections with system fields\n for (const [sectionName, section] of Object.entries(config)) {\n if (sectionName === \"global\" || sectionName === \"prompts\") continue;\n if (!section || typeof section !== \"object\") continue;\n\n const sectionObj = section as Record<string, unknown>;\n if (typeof sectionObj.system === \"string\" && hasTemplateSyntax(sectionObj.system)) {\n // Validate env vars in the system prompt itself\n try {\n validateEnvVars(sectionObj.system, undefined, configPath);\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(`[${sectionName}].system: ${error.message}`, configPath);\n }\n throw error;\n }\n\n // Resolve the template\n try {\n const resolved = resolveTemplate(eta, sectionObj.system, {}, configPath);\n result[sectionName] = {\n ...sectionObj,\n system: resolved,\n };\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(`[${sectionName}].system: ${error.message}`, configPath);\n }\n throw error;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Resolves inheritance chains for all sections in the config.\n * Each section can specify `inherits` as a string or array of strings.\n * Resolution follows these rules:\n * - For multiple parents, later parents override earlier ones (last wins)\n * - Section's own values always override inherited values\n * - Arrays are replaced, not merged\n * - Circular inheritance is detected and throws an error\n *\n * @param config - Validated config with possible unresolved inheritance\n * @param configPath - Path to config file for error messages\n * @returns Config with all inheritance resolved\n * @throws ConfigError if circular inheritance or unknown parent section\n */\nexport function resolveInheritance(config: CLIConfig, configPath?: string): CLIConfig {\n const resolved: Record<string, Record<string, unknown>> = {};\n const resolving = new Set<string>(); // For cycle detection\n\n function resolveSection(name: string): Record<string, unknown> {\n // Return cached if already resolved\n if (name in resolved) {\n return resolved[name];\n }\n\n // Cycle detection\n if (resolving.has(name)) {\n throw new ConfigError(`Circular inheritance detected: ${name}`, configPath);\n }\n\n const section = config[name];\n if (section === undefined || typeof section !== \"object\") {\n throw new ConfigError(`Cannot inherit from unknown section: ${name}`, configPath);\n }\n\n resolving.add(name);\n\n // Get inheritance list (normalize to array)\n const sectionObj = section as Record<string, unknown>;\n const inheritsRaw = sectionObj.inherits;\n const inheritsList: string[] = inheritsRaw\n ? Array.isArray(inheritsRaw)\n ? inheritsRaw\n : [inheritsRaw]\n : [];\n\n // Resolve all parents first (recursive), merge in order (last wins)\n let merged: Record<string, unknown> = {};\n for (const parent of inheritsList) {\n const parentResolved = resolveSection(parent);\n merged = { ...merged, ...parentResolved };\n }\n\n // Apply own values on top (excluding 'inherits' key - it's metadata, not a value)\n const { inherits: _inherits, ...ownValues } = sectionObj;\n merged = { ...merged, ...ownValues };\n\n resolving.delete(name);\n resolved[name] = merged;\n return merged;\n }\n\n // Resolve all sections\n for (const name of Object.keys(config)) {\n resolveSection(name);\n }\n\n return resolved as unknown as CLIConfig;\n}\n","import { Eta } from \"eta\";\n\n/**\n * Configuration for reusable prompt templates.\n * Each key is a prompt name, value is the template string.\n */\nexport interface PromptsConfig {\n [name: string]: string;\n}\n\n/**\n * Error thrown when template processing fails.\n */\nexport class TemplateError extends Error {\n constructor(\n message: string,\n public readonly promptName?: string,\n public readonly configPath?: string,\n ) {\n super(promptName ? `[prompts.${promptName}]: ${message}` : message);\n this.name = \"TemplateError\";\n }\n}\n\n/**\n * Creates an Eta instance configured with prompts as named templates.\n * Templates are registered with an @ prefix (e.g., @base-assistant).\n *\n * @param prompts - Map of prompt names to template strings\n * @param configPath - Path to config file for error messages\n * @returns Configured Eta instance\n * @throws TemplateError if a template has invalid syntax\n */\nexport function createTemplateEngine(prompts: PromptsConfig, configPath?: string): Eta {\n const eta = new Eta({\n views: \"/\", // Required but we use named templates\n autoEscape: false, // Don't escape - these are prompts, not HTML\n autoTrim: false, // Preserve whitespace in prompts\n });\n\n // Register all prompts as named templates with @ prefix\n // loadTemplate parses the template and will throw on syntax errors\n for (const [name, template] of Object.entries(prompts)) {\n try {\n eta.loadTemplate(`@${name}`, template);\n } catch (error) {\n throw new TemplateError(\n error instanceof Error ? error.message : String(error),\n name,\n configPath,\n );\n }\n }\n\n return eta;\n}\n\n/**\n * Resolves a template string using the configured Eta engine.\n * Injects environment variables into the context.\n *\n * @param eta - Configured Eta instance\n * @param template - Template string to resolve\n * @param context - Additional context variables\n * @param configPath - Path to config file for error messages\n * @returns Resolved template string\n */\nexport function resolveTemplate(\n eta: Eta,\n template: string,\n context: Record<string, unknown> = {},\n configPath?: string,\n): string {\n try {\n // Merge env vars into context\n const fullContext = {\n ...context,\n env: process.env,\n };\n return eta.renderString(template, fullContext);\n } catch (error) {\n throw new TemplateError(\n error instanceof Error ? error.message : String(error),\n undefined,\n configPath,\n );\n }\n}\n\n/**\n * Validates that all prompts can be compiled and references exist.\n * This is called at config load time to fail fast on errors.\n *\n * @param prompts - Map of prompt names to template strings\n * @param configPath - Path to config file for error messages\n * @throws TemplateError if validation fails\n */\nexport function validatePrompts(prompts: PromptsConfig, configPath?: string): void {\n // createTemplateEngine will throw TemplateError on syntax errors during loadTemplate\n const eta = createTemplateEngine(prompts, configPath);\n\n // Also try to render each template to catch missing includes\n for (const [name, template] of Object.entries(prompts)) {\n try {\n // Try to render with empty context to catch missing includes\n // (references to undefined prompts)\n eta.renderString(template, { env: {} });\n } catch (error) {\n throw new TemplateError(\n error instanceof Error ? error.message : String(error),\n name,\n configPath,\n );\n }\n }\n}\n\n/**\n * Validates that all environment variables referenced in a template are defined.\n *\n * @param template - Template string to check\n * @param promptName - Name of the prompt for error messages\n * @param configPath - Path to config file for error messages\n * @throws TemplateError if an undefined env var is referenced\n */\nexport function validateEnvVars(\n template: string,\n promptName?: string,\n configPath?: string,\n): void {\n // Match <%= it.env.VAR_NAME %> patterns\n const envVarPattern = /<%=\\s*it\\.env\\.(\\w+)\\s*%>/g;\n const matches = template.matchAll(envVarPattern);\n\n for (const match of matches) {\n const varName = match[1] as string;\n if (process.env[varName] === undefined) {\n throw new TemplateError(\n `Environment variable '${varName}' is not set`,\n promptName,\n configPath,\n );\n }\n }\n}\n\n/**\n * Checks if a string contains Eta template syntax.\n * Used to determine if a system prompt needs template resolution.\n *\n * @param str - String to check\n * @returns true if the string contains template syntax\n */\nexport function hasTemplateSyntax(str: string): boolean {\n return str.includes(\"<%\");\n}\n","/**\n * CLI command for testing and inspecting gadgets outside the agent loop.\n * Provides `gadget run`, `gadget info`, and `gadget validate` subcommands.\n *\n * @module cli/gadget-command\n */\n\nimport type { Command } from \"commander\";\nimport chalk from \"chalk\";\n\nimport type { BaseGadget } from \"../gadgets/gadget.js\";\nimport { schemaToJSONSchema } from \"../gadgets/schema-to-json.js\";\nimport { validateGadgetSchema } from \"../gadgets/schema-validator.js\";\n\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { loadGadgets } from \"./gadgets.js\";\nimport { promptForParameters, readStdinJson } from \"./gadget-prompts.js\";\nimport { executeAction } from \"./utils.js\";\n\n/**\n * Result of selecting a gadget from a file.\n */\ninterface GadgetSelection {\n gadget: BaseGadget;\n name: string;\n}\n\n/**\n * Options for the `gadget run` subcommand.\n */\ninterface GadgetRunOptions {\n name?: string;\n json?: boolean;\n raw?: boolean;\n}\n\n/**\n * Options for the `gadget info` subcommand.\n */\ninterface GadgetInfoOptions {\n name?: string;\n json?: boolean;\n}\n\n/**\n * Loads and selects a gadget from a file.\n * - Single gadget: returns it directly\n * - Multiple gadgets without --name: throws error listing available names\n * - Multiple gadgets with --name: finds matching gadget\n *\n * @param file - Path to gadget file\n * @param nameOption - Optional gadget name for selection\n * @param cwd - Current working directory\n * @returns Selected gadget with its name\n */\nasync function selectGadget(\n file: string,\n nameOption: string | undefined,\n cwd: string,\n): Promise<GadgetSelection> {\n const gadgets = await loadGadgets([file], cwd);\n\n if (gadgets.length === 0) {\n throw new Error(\n `No gadgets found in '${file}'.\\n` +\n \"Ensure the file exports a Gadget class or instance.\",\n );\n }\n\n // Single gadget - return it\n if (gadgets.length === 1) {\n const gadget = gadgets[0];\n const name = gadget.name ?? gadget.constructor.name;\n return { gadget, name };\n }\n\n // Multiple gadgets - need --name selection\n const names = gadgets.map((g) => g.name ?? g.constructor.name);\n\n if (!nameOption) {\n throw new Error(\n `File '${file}' exports ${gadgets.length} gadgets.\\n` +\n `Use --name to select one:\\n` +\n names.map((n) => ` - ${n}`).join(\"\\n\"),\n );\n }\n\n // Find by name (case-sensitive)\n const found = gadgets.find((g) => (g.name ?? g.constructor.name) === nameOption);\n\n if (!found) {\n throw new Error(\n `Gadget '${nameOption}' not found in '${file}'.\\n` +\n `Available gadgets:\\n` +\n names.map((n) => ` - ${n}`).join(\"\\n\"),\n );\n }\n\n return { gadget: found, name: nameOption };\n}\n\n/**\n * Executes the `gadget run` subcommand.\n * Loads a gadget, prompts for parameters (or reads from stdin), and executes it.\n */\nasync function executeGadgetRun(\n file: string,\n options: GadgetRunOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const cwd = process.cwd();\n const { gadget, name } = await selectGadget(file, options.name, cwd);\n\n env.stderr.write(chalk.cyan.bold(`\\n🔧 Running gadget: ${name}\\n`));\n\n // Get parameters - either interactive or from stdin\n let params: Record<string, unknown>;\n\n if (env.isTTY) {\n // Interactive mode: prompt for each parameter\n params = await promptForParameters(gadget.parameterSchema, {\n stdin: env.stdin,\n stdout: env.stderr, // Prompts go to stderr to keep stdout clean\n });\n } else {\n // Non-TTY mode: read JSON from stdin\n env.stderr.write(chalk.dim(\"Reading parameters from stdin...\\n\"));\n const stdinParams = await readStdinJson(env.stdin);\n\n // Validate through Zod if schema exists\n if (gadget.parameterSchema) {\n const result = gadget.parameterSchema.safeParse(stdinParams);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid parameters:\\n${issues}`);\n }\n params = result.data as Record<string, unknown>;\n } else {\n params = stdinParams;\n }\n }\n\n env.stderr.write(chalk.dim(\"\\nExecuting...\\n\"));\n\n // Execute with timeout if configured\n const startTime = Date.now();\n let result: string;\n\n try {\n if (gadget.timeoutMs && gadget.timeoutMs > 0) {\n result = await Promise.race([\n Promise.resolve(gadget.execute(params)),\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`Gadget timed out after ${gadget.timeoutMs}ms`)),\n gadget.timeoutMs,\n ),\n ),\n ]);\n } else {\n result = await Promise.resolve(gadget.execute(params));\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Execution failed: ${message}`);\n }\n\n const elapsed = Date.now() - startTime;\n env.stderr.write(chalk.green(`\\n✓ Completed in ${elapsed}ms\\n\\n`));\n\n // Output result\n formatOutput(result, options, env.stdout);\n}\n\n/**\n * Formats and writes the gadget execution result to stdout.\n */\nfunction formatOutput(\n result: string,\n options: GadgetRunOptions,\n stdout: NodeJS.WritableStream,\n): void {\n // Raw mode: output as-is\n if (options.raw) {\n stdout.write(result);\n if (!result.endsWith(\"\\n\")) stdout.write(\"\\n\");\n return;\n }\n\n // JSON mode or auto-detect JSON\n if (options.json || looksLikeJson(result)) {\n try {\n const parsed = JSON.parse(result);\n stdout.write(JSON.stringify(parsed, null, 2) + \"\\n\");\n return;\n } catch {\n // Not valid JSON, output as-is\n }\n }\n\n // Default: output as-is with trailing newline\n stdout.write(result);\n if (!result.endsWith(\"\\n\")) stdout.write(\"\\n\");\n}\n\n/**\n * Checks if a string looks like JSON (starts with { or [).\n */\nfunction looksLikeJson(str: string): boolean {\n const trimmed = str.trim();\n return (\n (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) ||\n (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\"))\n );\n}\n\n/**\n * Executes the `gadget info` subcommand.\n * Displays gadget description, schema, and examples.\n */\nasync function executeGadgetInfo(\n file: string,\n options: GadgetInfoOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const cwd = process.cwd();\n const { gadget, name } = await selectGadget(file, options.name, cwd);\n\n if (options.json) {\n // JSON output for programmatic use\n const info = buildGadgetInfo(gadget, name);\n env.stdout.write(JSON.stringify(info, null, 2) + \"\\n\");\n return;\n }\n\n // Pretty-printed output\n env.stdout.write(\"\\n\");\n env.stdout.write(chalk.cyan.bold(`${name}\\n`));\n env.stdout.write(chalk.cyan(\"═\".repeat(name.length)) + \"\\n\\n\");\n\n // Description\n env.stdout.write(chalk.bold(\"Description:\\n\"));\n env.stdout.write(` ${gadget.description}\\n\\n`);\n\n // Parameters\n if (gadget.parameterSchema) {\n env.stdout.write(chalk.bold(\"Parameters:\\n\"));\n const jsonSchema = schemaToJSONSchema(gadget.parameterSchema, { target: \"draft-7\" });\n env.stdout.write(formatSchemaAsText(jsonSchema, \" \") + \"\\n\\n\");\n } else {\n env.stdout.write(chalk.dim(\"No parameters required.\\n\\n\"));\n }\n\n // Timeout\n if (gadget.timeoutMs) {\n env.stdout.write(chalk.bold(\"Timeout:\\n\"));\n env.stdout.write(` ${gadget.timeoutMs}ms\\n\\n`);\n }\n\n // Examples\n if (gadget.examples && gadget.examples.length > 0) {\n env.stdout.write(chalk.bold(\"Examples:\\n\"));\n for (const example of gadget.examples) {\n if (example.comment) {\n env.stdout.write(chalk.dim(` # ${example.comment}\\n`));\n }\n env.stdout.write(` Input: ${chalk.cyan(JSON.stringify(example.params))}\\n`);\n if (example.output !== undefined) {\n env.stdout.write(` Output: ${chalk.green(example.output)}\\n`);\n }\n env.stdout.write(\"\\n\");\n }\n }\n}\n\n/**\n * Builds a JSON-serializable info object for a gadget.\n */\nfunction buildGadgetInfo(gadget: BaseGadget, name: string): Record<string, unknown> {\n const info: Record<string, unknown> = {\n name,\n description: gadget.description,\n };\n\n if (gadget.parameterSchema) {\n info.schema = schemaToJSONSchema(gadget.parameterSchema, { target: \"draft-7\" });\n }\n\n if (gadget.timeoutMs) {\n info.timeoutMs = gadget.timeoutMs;\n }\n\n if (gadget.examples && gadget.examples.length > 0) {\n info.examples = gadget.examples;\n }\n\n return info;\n}\n\n/**\n * Formats a JSON Schema as readable text with indentation.\n */\nfunction formatSchemaAsText(schema: Record<string, unknown>, indent = \"\"): string {\n const lines: string[] = [];\n const properties = (schema.properties || {}) as Record<string, Record<string, unknown>>;\n const required = (schema.required || []) as string[];\n\n for (const [key, prop] of Object.entries(properties)) {\n const type = prop.type as string;\n const description = prop.description as string | undefined;\n const isRequired = required.includes(key);\n const enumValues = prop.enum as string[] | undefined;\n const defaultValue = prop.default;\n\n // Build the line\n let line = `${indent}${chalk.cyan(key)}`;\n\n // Required marker\n if (isRequired) {\n line += chalk.red(\"*\");\n }\n\n // Type info\n if (type === \"array\") {\n const items = prop.items as Record<string, unknown> | undefined;\n const itemType = items?.type || \"any\";\n line += chalk.dim(` (${itemType}[])`);\n } else if (type === \"object\" && prop.properties) {\n line += chalk.dim(\" (object)\");\n } else {\n line += chalk.dim(` (${type})`);\n }\n\n // Default value\n if (defaultValue !== undefined) {\n line += chalk.dim(` [default: ${JSON.stringify(defaultValue)}]`);\n }\n\n // Description\n if (description) {\n line += `: ${description}`;\n }\n\n // Enum values\n if (enumValues) {\n line += chalk.yellow(` - one of: ${enumValues.join(\", \")}`);\n }\n\n lines.push(line);\n\n // Recurse for nested objects\n if (type === \"object\" && prop.properties) {\n lines.push(formatSchemaAsText(prop, indent + \" \"));\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Executes the `gadget validate` subcommand.\n * Checks if a file exports valid gadget(s).\n */\nasync function executeGadgetValidate(file: string, env: CLIEnvironment): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const gadgets = await loadGadgets([file], cwd);\n\n if (gadgets.length === 0) {\n throw new Error(\n \"No gadgets exported from file.\\n\" +\n \"A valid gadget must have:\\n\" +\n \" - execute() method\\n\" +\n \" - description property\\n\" +\n \" - parameterSchema (optional)\",\n );\n }\n\n // Validate each gadget's structure and schema\n const issues: string[] = [];\n\n for (const gadget of gadgets) {\n const name = gadget.name ?? gadget.constructor.name;\n\n // Check required fields\n if (!gadget.description) {\n issues.push(`${name}: Missing 'description' property.`);\n }\n\n // Validate schema if present\n if (gadget.parameterSchema) {\n try {\n validateGadgetSchema(gadget.parameterSchema, name);\n } catch (schemaError) {\n const message = schemaError instanceof Error ? schemaError.message : String(schemaError);\n issues.push(`${name}: ${message}`);\n }\n }\n\n // Check execute method\n if (typeof gadget.execute !== \"function\") {\n issues.push(`${name}: Missing 'execute()' method.`);\n }\n }\n\n if (issues.length > 0) {\n throw new Error(`Validation issues:\\n${issues.map((i) => ` - ${i}`).join(\"\\n\")}`);\n }\n\n // Success output\n env.stdout.write(chalk.green.bold(\"\\n✓ Valid\\n\\n\"));\n env.stdout.write(chalk.bold(\"Gadgets found:\\n\"));\n\n for (const gadget of gadgets) {\n const name = gadget.name ?? gadget.constructor.name;\n const schemaInfo = gadget.parameterSchema\n ? chalk.cyan(\"(with schema)\")\n : chalk.dim(\"(no schema)\");\n env.stdout.write(` ${chalk.bold(name)} ${schemaInfo}\\n`);\n env.stdout.write(chalk.dim(` ${gadget.description}\\n`));\n }\n\n env.stdout.write(\"\\n\");\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n env.stdout.write(chalk.red.bold(`\\n✗ Invalid\\n\\n`));\n env.stdout.write(`${message}\\n\\n`);\n env.setExitCode(1);\n }\n}\n\n/**\n * Registers the `gadget` command group with run/info/validate subcommands.\n *\n * @param program - Commander program to register on\n * @param env - CLI environment for I/O\n */\nexport function registerGadgetCommand(program: Command, env: CLIEnvironment): void {\n const gadgetCmd = program\n .command(\"gadget\")\n .description(\"Test and inspect gadgets outside the agent loop.\");\n\n // Subcommand: run\n gadgetCmd\n .command(\"run <file>\")\n .description(\"Execute a gadget with interactive prompts or stdin JSON.\")\n .option(\"--name <gadget>\", \"Select gadget by name (required if file exports multiple)\")\n .option(\"--json\", \"Format output as pretty-printed JSON\")\n .option(\"--raw\", \"Output result as raw string without formatting\")\n .action((file: string, options: GadgetRunOptions) =>\n executeAction(() => executeGadgetRun(file, options, env), env),\n );\n\n // Subcommand: info\n gadgetCmd\n .command(\"info <file>\")\n .description(\"Display gadget description, schema, and examples.\")\n .option(\"--name <gadget>\", \"Select gadget by name (required if file exports multiple)\")\n .option(\"--json\", \"Output as JSON instead of formatted text\")\n .action((file: string, options: GadgetInfoOptions) =>\n executeAction(() => executeGadgetInfo(file, options, env), env),\n );\n\n // Subcommand: validate\n gadgetCmd\n .command(\"validate <file>\")\n .description(\"Check if file exports valid gadget(s).\")\n .action((file: string) =>\n executeAction(() => executeGadgetValidate(file, env), env),\n );\n}\n","/**\n * Interactive prompts for schema-driven gadget parameter input.\n * Converts Zod schemas to JSON Schema for introspection and prompts\n * users for each parameter with type hints, descriptions, and defaults.\n *\n * @module cli/gadget-prompts\n */\n\nimport { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport type { ZodTypeAny } from \"zod\";\n\nimport { schemaToJSONSchema } from \"../gadgets/schema-to-json.js\";\n\n/**\n * Context for interactive prompting.\n */\nexport interface PromptContext {\n stdin: NodeJS.ReadableStream;\n stdout: NodeJS.WritableStream;\n}\n\n/**\n * JSON Schema property representation for a single field.\n */\ninterface JsonSchemaProperty {\n type?: string;\n description?: string;\n enum?: string[];\n default?: unknown;\n items?: { type?: string; enum?: string[] };\n properties?: Record<string, JsonSchemaProperty>;\n required?: string[];\n}\n\n/**\n * Prompts user for parameter values based on Zod schema.\n * Displays type hints, descriptions, and defaults for each field.\n * Returns validated and transformed parameters.\n *\n * @param schema - Zod schema describing expected parameters\n * @param ctx - I/O context for prompts\n * @returns Object containing user-provided parameter values\n */\nexport async function promptForParameters(\n schema: ZodTypeAny | undefined,\n ctx: PromptContext,\n): Promise<Record<string, unknown>> {\n if (!schema) {\n return {}; // No parameters required\n }\n\n const jsonSchema = schemaToJSONSchema(schema, { target: \"draft-7\" }) as {\n properties?: Record<string, JsonSchemaProperty>;\n required?: string[];\n };\n\n if (!jsonSchema.properties || Object.keys(jsonSchema.properties).length === 0) {\n return {};\n }\n\n const rl = createInterface({ input: ctx.stdin, output: ctx.stdout });\n const params: Record<string, unknown> = {};\n\n try {\n for (const [key, prop] of Object.entries(jsonSchema.properties)) {\n const value = await promptForField(rl, key, prop, jsonSchema.required ?? []);\n if (value !== undefined) {\n params[key] = value;\n }\n }\n } finally {\n rl.close();\n }\n\n // Validate and apply defaults/transforms through Zod\n const result = schema.safeParse(params);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid parameters:\\n${issues}`);\n }\n\n return result.data as Record<string, unknown>;\n}\n\n/**\n * Prompts for a single field value with type-aware formatting.\n */\nasync function promptForField(\n rl: ReturnType<typeof createInterface>,\n key: string,\n prop: JsonSchemaProperty,\n required: string[],\n): Promise<unknown> {\n const isRequired = required.includes(key);\n const typeHint = formatTypeHint(prop);\n const defaultHint =\n prop.default !== undefined ? chalk.dim(` [default: ${JSON.stringify(prop.default)}]`) : \"\";\n const requiredMarker = isRequired ? chalk.red(\"*\") : \"\";\n\n // Build prompt with description\n let prompt = `\\n${chalk.cyan.bold(key)}${requiredMarker}`;\n if (prop.description) {\n prompt += chalk.dim(` - ${prop.description}`);\n }\n prompt += `\\n ${typeHint}${defaultHint}\\n ${chalk.green(\">\")} `;\n\n const answer = await rl.question(prompt);\n const trimmed = answer.trim();\n\n // Handle empty input\n if (!trimmed) {\n if (prop.default !== undefined) {\n return undefined; // Let Zod apply default\n }\n if (!isRequired) {\n return undefined; // Optional field, skip\n }\n throw new Error(`Parameter '${key}' is required.`);\n }\n\n // Parse based on type\n return parseValue(trimmed, prop, key);\n}\n\n/**\n * Formats the type hint for display (e.g., \"(number)\", \"(add | subtract)\").\n */\nfunction formatTypeHint(prop: JsonSchemaProperty): string {\n // Enum types: show allowed values\n if (prop.enum) {\n return chalk.yellow(`(${prop.enum.join(\" | \")})`);\n }\n\n // Array types: show item type\n if (prop.type === \"array\") {\n const items = prop.items;\n if (items?.enum) {\n return chalk.yellow(`(${items.enum.join(\" | \")})[] comma-separated`);\n }\n const itemType = items?.type ?? \"any\";\n return chalk.yellow(`(${itemType}[]) comma-separated`);\n }\n\n // Object types: indicate nested structure\n if (prop.type === \"object\" && prop.properties) {\n return chalk.yellow(\"(object) enter as JSON\");\n }\n\n // Simple types\n return chalk.yellow(`(${prop.type ?? \"any\"})`);\n}\n\n/**\n * Parses a string value into the appropriate type based on schema.\n */\nfunction parseValue(input: string, prop: JsonSchemaProperty, key: string): unknown {\n const type = prop.type;\n\n // Numbers\n if (type === \"number\" || type === \"integer\") {\n const num = Number(input);\n if (Number.isNaN(num)) {\n throw new Error(`Invalid number for '${key}': ${input}`);\n }\n if (type === \"integer\" && !Number.isInteger(num)) {\n throw new Error(`Expected integer for '${key}', got: ${input}`);\n }\n return num;\n }\n\n // Booleans\n if (type === \"boolean\") {\n const lower = input.toLowerCase();\n if ([\"true\", \"yes\", \"1\", \"y\"].includes(lower)) return true;\n if ([\"false\", \"no\", \"0\", \"n\"].includes(lower)) return false;\n throw new Error(`Invalid boolean for '${key}': ${input} (use true/false, yes/no, 1/0)`);\n }\n\n // Arrays (comma-separated)\n if (type === \"array\") {\n const items = input.split(\",\").map((s) => s.trim()).filter(Boolean);\n const itemType = prop.items?.type;\n\n // Convert array items to appropriate type\n if (itemType === \"number\" || itemType === \"integer\") {\n return items.map((item) => {\n const num = Number(item);\n if (Number.isNaN(num)) throw new Error(`Invalid number in '${key}' array: ${item}`);\n return num;\n });\n }\n if (itemType === \"boolean\") {\n return items.map((item) => {\n const lower = item.toLowerCase();\n if ([\"true\", \"yes\", \"1\", \"y\"].includes(lower)) return true;\n if ([\"false\", \"no\", \"0\", \"n\"].includes(lower)) return false;\n throw new Error(`Invalid boolean in '${key}' array: ${item}`);\n });\n }\n return items; // String array\n }\n\n // Objects (parse as JSON)\n if (type === \"object\") {\n try {\n return JSON.parse(input);\n } catch {\n throw new Error(`Invalid JSON for '${key}': ${input}`);\n }\n }\n\n // String (default) - also handles enums which are validated by Zod\n return input;\n}\n\n/**\n * Reads JSON parameters from stdin (for non-TTY piped input).\n *\n * @param stdin - Readable stream to read from\n * @returns Parsed JSON object\n */\nexport async function readStdinJson(stdin: NodeJS.ReadableStream): Promise<Record<string, unknown>> {\n const chunks: string[] = [];\n\n for await (const chunk of stdin) {\n if (typeof chunk === \"string\") {\n chunks.push(chunk);\n } else {\n chunks.push(chunk.toString(\"utf8\"));\n }\n }\n\n const content = chunks.join(\"\").trim();\n\n if (!content) {\n return {}; // Empty stdin, use defaults\n }\n\n try {\n const parsed = JSON.parse(content);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(\"Stdin must contain a JSON object, not an array or primitive.\");\n }\n return parsed as Record<string, unknown>;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid JSON from stdin: ${error.message}`);\n }\n throw error;\n }\n}\n","import { type Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { executeAction } from \"./utils.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport { MODEL_ALIASES } from \"../core/model-shortcuts.js\";\n\ninterface ModelsCommandOptions {\n provider?: string;\n format?: \"table\" | \"json\";\n verbose?: boolean;\n}\n\nasync function handleModelsCommand(\n options: ModelsCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const client = env.createClient();\n\n // Get models, optionally filtered by provider\n const models = client.modelRegistry.listModels(options.provider);\n\n if (options.format === \"json\") {\n renderJSON(models, env.stdout);\n } else {\n renderTable(models, options.verbose || false, env.stdout);\n }\n}\n\nfunction renderTable(models: ModelSpec[], verbose: boolean, stream: NodeJS.WritableStream): void {\n // Group models by provider\n const grouped = new Map<string, ModelSpec[]>();\n for (const model of models) {\n const provider = model.provider;\n if (!grouped.has(provider)) {\n grouped.set(provider, []);\n }\n grouped.get(provider)!.push(model);\n }\n\n // Header\n stream.write(chalk.bold.cyan(\"\\nAvailable Models\\n\"));\n stream.write(chalk.cyan(\"=\".repeat(80)) + \"\\n\\n\");\n\n // Display each provider's models\n const providers = Array.from(grouped.keys()).sort();\n for (const provider of providers) {\n const providerModels = grouped.get(provider)!;\n const providerName = provider.charAt(0).toUpperCase() + provider.slice(1);\n\n stream.write(chalk.bold.yellow(`${providerName} Models\\n`));\n\n if (verbose) {\n renderVerboseTable(providerModels, stream);\n } else {\n renderCompactTable(providerModels, stream);\n }\n\n stream.write(\"\\n\");\n }\n\n // Display shortcuts\n stream.write(chalk.bold.magenta(\"Model Shortcuts\\n\"));\n stream.write(chalk.dim(\"─\".repeat(80)) + \"\\n\");\n\n const shortcuts = Object.entries(MODEL_ALIASES).sort((a, b) => a[0].localeCompare(b[0]));\n for (const [shortcut, fullName] of shortcuts) {\n stream.write(chalk.cyan(` ${shortcut.padEnd(15)}`) + chalk.dim(\" → \") + chalk.white(fullName) + \"\\n\");\n }\n stream.write(\"\\n\");\n}\n\nfunction renderCompactTable(models: ModelSpec[], stream: NodeJS.WritableStream): void {\n // Column widths\n const idWidth = 25;\n const nameWidth = 22;\n const contextWidth = 13;\n const inputWidth = 10;\n const outputWidth = 10;\n\n // Header\n stream.write(chalk.dim(\"─\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\n\");\n stream.write(\n chalk.bold(\n \"Model ID\".padEnd(idWidth) +\n \" \" + \"Display Name\".padEnd(nameWidth) +\n \" \" + \"Context\".padEnd(contextWidth) +\n \" \" + \"Input\".padEnd(inputWidth) +\n \" \" + \"Output\".padEnd(outputWidth)\n ) + \"\\n\"\n );\n stream.write(chalk.dim(\"─\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\n\");\n\n // Rows\n for (const model of models) {\n const contextFormatted = formatTokens(model.contextWindow);\n const inputPrice = `$${model.pricing.input.toFixed(2)}`;\n const outputPrice = `$${model.pricing.output.toFixed(2)}`;\n\n stream.write(\n chalk.green(model.modelId.padEnd(idWidth)) +\n \" \" + chalk.white(model.displayName.padEnd(nameWidth)) +\n \" \" + chalk.yellow(contextFormatted.padEnd(contextWidth)) +\n \" \" + chalk.cyan(inputPrice.padEnd(inputWidth)) +\n \" \" + chalk.cyan(outputPrice.padEnd(outputWidth)) +\n \"\\n\"\n );\n }\n\n stream.write(chalk.dim(\"─\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\n\");\n stream.write(chalk.dim(` * Prices are per 1M tokens\\n`));\n}\n\nfunction renderVerboseTable(models: ModelSpec[], stream: NodeJS.WritableStream): void {\n for (const model of models) {\n stream.write(chalk.bold.green(`\\n ${model.modelId}\\n`));\n stream.write(chalk.dim(\" \" + \"─\".repeat(60)) + \"\\n\");\n stream.write(` ${chalk.dim(\"Name:\")} ${chalk.white(model.displayName)}\\n`);\n stream.write(` ${chalk.dim(\"Context:\")} ${chalk.yellow(formatTokens(model.contextWindow))}\\n`);\n stream.write(` ${chalk.dim(\"Max Output:\")} ${chalk.yellow(formatTokens(model.maxOutputTokens))}\\n`);\n stream.write(` ${chalk.dim(\"Pricing:\")} ${chalk.cyan(`$${model.pricing.input.toFixed(2)} input`)} ${chalk.dim(\"/\")} ${chalk.cyan(`$${model.pricing.output.toFixed(2)} output`)} ${chalk.dim(\"(per 1M tokens)\")}\\n`);\n\n if (model.pricing.cachedInput !== undefined) {\n stream.write(` ${chalk.dim(\"Cached Input:\")} ${chalk.cyan(`$${model.pricing.cachedInput.toFixed(2)} per 1M tokens`)}\\n`);\n }\n\n if (model.knowledgeCutoff) {\n stream.write(` ${chalk.dim(\"Knowledge:\")} ${model.knowledgeCutoff}\\n`);\n }\n\n // Features\n const features: string[] = [];\n if (model.features.streaming) features.push(\"streaming\");\n if (model.features.functionCalling) features.push(\"function-calling\");\n if (model.features.vision) features.push(\"vision\");\n if (model.features.reasoning) features.push(\"reasoning\");\n if (model.features.structuredOutputs) features.push(\"structured-outputs\");\n if (model.features.fineTuning) features.push(\"fine-tuning\");\n\n if (features.length > 0) {\n stream.write(` ${chalk.dim(\"Features:\")} ${chalk.blue(features.join(\", \"))}\\n`);\n }\n\n // Metadata\n if (model.metadata) {\n if (model.metadata.family) {\n stream.write(` ${chalk.dim(\"Family:\")} ${model.metadata.family}\\n`);\n }\n if (model.metadata.releaseDate) {\n stream.write(` ${chalk.dim(\"Released:\")} ${model.metadata.releaseDate}\\n`);\n }\n if (model.metadata.notes) {\n stream.write(` ${chalk.dim(\"Notes:\")} ${chalk.italic(model.metadata.notes)}\\n`);\n }\n }\n }\n stream.write(\"\\n\");\n}\n\nfunction renderJSON(models: ModelSpec[], stream: NodeJS.WritableStream): void {\n const output = {\n models: models.map(model => ({\n provider: model.provider,\n modelId: model.modelId,\n displayName: model.displayName,\n contextWindow: model.contextWindow,\n maxOutputTokens: model.maxOutputTokens,\n pricing: {\n input: model.pricing.input,\n output: model.pricing.output,\n cachedInput: model.pricing.cachedInput,\n currency: \"USD\",\n per: \"1M tokens\",\n },\n knowledgeCutoff: model.knowledgeCutoff,\n features: model.features,\n metadata: model.metadata,\n })),\n shortcuts: MODEL_ALIASES,\n };\n\n stream.write(JSON.stringify(output, null, 2) + \"\\n\");\n}\n\nfunction formatTokens(count: number): string {\n if (count >= 1_000_000) {\n return `${(count / 1_000_000).toFixed(1)}M tokens`;\n } else if (count >= 1_000) {\n return `${(count / 1_000).toFixed(0)}K tokens`;\n } else {\n return `${count} tokens`;\n }\n}\n\nexport function registerModelsCommand(program: Command, env: CLIEnvironment): void {\n program\n .command(COMMANDS.models)\n .description(\"List all available LLM models with pricing and capabilities.\")\n .option(\"--provider <name>\", \"Filter by provider (openai, anthropic, gemini)\")\n .option(\"--format <format>\", \"Output format: table or json\", \"table\")\n .option(\"--verbose\", \"Show detailed model information\", false)\n .action((options) =>\n executeAction(\n () => handleModelsCommand(options as ModelsCommandOptions, env),\n env,\n ),\n );\n}\n","import readline from \"node:readline\";\nimport chalk from \"chalk\";\nimport type { ILogObj, Logger } from \"tslog\";\nimport { LLMist } from \"../core/client.js\";\nimport type { LoggerOptions } from \"../logging/logger.js\";\nimport { createLogger } from \"../logging/logger.js\";\n\n/**\n * Stream type that may have TTY capabilities.\n */\nexport type TTYStream = NodeJS.ReadableStream & { isTTY?: boolean };\n\n/**\n * Logger configuration for CLI commands.\n */\nexport interface CLILoggerConfig {\n logLevel?: string;\n logFile?: string;\n logReset?: boolean;\n}\n\n/**\n * Environment abstraction for CLI dependencies and I/O.\n * Allows dependency injection for testing.\n */\nexport interface CLIEnvironment {\n argv: string[];\n stdin: TTYStream;\n stdout: NodeJS.WritableStream;\n stderr: NodeJS.WritableStream;\n createClient: () => LLMist;\n setExitCode: (code: number) => void;\n loggerConfig?: CLILoggerConfig;\n createLogger: (name: string) => Logger<ILogObj>;\n /** Whether stdin is a TTY (interactive terminal) */\n isTTY: boolean;\n /** Prompt the user for input (only works when isTTY is true) */\n prompt: (question: string) => Promise<string>;\n}\n\nconst LOG_LEVEL_MAP: Record<string, number> = {\n silly: 0,\n trace: 1,\n debug: 2,\n info: 3,\n warn: 4,\n error: 5,\n fatal: 6,\n};\n\n/**\n * Creates a logger factory based on CLI configuration.\n * Priority: CLI options > environment variables > defaults\n */\nfunction createLoggerFactory(config?: CLILoggerConfig): (name: string) => Logger<ILogObj> {\n return (name: string) => {\n const options: LoggerOptions = { name };\n\n // CLI --log-level takes priority over LLMIST_LOG_LEVEL env var\n if (config?.logLevel) {\n const level = config.logLevel.toLowerCase();\n if (level in LOG_LEVEL_MAP) {\n options.minLevel = LOG_LEVEL_MAP[level];\n }\n }\n\n // CLI --log-reset takes priority over LLMIST_LOG_RESET env var\n if (config?.logReset !== undefined) {\n options.logReset = config.logReset;\n }\n\n // CLI --log-file takes priority over LLMIST_LOG_FILE env var\n // When log file is set via CLI, we temporarily set the env var\n // so createLogger picks it up\n if (config?.logFile) {\n const originalLogFile = process.env.LLMIST_LOG_FILE;\n process.env.LLMIST_LOG_FILE = config.logFile;\n const logger = createLogger(options);\n // Restore original (or delete if it wasn't set)\n if (originalLogFile === undefined) {\n delete process.env.LLMIST_LOG_FILE;\n } else {\n process.env.LLMIST_LOG_FILE = originalLogFile;\n }\n return logger;\n }\n\n // If no log file, default to pretty output (not hidden)\n if (!process.env.LLMIST_LOG_FILE) {\n options.type = \"pretty\";\n }\n\n return createLogger(options);\n };\n}\n\n/**\n * Creates a readline-based prompt function for user input.\n */\nfunction createPromptFunction(\n stdin: NodeJS.ReadableStream,\n stdout: NodeJS.WritableStream,\n): (question: string) => Promise<string> {\n return (question: string) => {\n return new Promise((resolve) => {\n const rl = readline.createInterface({\n input: stdin,\n output: stdout,\n });\n // Display question with visual styling\n stdout.write(\"\\n\");\n stdout.write(`${chalk.cyan(\"─\".repeat(60))}\\n`);\n stdout.write(chalk.cyan.bold(\"🤖 Agent asks:\\n\"));\n stdout.write(`${question}\\n`);\n stdout.write(`${chalk.cyan(\"─\".repeat(60))}\\n`);\n rl.question(chalk.green.bold(\"You: \"), (answer) => {\n rl.close();\n resolve(answer);\n });\n });\n };\n}\n\n/**\n * Creates the default CLI environment using Node.js process globals.\n * Uses process.argv, process.stdin/stdout/stderr, and creates a new LLMist client.\n *\n * @param loggerConfig - Optional logger configuration from CLI options\n * @returns Default CLI environment\n */\nexport function createDefaultEnvironment(loggerConfig?: CLILoggerConfig): CLIEnvironment {\n const isTTY = Boolean(process.stdin.isTTY);\n\n return {\n argv: process.argv,\n stdin: process.stdin,\n stdout: process.stdout,\n stderr: process.stderr,\n createClient: () => new LLMist(),\n setExitCode: (code: number) => {\n process.exitCode = code;\n },\n loggerConfig,\n createLogger: createLoggerFactory(loggerConfig),\n isTTY,\n prompt: isTTY\n ? createPromptFunction(process.stdin, process.stdout)\n : async () => {\n throw new Error(\"Cannot prompt for input: stdin is not a TTY\");\n },\n };\n}\n","import type { Command } from \"commander\";\nimport { executeAgent } from \"./agent-command.js\";\nimport { executeComplete } from \"./complete-command.js\";\nimport type { CustomCommandConfig } from \"./config.js\";\nimport { createDefaultEnvironment, type CLIEnvironment, type CLILoggerConfig } from \"./environment.js\";\nimport {\n addAgentOptions,\n addCompleteOptions,\n type AgentCommandOptions,\n type CompleteCommandOptions,\n configToAgentOptions,\n configToCompleteOptions,\n} from \"./option-helpers.js\";\nimport { executeAction } from \"./utils.js\";\n\n/**\n * Creates an environment with per-command logging config merged in.\n * If the command has logging options, creates a new environment; otherwise returns the original.\n */\nfunction createCommandEnvironment(\n baseEnv: CLIEnvironment,\n config: CustomCommandConfig,\n): CLIEnvironment {\n // Check if command has any logging overrides\n const hasLoggingConfig =\n config[\"log-level\"] !== undefined ||\n config[\"log-file\"] !== undefined ||\n config[\"log-reset\"] !== undefined;\n\n if (!hasLoggingConfig) {\n return baseEnv;\n }\n\n // Merge per-command logging config with base environment's config\n const loggerConfig: CLILoggerConfig = {\n logLevel: config[\"log-level\"] ?? baseEnv.loggerConfig?.logLevel,\n logFile: config[\"log-file\"] ?? baseEnv.loggerConfig?.logFile,\n logReset: config[\"log-reset\"] ?? baseEnv.loggerConfig?.logReset,\n };\n\n // Create new environment with merged logging config\n return createDefaultEnvironment(loggerConfig);\n}\n\n/**\n * Registers a custom command from config file.\n *\n * Custom commands are defined in ~/.llmist/cli.toml as sections like [code-review].\n * Each section can specify `type = \"agent\"` (default) or `type = \"complete\"` to\n * determine the execution behavior.\n *\n * @param program - Commander program to register the command with\n * @param name - Command name (e.g., \"code-review\")\n * @param config - Command configuration from TOML file\n * @param env - CLI environment for I/O operations\n */\nexport function registerCustomCommand(\n program: Command,\n name: string,\n config: CustomCommandConfig,\n env: CLIEnvironment,\n): void {\n const type = config.type ?? \"agent\";\n const description = config.description ?? `Custom ${type} command`;\n\n const cmd = program\n .command(name)\n .description(description)\n .argument(\"[prompt]\", \"Prompt for the command. Falls back to stdin when available.\");\n\n if (type === \"complete\") {\n // Complete type command\n addCompleteOptions(cmd, config);\n\n cmd.action((prompt, cliOptions) => {\n // Create environment with per-command logging config\n const cmdEnv = createCommandEnvironment(env, config);\n return executeAction(async () => {\n // Config values are base, CLI options override\n const configDefaults = configToCompleteOptions(config);\n const options: CompleteCommandOptions = {\n ...configDefaults,\n ...(cliOptions as Partial<CompleteCommandOptions>),\n } as CompleteCommandOptions;\n await executeComplete(prompt, options, cmdEnv);\n }, cmdEnv);\n });\n } else {\n // Agent type command (default)\n addAgentOptions(cmd, config);\n\n cmd.action((prompt, cliOptions) => {\n // Create environment with per-command logging config\n const cmdEnv = createCommandEnvironment(env, config);\n return executeAction(async () => {\n // Config values are base, CLI options override\n const configDefaults = configToAgentOptions(config);\n const options: AgentCommandOptions = {\n ...configDefaults,\n ...(cliOptions as Partial<AgentCommandOptions>),\n } as AgentCommandOptions;\n await executeAgent(prompt, options, cmdEnv);\n }, cmdEnv);\n });\n }\n}\n","#!/usr/bin/env node\nimport { SUMMARY_PREFIX } from \"./cli/constants.js\";\nimport { runCLI } from \"./cli/program.js\";\n\nrunCLI().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`${SUMMARY_PREFIX} Error: ${message}\\n`);\n process.exitCode = 1;\n});\n"],"mappings":"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","names":["path","path","z","pointer","path","stream","stream","init_constants","Anthropic","init_constants","stream","init_constants","stream","OpenAI","init_constants","stream","providerSpecs","import_commander","import_promises","import_chalk","init_constants","import_zod","import_node_fs","import_node_path","path","fs","exports","import_node_path","import_chalk","init_constants","chalk","stream","chalk","gadgets","stderrTTY","chalk","init_constants","stream","import_node_fs","import_node_os","import_node_path","path","parseToml","import_chalk","import_promises","import_chalk","chalk","chalk","result","import_chalk","stream","chalk","formatTokens","import_chalk","readline","chalk","parseLogLevel"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/constants.ts","../src/core/model-shortcuts.ts","../src/gadgets/schema-validator.ts","../src/gadgets/registry.ts","../src/core/prompt-config.ts","../src/core/messages.ts","../src/logging/logger.ts","../src/gadgets/schema-to-json.ts","../src/gadgets/gadget.ts","../src/gadgets/create-gadget.ts","../src/gadgets/output-viewer.ts","../src/agent/compaction/config.ts","../src/agent/compaction/strategy.ts","../src/agent/compaction/strategies/sliding-window.ts","../src/agent/compaction/strategies/summarization.ts","../src/agent/compaction/strategies/hybrid.ts","../src/agent/compaction/strategies/index.ts","../src/agent/compaction/manager.ts","../src/agent/gadget-output-store.ts","../src/agent/agent-internal-key.ts","../src/agent/conversation-manager.ts","../src/agent/event-handlers.ts","../src/agent/hook-validators.ts","../src/gadgets/schema-introspector.ts","../src/gadgets/block-params.ts","../src/gadgets/error-formatter.ts","../src/gadgets/exceptions.ts","../src/gadgets/parser.ts","../src/gadgets/executor.ts","../src/agent/stream-processor.ts","../src/agent/agent.ts","../src/providers/anthropic-models.ts","../src/providers/base-provider.ts","../src/providers/constants.ts","../src/providers/utils.ts","../src/providers/anthropic.ts","../src/providers/gemini-models.ts","../src/providers/gemini.ts","../src/providers/openai-models.ts","../src/providers/openai.ts","../src/providers/discovery.ts","../src/core/model-registry.ts","../src/core/options.ts","../src/core/quick-methods.ts","../src/core/client.ts","../src/agent/builder.ts","../src/cli/constants.ts","../src/cli/program.ts","../package.json","../src/cli/agent-command.ts","../src/cli/builtin-gadgets.ts","../src/cli/gadgets.ts","../src/cli/llm-logging.ts","../src/cli/utils.ts","../src/cli/ui/formatters.ts","../src/cli/option-helpers.ts","../src/cli/complete-command.ts","../src/cli/config.ts","../src/cli/templates.ts","../src/cli/gadget-command.ts","../src/cli/gadget-prompts.ts","../src/cli/models-command.ts","../src/cli/environment.ts","../src/cli/custom-command.ts","../src/cli.ts"],"sourcesContent":["// Gadget marker constants\nexport const GADGET_START_PREFIX = \"!!!GADGET_START:\";\nexport const GADGET_END_PREFIX = \"!!!GADGET_END\";\nexport const GADGET_ARG_PREFIX = \"!!!ARG:\";\n\n// Default configuration values\nexport const DEFAULT_MAX_TOKENS = 1024;\nexport const DEFAULT_MAX_ITERATIONS = 10;\n\n// Gadget output limiting defaults\n/** Default: gadget output limiting is enabled */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT = true;\n\n/** Default: limit gadget output to 15% of context window */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;\n\n/** Approximate characters per token for limit calculation */\nexport const CHARS_PER_TOKEN = 4;\n\n/** Fallback context window size if model is not in registry */\nexport const FALLBACK_CONTEXT_WINDOW = 128_000;\n","/**\n * Model shortcuts and aliases for more expressive DX.\n *\n * This module provides convenient aliases for common model names,\n * allowing developers to use short, memorable names instead of\n * verbose provider:model-id formats.\n *\n * @example\n * ```typescript\n * // Instead of:\n * model: \"openai:gpt-5-nano\"\n *\n * // You can use:\n * model: \"gpt5-nano\"\n * // or even:\n * model: \"gpt-5-nano\" // Auto-detects provider\n * ```\n */\n\n/**\n * Map of common model aliases to their full provider:model-id format.\n */\nexport const MODEL_ALIASES: Record<string, string> = {\n // OpenAI aliases\n gpt4: \"openai:gpt-4o\",\n gpt4o: \"openai:gpt-4o\",\n gpt5: \"openai:gpt-5\",\n \"gpt5-mini\": \"openai:gpt-5-mini\",\n \"gpt5-nano\": \"openai:gpt-5-nano\",\n\n // Anthropic aliases\n sonnet: \"anthropic:claude-sonnet-4-5\",\n \"claude-sonnet\": \"anthropic:claude-sonnet-4-5\",\n haiku: \"anthropic:claude-haiku-4-5\",\n \"claude-haiku\": \"anthropic:claude-haiku-4-5\",\n opus: \"anthropic:claude-opus-4-5\",\n \"claude-opus\": \"anthropic:claude-opus-4-5\",\n\n // Gemini aliases\n flash: \"gemini:gemini-2.0-flash\",\n \"gemini-flash\": \"gemini:gemini-2.0-flash\",\n \"gemini-pro\": \"gemini:gemini-2.5-pro\",\n pro: \"gemini:gemini-2.5-pro\",\n};\n\n/**\n * Options for resolveModel function.\n */\nexport interface ResolveModelOptions {\n /**\n * If true, throw an error for unknown model names instead of falling back to OpenAI.\n * This helps catch typos like \"gp4\" instead of \"gpt4\".\n * Default: false\n */\n strict?: boolean;\n\n /**\n * If true, suppress warnings for unknown model names.\n * Default: false\n */\n silent?: boolean;\n}\n\n/**\n * Known model name patterns for validation.\n * These patterns help detect typos and unknown models.\n */\nconst KNOWN_MODEL_PATTERNS = [\n /^gpt-?\\d/i, // gpt-4, gpt-3.5, gpt4, etc.\n /^claude-?\\d/i, // claude-3, claude-2, etc.\n /^gemini-?(\\d|pro|flash)/i, // gemini-2.0, gemini-pro, gemini-flash, etc.\n /^o\\d/i, // OpenAI o1, o3, etc.\n];\n\n/**\n * Check if a model name matches known patterns.\n *\n * @param model - Model name to check\n * @returns True if the model matches a known pattern\n */\nfunction isKnownModelPattern(model: string): boolean {\n const normalized = model.toLowerCase();\n\n // Check if it's a known alias\n if (MODEL_ALIASES[normalized]) {\n return true;\n }\n\n // Check against known patterns\n return KNOWN_MODEL_PATTERNS.some((pattern) => pattern.test(model));\n}\n\n/**\n * Resolves a model name to its full provider:model format.\n *\n * Supports:\n * - Direct aliases: 'gpt5', 'sonnet', 'flash'\n * - Auto-detection: 'gpt-5-nano' → 'openai:gpt-5-nano'\n * - Pass-through: 'openai:gpt-5' → 'openai:gpt-5'\n *\n * Warnings:\n * - Logs a warning when an unknown model name falls back to OpenAI\n * - Use { strict: true } to throw an error instead\n * - Use { silent: true } to suppress warnings\n *\n * @param model - Model name or alias\n * @param options - Resolution options\n * @returns Full provider:model-id string\n *\n * @example\n * ```typescript\n * resolveModel('gpt5') // → 'openai:gpt-5'\n * resolveModel('sonnet') // → 'anthropic:claude-sonnet-4-5'\n * resolveModel('gpt-5-nano') // → 'openai:gpt-5-nano'\n * resolveModel('openai:gpt-5') // → 'openai:gpt-5' (passthrough)\n * resolveModel('claude-3-5-sonnet') // → 'anthropic:claude-3-5-sonnet'\n *\n * // Typo detection\n * resolveModel('gp5') // ⚠️ Warning: Unknown model 'gp5', falling back to 'openai:gp5'\n *\n * // Strict mode (throws on typos)\n * resolveModel('gp5', { strict: true }) // ❌ Error: Unknown model 'gp5'\n * ```\n */\nexport function resolveModel(model: string, options: ResolveModelOptions = {}): string {\n // Already has provider prefix - pass through\n if (model.includes(\":\")) {\n return model;\n }\n\n // Check if it's a known alias\n const normalized = model.toLowerCase();\n if (MODEL_ALIASES[normalized]) {\n return MODEL_ALIASES[normalized];\n }\n\n // Smart detection by model name patterns\n const modelLower = model.toLowerCase();\n\n // OpenAI models start with 'gpt'\n if (modelLower.startsWith(\"gpt\")) {\n return `openai:${model}`;\n }\n\n // Anthropic models start with 'claude'\n if (modelLower.startsWith(\"claude\")) {\n return `anthropic:${model}`;\n }\n\n // Gemini models start with 'gemini'\n if (modelLower.startsWith(\"gemini\")) {\n return `gemini:${model}`;\n }\n\n // OpenAI o-series models (o1, o3, etc.)\n if (modelLower.match(/^o\\d/)) {\n return `openai:${model}`;\n }\n\n // Unknown model: validate and warn/error\n if (!isKnownModelPattern(model)) {\n if (options.strict) {\n throw new Error(\n `Unknown model '${model}'. Did you mean one of: gpt4, sonnet, haiku, flash? ` +\n `Use explicit provider prefix like 'openai:${model}' to bypass this check.`,\n );\n }\n\n if (!options.silent) {\n console.warn(\n `⚠️ Unknown model '${model}', falling back to 'openai:${model}'. ` +\n `This might be a typo. Did you mean: gpt4, gpt5, gpt5-nano, sonnet, haiku, flash? ` +\n `Use { strict: true } to error on unknown models, or { silent: true } to suppress this warning.`,\n );\n }\n }\n\n // Default: assume OpenAI for unknown models\n // This provides a reasonable fallback for most cases\n return `openai:${model}`;\n}\n\n/**\n * Check if a model string is already in provider:model format.\n *\n * @param model - Model string to check\n * @returns True if the model has a provider prefix\n *\n * @example\n * ```typescript\n * hasProviderPrefix('openai:gpt-4o') // → true\n * hasProviderPrefix('gpt4') // → false\n * hasProviderPrefix('claude-3-5-sonnet') // → false\n * ```\n */\nexport function hasProviderPrefix(model: string): boolean {\n return model.includes(\":\");\n}\n\n/**\n * Extract the provider from a full model string.\n *\n * @param model - Full model string (provider:model-id)\n * @returns Provider name, or undefined if no prefix\n *\n * @example\n * ```typescript\n * getProvider('openai:gpt-4o') // → 'openai'\n * getProvider('anthropic:claude') // → 'anthropic'\n * getProvider('gpt4') // → undefined\n * ```\n */\nexport function getProvider(model: string): string | undefined {\n const separatorIndex = model.indexOf(\":\");\n if (separatorIndex === -1) {\n return undefined;\n }\n return model.slice(0, separatorIndex);\n}\n\n/**\n * Extract the model ID from a full model string.\n *\n * @param model - Full model string (provider:model-id)\n * @returns Model ID, or the original string if no prefix\n *\n * @example\n * ```typescript\n * getModelId('openai:gpt-4o') // → 'gpt-4o'\n * getModelId('anthropic:claude') // → 'claude'\n * getModelId('gpt4') // → 'gpt4'\n * ```\n */\nexport function getModelId(model: string): string {\n const separatorIndex = model.indexOf(\":\");\n if (separatorIndex === -1) {\n return model;\n }\n return model.slice(separatorIndex + 1);\n}\n","import type { ZodTypeAny } from \"zod\";\nimport * as z from \"zod\";\n\n/**\n * Validates that a Zod schema doesn't contain z.unknown() which produces\n * incomplete JSON schemas without type information.\n *\n * @param schema - The Zod schema to validate\n * @param gadgetName - Name of the gadget (for error messages)\n * @throws Error if z.unknown() is detected with helpful suggestions\n */\nexport function validateGadgetSchema(schema: ZodTypeAny, gadgetName: string): void {\n let jsonSchema;\n try {\n jsonSchema = z.toJSONSchema(schema, { target: \"draft-7\" });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Gadget \"${gadgetName}\" has a schema that cannot be serialized to JSON Schema.\\n` +\n `This usually happens with unsupported patterns like:\\n` +\n `- z.record() - use z.object({}).passthrough() instead\\n` +\n `- Complex transforms or custom refinements\\n` +\n `- Circular references\\n` +\n `\\n` +\n `Original error: ${errorMessage}\\n` +\n `\\n` +\n `Only use schema patterns that Zod v4's native toJSONSchema() supports.`,\n );\n }\n const issues = findUnknownTypes(jsonSchema);\n\n if (issues.length > 0) {\n const fieldList = issues.join(\", \");\n throw new Error(\n `Gadget \"${gadgetName}\" uses z.unknown() which produces incomplete schemas.\\n` +\n `Problematic fields: ${fieldList}\\n` +\n `\\n` +\n `z.unknown() doesn't generate type information in JSON Schema, making it unclear\\n` +\n `to the LLM what data structure to provide.\\n` +\n `\\n` +\n `Suggestions:\\n` +\n `- Use z.object({}).passthrough() for flexible objects\\n` +\n `- Use z.record(z.string()) for key-value objects with string values\\n` +\n `- Define specific structure if possible\\n` +\n `\\n` +\n `Example fixes:\\n` +\n ` // ❌ Bad\\n` +\n ` content: z.unknown()\\n` +\n `\\n` +\n ` // ✅ Good\\n` +\n ` content: z.object({}).passthrough() // for flexible objects\\n` +\n ` content: z.record(z.string()) // for key-value objects\\n` +\n ` content: z.array(z.string()) // for arrays of strings\\n`,\n );\n }\n}\n\n/**\n * Recursively searches a JSON Schema for properties without type information,\n * which indicates z.unknown() usage.\n *\n * @param schema - JSON Schema object to search\n * @param path - Current path in schema (for error reporting)\n * @returns Array of problematic field paths\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction findUnknownTypes(schema: any, path: string[] = []): string[] {\n const issues: string[] = [];\n\n if (!schema || typeof schema !== \"object\") {\n return issues;\n }\n\n // Check if we're in a definitions block\n if (schema.definitions) {\n for (const defSchema of Object.values(schema.definitions)) {\n issues.push(...findUnknownTypes(defSchema, []));\n }\n }\n\n // Check properties of objects\n if (schema.properties) {\n for (const [propName, propSchema] of Object.entries(schema.properties)) {\n const propPath = [...path, propName];\n\n // Check if this property has no type information\n if (hasNoType(propSchema)) {\n issues.push(propPath.join(\".\") || propName);\n }\n\n // Recursively check nested properties\n issues.push(...findUnknownTypes(propSchema, propPath));\n }\n }\n\n // Check array items\n if (schema.items) {\n const itemPath = [...path, \"[]\"];\n if (hasNoType(schema.items)) {\n issues.push(itemPath.join(\".\"));\n }\n issues.push(...findUnknownTypes(schema.items, itemPath));\n }\n\n // Check anyOf/oneOf/allOf unions\n if (schema.anyOf) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema.anyOf.forEach((subSchema: any, index: number) => {\n issues.push(...findUnknownTypes(subSchema, [...path, `anyOf[${index}]`]));\n });\n }\n\n if (schema.oneOf) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema.oneOf.forEach((subSchema: any, index: number) => {\n issues.push(...findUnknownTypes(subSchema, [...path, `oneOf[${index}]`]));\n });\n }\n\n if (schema.allOf) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema.allOf.forEach((subSchema: any, index: number) => {\n issues.push(...findUnknownTypes(subSchema, [...path, `allOf[${index}]`]));\n });\n }\n\n return issues;\n}\n\n/**\n * Checks if a schema property has no type information.\n * This indicates z.unknown() usage.\n *\n * A property has \"no type\" if it:\n * - Is an object\n * - Has no \"type\" field\n * - Has no \"$ref\" (reference to definition)\n * - Has no \"anyOf\", \"oneOf\", or \"allOf\" (union types)\n * - Has only \"description\" or is empty\n *\n * @param prop - Property schema to check\n * @returns true if property has no type information\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction hasNoType(prop: any): boolean {\n if (!prop || typeof prop !== \"object\") {\n return false;\n }\n\n const hasType = prop.type !== undefined;\n const hasRef = prop.$ref !== undefined;\n const hasUnion = prop.anyOf !== undefined || prop.oneOf !== undefined || prop.allOf !== undefined;\n\n // If it has any type information, it's fine\n if (hasType || hasRef || hasUnion) {\n return false;\n }\n\n // Check if it only has description and/or other non-type metadata\n const keys = Object.keys(prop);\n const metadataKeys = [\"description\", \"title\", \"default\", \"examples\"];\n const hasOnlyMetadata = keys.every((key) => metadataKeys.includes(key));\n\n // If it only has metadata or is empty (besides metadata), it's missing type info\n return hasOnlyMetadata || keys.length === 0;\n}\n","import type { BaseGadget } from \"./gadget.js\";\nimport { validateGadgetSchema } from \"./schema-validator.js\";\n\n// Type for gadget constructor\nexport type GadgetClass = new (...args: unknown[]) => BaseGadget;\n\n// Type for gadget or gadget class\nexport type GadgetOrClass = BaseGadget | GadgetClass;\n\nexport class GadgetRegistry {\n private readonly gadgets = new Map<string, BaseGadget>();\n\n /**\n * Creates a registry from an array of gadget classes or instances,\n * or an object mapping names to gadgets.\n *\n * @param gadgets - Array of gadgets/classes or object with custom names\n * @returns New GadgetRegistry with all gadgets registered\n *\n * @example\n * ```typescript\n * // From array of classes\n * const registry = GadgetRegistry.from([Calculator, Weather]);\n *\n * // From array of instances\n * const registry = GadgetRegistry.from([new Calculator(), new Weather()]);\n *\n * // From object with custom names\n * const registry = GadgetRegistry.from({\n * calc: Calculator,\n * weather: new Weather({ apiKey: \"...\" })\n * });\n * ```\n */\n static from(gadgets: GadgetOrClass[] | Record<string, GadgetOrClass>): GadgetRegistry {\n const registry = new GadgetRegistry();\n\n if (Array.isArray(gadgets)) {\n // Array of gadgets or classes\n registry.registerMany(gadgets);\n } else {\n // Object with custom names\n for (const [name, gadget] of Object.entries(gadgets)) {\n const instance = typeof gadget === \"function\" ? new gadget() : gadget;\n registry.register(name, instance);\n }\n }\n\n return registry;\n }\n\n /**\n * Registers multiple gadgets at once from an array.\n *\n * @param gadgets - Array of gadget instances or classes\n * @returns This registry for chaining\n *\n * @example\n * ```typescript\n * registry.registerMany([Calculator, Weather, Email]);\n * registry.registerMany([new Calculator(), new Weather()]);\n * ```\n */\n registerMany(gadgets: GadgetOrClass[]): this {\n for (const gadget of gadgets) {\n const instance = typeof gadget === \"function\" ? new gadget() : gadget;\n this.registerByClass(instance);\n }\n return this;\n }\n\n // Register a gadget by name\n register(name: string, gadget: BaseGadget): void {\n const normalizedName = name.toLowerCase();\n if (this.gadgets.has(normalizedName)) {\n throw new Error(`Gadget '${name}' is already registered`);\n }\n\n // Validate schema if present\n if (gadget.parameterSchema) {\n validateGadgetSchema(gadget.parameterSchema, name);\n }\n\n this.gadgets.set(normalizedName, gadget);\n }\n\n // Register a gadget using its name property or class name\n registerByClass(gadget: BaseGadget): void {\n const name = gadget.name ?? gadget.constructor.name;\n this.register(name, gadget);\n }\n\n // Get gadget by name (case-insensitive)\n get(name: string): BaseGadget | undefined {\n return this.gadgets.get(name.toLowerCase());\n }\n\n // Check if gadget exists (case-insensitive)\n has(name: string): boolean {\n return this.gadgets.has(name.toLowerCase());\n }\n\n // Get all registered gadget names\n getNames(): string[] {\n return Array.from(this.gadgets.keys());\n }\n\n // Get all gadgets for instruction generation\n getAll(): BaseGadget[] {\n return Array.from(this.gadgets.values());\n }\n\n // Unregister gadget (useful for testing, case-insensitive)\n unregister(name: string): boolean {\n return this.gadgets.delete(name.toLowerCase());\n }\n\n // Clear all gadgets (useful for testing)\n clear(): void {\n this.gadgets.clear();\n }\n}\n","/**\n * Context provided to prompt template functions for rendering dynamic content.\n */\nexport interface PromptContext {\n /** Custom gadget start prefix */\n startPrefix: string;\n /** Custom gadget end prefix */\n endPrefix: string;\n /** Custom argument prefix for block format */\n argPrefix: string;\n /** Number of gadgets being registered */\n gadgetCount: number;\n /** Names of all gadgets */\n gadgetNames: string[];\n}\n\n/**\n * Context provided to hint template functions for rendering dynamic hints.\n */\nexport interface HintContext {\n /** Current iteration (1-based for readability) */\n iteration: number;\n /** Maximum iterations allowed */\n maxIterations: number;\n /** Iterations remaining (maxIterations - iteration) */\n remaining: number;\n /** Number of gadget calls in the current response */\n gadgetCallCount?: number;\n}\n\n/**\n * Template that can be either a static string or a function that renders based on context.\n */\nexport type PromptTemplate = string | ((context: PromptContext) => string);\n\n/**\n * Template for hints that can be either a static string or a function that renders based on hint context.\n */\nexport type HintTemplate = string | ((context: HintContext) => string);\n\n/**\n * Configuration for customizing all prompts used internally by llmist.\n *\n * Each field can be either a string (static text) or a function that receives\n * context and returns a string (for dynamic content).\n *\n * @example\n * ```typescript\n * const customConfig: PromptConfig = {\n * mainInstruction: \"USE ONLY THE GADGET MARKERS BELOW:\",\n * criticalUsage: \"Important: Follow the exact format shown.\",\n * rules: (ctx) => [\n * \"Always use the markers to invoke gadgets\",\n * \"Never use function calling\",\n * `You have ${ctx.gadgetCount} gadgets available`\n * ]\n * };\n * ```\n */\nexport interface PromptConfig {\n /**\n * Main instruction block that appears at the start of the gadget system prompt.\n * Default emphasizes using text markers instead of function calling.\n */\n mainInstruction?: PromptTemplate;\n\n /**\n * Critical usage instruction that appears in the usage section.\n * Default emphasizes the exact format requirement.\n */\n criticalUsage?: PromptTemplate;\n\n /**\n * Format description for the block parameter format.\n * Default uses the configured argPrefix dynamically.\n */\n formatDescription?: PromptTemplate;\n\n /**\n * Rules that appear in the rules section.\n * Can be an array of strings or a function that returns an array.\n * Default includes rules about not using function calling.\n */\n rules?: PromptTemplate | string[] | ((context: PromptContext) => string[]);\n\n /**\n * Custom examples to show in the examples section.\n * If provided, replaces the default examples entirely.\n * Should be a function that returns formatted example strings.\n */\n customExamples?: (context: PromptContext) => string;\n\n // ============================================================================\n // HINT TEMPLATES\n // ============================================================================\n\n /**\n * Hint shown when LLM uses only one gadget per response.\n * Encourages parallel gadget usage for efficiency.\n */\n parallelGadgetsHint?: HintTemplate;\n\n /**\n * Template for iteration progress hint.\n * Informs the LLM about remaining iterations to help plan work.\n *\n * When using a string template, supports placeholders:\n * - {iteration}: Current iteration (1-based)\n * - {maxIterations}: Maximum iterations allowed\n * - {remaining}: Iterations remaining\n */\n iterationProgressHint?: HintTemplate;\n}\n\n/**\n * Default hint templates used by llmist.\n */\nexport const DEFAULT_HINTS = {\n parallelGadgetsHint:\n \"Tip: You can call multiple gadgets in a single response for efficiency.\",\n\n iterationProgressHint:\n \"[Iteration {iteration}/{maxIterations}] Plan your actions accordingly.\",\n} as const;\n\n/**\n * Default prompt templates used by llmist.\n */\nexport const DEFAULT_PROMPTS: Required<\n Omit<PromptConfig, \"rules\" | \"customExamples\" | \"parallelGadgetsHint\" | \"iterationProgressHint\"> & {\n rules: (context: PromptContext) => string[];\n customExamples: null;\n }\n> = {\n mainInstruction: [\n \"⚠️ CRITICAL: RESPOND ONLY WITH GADGET INVOCATIONS\",\n \"DO NOT use function calling or tool calling\",\n \"You must output the exact text markers shown below in plain text.\",\n \"EACH MARKER MUST START WITH A NEWLINE.\",\n ].join(\"\\n\"),\n\n criticalUsage: \"INVOKE gadgets using the markers - do not describe what you want to do.\",\n\n formatDescription: (ctx) =>\n `Parameters using ${ctx.argPrefix}name markers (value on next line(s), no escaping needed)`,\n\n rules: () => [\n \"Output ONLY plain text with the exact markers - never use function/tool calling\",\n \"You can invoke multiple gadgets in a single response\",\n \"For dependent gadgets, invoke the first one and wait for the result\",\n ],\n\n customExamples: null,\n};\n\n/**\n * Resolve a prompt template to a string using the given context.\n */\nexport function resolvePromptTemplate(\n template: PromptTemplate | undefined,\n defaultValue: PromptTemplate,\n context: PromptContext,\n): string {\n const resolved = template ?? defaultValue;\n return typeof resolved === \"function\" ? resolved(context) : resolved;\n}\n\n/**\n * Resolve rules template to an array of strings.\n */\nexport function resolveRulesTemplate(\n rules: PromptConfig[\"rules\"] | undefined,\n context: PromptContext,\n): string[] {\n const resolved = rules ?? DEFAULT_PROMPTS.rules;\n\n if (Array.isArray(resolved)) {\n return resolved;\n }\n\n if (typeof resolved === \"function\") {\n const result = resolved(context);\n return Array.isArray(result) ? result : [result];\n }\n\n return [resolved];\n}\n\n/**\n * Resolve a hint template to a string using the given context.\n * Supports both function templates and string templates with placeholders.\n *\n * @param template - The hint template to resolve\n * @param defaultValue - Default value if template is undefined\n * @param context - Context for rendering the template\n * @returns The resolved hint string\n */\nexport function resolveHintTemplate(\n template: HintTemplate | undefined,\n defaultValue: string,\n context: HintContext,\n): string {\n const resolved = template ?? defaultValue;\n\n if (typeof resolved === \"function\") {\n return resolved(context);\n }\n\n // Replace placeholders in string template\n return resolved\n .replace(/\\{iteration\\}/g, String(context.iteration))\n .replace(/\\{maxIterations\\}/g, String(context.maxIterations))\n .replace(/\\{remaining\\}/g, String(context.remaining));\n}\n","import type { BaseGadget } from \"../gadgets/gadget.js\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"./constants.js\";\nimport type { PromptConfig } from \"./prompt-config.js\";\nimport { DEFAULT_PROMPTS, resolvePromptTemplate, resolveRulesTemplate } from \"./prompt-config.js\";\n\nexport type LLMRole = \"system\" | \"user\" | \"assistant\";\n\nexport interface LLMMessage {\n role: LLMRole;\n content: string;\n name?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport class LLMMessageBuilder {\n private readonly messages: LLMMessage[] = [];\n private startPrefix: string = GADGET_START_PREFIX;\n private endPrefix: string = GADGET_END_PREFIX;\n private argPrefix: string = GADGET_ARG_PREFIX;\n private promptConfig: PromptConfig;\n\n constructor(promptConfig?: PromptConfig) {\n this.promptConfig = promptConfig ?? {};\n }\n\n /**\n * Set custom prefixes for gadget markers.\n * Used to configure history builder to match system prompt markers.\n */\n withPrefixes(startPrefix: string, endPrefix: string, argPrefix?: string): this {\n this.startPrefix = startPrefix;\n this.endPrefix = endPrefix;\n if (argPrefix) {\n this.argPrefix = argPrefix;\n }\n return this;\n }\n\n addSystem(content: string, metadata?: Record<string, unknown>): this {\n this.messages.push({ role: \"system\", content, metadata });\n return this;\n }\n\n addGadgets(\n gadgets: BaseGadget[],\n options?: { startPrefix?: string; endPrefix?: string; argPrefix?: string },\n ): this {\n // Store custom prefixes for later use in addGadgetCall\n if (options?.startPrefix) {\n this.startPrefix = options.startPrefix;\n }\n if (options?.endPrefix) {\n this.endPrefix = options.endPrefix;\n }\n if (options?.argPrefix) {\n this.argPrefix = options.argPrefix;\n }\n\n const context = {\n startPrefix: this.startPrefix,\n endPrefix: this.endPrefix,\n argPrefix: this.argPrefix,\n gadgetCount: gadgets.length,\n gadgetNames: gadgets.map((g) => g.name ?? g.constructor.name),\n };\n\n const parts: string[] = [];\n\n // Use configurable main instruction\n const mainInstruction = resolvePromptTemplate(\n this.promptConfig.mainInstruction,\n DEFAULT_PROMPTS.mainInstruction,\n context,\n );\n parts.push(mainInstruction);\n\n parts.push(this.buildGadgetsSection(gadgets));\n parts.push(this.buildUsageSection(context));\n\n this.messages.push({ role: \"system\", content: parts.join(\"\") });\n return this;\n }\n\n private buildGadgetsSection(gadgets: BaseGadget[]): string {\n const parts: string[] = [];\n parts.push(\"\\n\\nAVAILABLE GADGETS\");\n parts.push(\"\\n=================\\n\");\n\n for (const gadget of gadgets) {\n const gadgetName = gadget.name ?? gadget.constructor.name;\n const instruction = gadget.getInstruction(this.argPrefix);\n\n // Parse instruction to separate description and schema\n const schemaMarker = \"\\n\\nInput Schema (BLOCK):\";\n const schemaIndex = instruction.indexOf(schemaMarker);\n\n const description = (\n schemaIndex !== -1 ? instruction.substring(0, schemaIndex) : instruction\n ).trim();\n const schema =\n schemaIndex !== -1 ? instruction.substring(schemaIndex + schemaMarker.length).trim() : \"\";\n\n parts.push(`\\nGADGET: ${gadgetName}`);\n parts.push(`\\n${description}`);\n if (schema) {\n parts.push(`\\n\\nPARAMETERS (BLOCK):\\n${schema}`);\n }\n parts.push(\"\\n\\n---\");\n }\n\n return parts.join(\"\");\n }\n\n private buildUsageSection(context: {\n startPrefix: string;\n endPrefix: string;\n argPrefix: string;\n gadgetCount: number;\n gadgetNames: string[];\n }): string {\n const parts: string[] = [];\n\n // Use configurable format description\n const formatDescription = resolvePromptTemplate(\n this.promptConfig.formatDescription,\n DEFAULT_PROMPTS.formatDescription,\n context,\n );\n\n parts.push(\"\\n\\nHOW TO INVOKE GADGETS\");\n parts.push(\"\\n=====================\\n\");\n\n // Use configurable critical usage instruction\n const criticalUsage = resolvePromptTemplate(\n this.promptConfig.criticalUsage,\n DEFAULT_PROMPTS.criticalUsage,\n context,\n );\n parts.push(`\\nCRITICAL: ${criticalUsage}\\n`);\n\n // Format section\n parts.push(\"\\nFORMAT:\");\n parts.push(`\\n 1. Start marker: ${this.startPrefix}gadget_name`);\n parts.push(`\\n 2. ${formatDescription}`);\n parts.push(`\\n 3. End marker: ${this.endPrefix}`);\n\n parts.push(this.buildExamplesSection(context));\n parts.push(this.buildRulesSection(context));\n\n parts.push(\"\\n\");\n\n return parts.join(\"\");\n }\n\n private buildExamplesSection(context: {\n startPrefix: string;\n endPrefix: string;\n argPrefix: string;\n gadgetCount: number;\n gadgetNames: string[];\n }): string {\n // Allow custom examples to completely replace default examples\n if (this.promptConfig.customExamples) {\n return this.promptConfig.customExamples(context);\n }\n\n const parts: string[] = [];\n\n // Single gadget example\n const singleExample = `${this.startPrefix}translate\n${this.argPrefix}from\nEnglish\n${this.argPrefix}to\nPolish\n${this.argPrefix}content\nParis is the capital of France: a beautiful city.\n${this.endPrefix}`;\n\n parts.push(`\\n\\nEXAMPLE (Single Gadget):\\n\\n${singleExample}`);\n\n // Multiple gadget example with multiline content\n const multipleExample = `${this.startPrefix}translate\n${this.argPrefix}from\nEnglish\n${this.argPrefix}to\nPolish\n${this.argPrefix}content\nParis is the capital of France: a beautiful city.\n${this.endPrefix}\n${this.startPrefix}analyze\n${this.argPrefix}type\neconomic_analysis\n${this.argPrefix}matter\nPolish Economy\n${this.argPrefix}question\nAnalyze the following:\n- Polish arms exports 2025\n- Economic implications\n${this.endPrefix}`;\n\n parts.push(`\\n\\nEXAMPLE (Multiple Gadgets):\\n\\n${multipleExample}`);\n\n // Block format syntax guide\n parts.push(`\n\nBLOCK FORMAT SYNTAX:\nBlock format uses ${this.argPrefix}name markers. Values are captured verbatim until the next marker.\n\n${this.argPrefix}filename\ncalculator.ts\n${this.argPrefix}code\nclass Calculator {\n private history: string[] = [];\n\n add(a: number, b: number): number {\n const result = a + b;\n this.history.push(\\`\\${a} + \\${b} = \\${result}\\`);\n return result;\n }\n}\n\nBLOCK FORMAT RULES:\n- Each parameter starts with ${this.argPrefix}parameterName on its own line\n- The value starts on the NEXT line after the marker\n- Value ends when the next ${this.argPrefix} or ${this.endPrefix} appears\n- NO escaping needed - write values exactly as they should appear\n- Perfect for code, JSON, markdown, or any content with special characters\n\nNESTED OBJECTS (use / separator):\n${this.argPrefix}config/timeout\n30\n${this.argPrefix}config/retries\n3\nProduces: { \"config\": { \"timeout\": \"30\", \"retries\": \"3\" } }\n\nARRAYS (use numeric indices):\n${this.argPrefix}items/0\nfirst\n${this.argPrefix}items/1\nsecond\nProduces: { \"items\": [\"first\", \"second\"] }`);\n\n return parts.join(\"\");\n }\n\n private buildRulesSection(context: {\n startPrefix: string;\n endPrefix: string;\n argPrefix: string;\n gadgetCount: number;\n gadgetNames: string[];\n }): string {\n const parts: string[] = [];\n parts.push(\"\\n\\nRULES:\");\n\n // Use configurable rules\n const rules = resolveRulesTemplate(this.promptConfig.rules, context);\n\n for (const rule of rules) {\n parts.push(`\\n - ${rule}`);\n }\n\n return parts.join(\"\");\n }\n\n addUser(content: string, metadata?: Record<string, unknown>): this {\n this.messages.push({ role: \"user\", content, metadata });\n return this;\n }\n\n addAssistant(content: string, metadata?: Record<string, unknown>): this {\n this.messages.push({ role: \"assistant\", content, metadata });\n return this;\n }\n\n addGadgetCall(gadget: string, parameters: Record<string, unknown>, result: string) {\n const paramStr = this.formatBlockParameters(parameters, \"\");\n\n // Assistant message with simplified gadget markers (no invocation ID)\n this.messages.push({\n role: \"assistant\",\n content: `${this.startPrefix}${gadget}\\n${paramStr}\\n${this.endPrefix}`,\n });\n\n // User message with result\n this.messages.push({\n role: \"user\",\n content: `Result: ${result}`,\n });\n\n return this;\n }\n\n /**\n * Format parameters as Block format with JSON Pointer paths.\n * Uses the configured argPrefix for consistency with system prompt.\n */\n private formatBlockParameters(\n params: Record<string, unknown>,\n prefix: string,\n ): string {\n const lines: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n const fullPath = prefix ? `${prefix}/${key}` : key;\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n const itemPath = `${fullPath}/${index}`;\n if (typeof item === \"object\" && item !== null) {\n lines.push(this.formatBlockParameters(item as Record<string, unknown>, itemPath));\n } else {\n lines.push(`${this.argPrefix}${itemPath}`);\n lines.push(String(item));\n }\n });\n } else if (typeof value === \"object\" && value !== null) {\n lines.push(this.formatBlockParameters(value as Record<string, unknown>, fullPath));\n } else {\n lines.push(`${this.argPrefix}${fullPath}`);\n lines.push(String(value));\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n build(): LLMMessage[] {\n return [...this.messages];\n }\n}\n\nexport const isLLMMessage = (value: unknown): value is LLMMessage => {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const message = value as Partial<LLMMessage>;\n return (\n (message.role === \"system\" || message.role === \"user\" || message.role === \"assistant\") &&\n typeof message.content === \"string\"\n );\n};\n","import { createWriteStream, mkdirSync, type WriteStream } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { type ILogObj, Logger } from \"tslog\";\n\nconst LEVEL_NAME_TO_ID: 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\nfunction parseLogLevel(value?: string): number | undefined {\n if (!value) {\n return undefined;\n }\n\n const normalized = value.trim().toLowerCase();\n\n if (normalized === \"\") {\n return undefined;\n }\n\n const numericLevel = Number(normalized);\n if (Number.isFinite(numericLevel)) {\n return Math.max(0, Math.min(6, Math.floor(numericLevel)));\n }\n\n return LEVEL_NAME_TO_ID[normalized];\n}\n\n/**\n * Logger configuration options for the library.\n */\nexport interface LoggerOptions {\n /**\n * Log level: 0=silly, 1=trace, 2=debug, 3=info, 4=warn, 5=error, 6=fatal\n * @default 4 (warn)\n */\n minLevel?: number;\n\n /**\n * Output type: 'pretty' for development, 'json' for production\n * @default 'pretty'\n */\n type?: \"pretty\" | \"json\" | \"hidden\";\n\n /**\n * Logger name (appears in logs)\n */\n name?: string;\n\n /**\n * When true, reset (truncate) the log file instead of appending.\n * Useful for getting clean logs per session.\n * @default false\n */\n logReset?: boolean;\n}\n\n/**\n * Parses a boolean environment variable.\n */\nfunction parseEnvBoolean(value?: string): boolean | undefined {\n if (!value) return undefined;\n const normalized = value.trim().toLowerCase();\n if (normalized === \"true\" || normalized === \"1\") return true;\n if (normalized === \"false\" || normalized === \"0\") return false;\n return undefined;\n}\n\n/**\n * Create a new logger instance for the library.\n *\n * @param options - Logger configuration options\n * @returns Configured Logger instance\n *\n * @example\n * ```typescript\n * // Development logger with pretty output\n * const logger = createLogger({ type: 'pretty', minLevel: 2 });\n *\n * // Production logger with JSON output\n * const logger = createLogger({ type: 'json', minLevel: 3 });\n *\n * // Silent logger for tests\n * const logger = createLogger({ type: 'hidden' });\n * ```\n */\nexport function createLogger(options: LoggerOptions = {}): Logger<ILogObj> {\n const envMinLevel = parseLogLevel(process.env.LLMIST_LOG_LEVEL);\n const envLogFile = process.env.LLMIST_LOG_FILE?.trim() ?? \"\";\n const envLogReset = parseEnvBoolean(process.env.LLMIST_LOG_RESET);\n\n const minLevel = options.minLevel ?? envMinLevel ?? 4;\n const defaultType = options.type ?? \"pretty\";\n const name = options.name ?? \"llmist\";\n // Priority: options > env var > default (false = append)\n const logReset = options.logReset ?? envLogReset ?? false;\n\n let logFileStream: WriteStream | undefined;\n let finalType = defaultType;\n\n if (envLogFile) {\n try {\n mkdirSync(dirname(envLogFile), { recursive: true });\n // Use \"w\" (write/truncate) when logReset is true, \"a\" (append) otherwise\n const flags = logReset ? \"w\" : \"a\";\n logFileStream = createWriteStream(envLogFile, { flags });\n finalType = \"hidden\";\n } catch (error) {\n console.error(\"Failed to initialize LLMIST_LOG_FILE output:\", error);\n }\n }\n\n const logger = new Logger<ILogObj>({\n name,\n minLevel,\n type: finalType,\n // Optimize for production\n hideLogPositionForProduction: finalType !== \"pretty\",\n // Pretty output settings\n prettyLogTemplate:\n finalType === \"pretty\"\n ? \"{{yyyy}}-{{mm}}-{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}} {{logLevelName}} [{{name}}] \"\n : undefined,\n });\n\n if (logFileStream) {\n logger.attachTransport((logObj) => {\n logFileStream?.write(`${JSON.stringify(logObj)}\\n`);\n });\n }\n\n return logger;\n}\n\n/**\n * Default logger instance for the library.\n * Users can replace this with their own configured logger.\n */\nexport const defaultLogger = createLogger();\n","/**\n * Zod schema to JSON Schema conversion with instance mismatch detection.\n *\n * When consumers use their own `import { z } from \"zod\"` instead of\n * `import { z } from \"llmist\"`, the `.describe()` metadata can be lost\n * because Zod stores metadata on schema instances and `toJSONSchema()`\n * only reads from schemas created by the same Zod module instance.\n *\n * This module provides a `schemaToJSONSchema()` function that:\n * 1. Converts Zod schema to JSON Schema using the standard API\n * 2. Detects if descriptions were lost due to instance mismatch\n * 3. Logs a warning recommending `import { z } from \"llmist\"`\n * 4. Falls back to extracting descriptions from `schema._def`\n *\n * @module gadgets/schema-to-json\n */\n\nimport type { ZodTypeAny } from \"zod\";\nimport * as z from \"zod\";\nimport { defaultLogger } from \"../logging/logger.js\";\n\n/**\n * Convert a Zod schema to JSON Schema with description fallback.\n *\n * If descriptions exist in schema._def but are missing from the generated\n * JSON Schema (indicating a Zod instance mismatch), this function:\n * 1. Logs a warning recommending `import { z } from \"llmist\"`\n * 2. Extracts descriptions from _def and merges them into the JSON Schema\n *\n * @param schema - Zod schema to convert\n * @param options - Conversion options (target JSON Schema version)\n * @returns JSON Schema object with descriptions preserved\n *\n * @example\n * ```typescript\n * import { schemaToJSONSchema } from './schema-to-json.js';\n * import { z } from 'zod';\n *\n * const schema = z.object({\n * name: z.string().describe('User name'),\n * });\n *\n * const jsonSchema = schemaToJSONSchema(schema);\n * // { type: 'object', properties: { name: { type: 'string', description: 'User name' } } }\n * ```\n */\nexport function schemaToJSONSchema(\n schema: ZodTypeAny,\n options?: { target?: \"draft-7\" | \"draft-2020-12\" },\n): Record<string, unknown> {\n const jsonSchema = z.toJSONSchema(schema, options ?? { target: \"draft-7\" });\n\n // Check for instance mismatch by comparing _def descriptions with JSON schema\n const mismatches = detectDescriptionMismatch(schema, jsonSchema);\n\n if (mismatches.length > 0) {\n defaultLogger.warn(\n `Zod instance mismatch detected: ${mismatches.length} description(s) lost. ` +\n `For best results, use: import { z } from \"llmist\"`,\n );\n\n // Merge descriptions from _def into JSON schema\n return mergeDescriptions(schema, jsonSchema);\n }\n\n return jsonSchema;\n}\n\n/**\n * Detect if schema._def contains descriptions that are missing from JSON schema.\n * Returns array of paths where descriptions were lost.\n */\nfunction detectDescriptionMismatch(\n schema: ZodTypeAny,\n jsonSchema: Record<string, unknown>,\n): string[] {\n const mismatches: string[] = [];\n\n function checkSchema(zodSchema: ZodTypeAny, json: unknown, path: string): void {\n if (!zodSchema || typeof zodSchema !== \"object\") return;\n\n const def = zodSchema._def as unknown as Record<string, unknown> | undefined;\n const jsonObj = json as Record<string, unknown> | undefined;\n\n // Check if _def has description but JSON schema doesn't\n if (def?.description && !jsonObj?.description) {\n mismatches.push(path || \"root\");\n }\n\n // Recursively check object properties\n if (def?.typeName === \"ZodObject\" && def?.shape) {\n const shape =\n typeof def.shape === \"function\"\n ? (def.shape as () => Record<string, ZodTypeAny>)()\n : def.shape;\n for (const [key, fieldSchema] of Object.entries(shape as Record<string, ZodTypeAny>)) {\n const properties = jsonObj?.properties as Record<string, unknown> | undefined;\n const jsonProp = properties?.[key];\n checkSchema(fieldSchema, jsonProp, path ? `${path}.${key}` : key);\n }\n }\n\n // Check array items\n if (def?.typeName === \"ZodArray\" && def?.type) {\n checkSchema(def.type as ZodTypeAny, jsonObj?.items, path ? `${path}[]` : \"[]\");\n }\n\n // Check optional/nullable wrapped types\n if ((def?.typeName === \"ZodOptional\" || def?.typeName === \"ZodNullable\") && def?.innerType) {\n checkSchema(def.innerType as ZodTypeAny, json, path);\n }\n\n // Check default wrapped types\n if (def?.typeName === \"ZodDefault\" && def?.innerType) {\n checkSchema(def.innerType as ZodTypeAny, json, path);\n }\n }\n\n checkSchema(schema, jsonSchema, \"\");\n return mismatches;\n}\n\n/**\n * Merge descriptions from schema._def into JSON schema.\n * Returns a new JSON schema object with descriptions filled in from _def.\n */\nfunction mergeDescriptions(\n schema: ZodTypeAny,\n jsonSchema: Record<string, unknown>,\n): Record<string, unknown> {\n function merge(zodSchema: ZodTypeAny, json: unknown): unknown {\n if (!json || typeof json !== \"object\") return json;\n\n const def = zodSchema._def as unknown as Record<string, unknown> | undefined;\n const jsonObj = json as Record<string, unknown>;\n const merged: Record<string, unknown> = { ...jsonObj };\n\n // Copy description from _def if missing in JSON\n if (def?.description && !jsonObj.description) {\n merged.description = def.description;\n }\n\n // Recursively merge object properties\n if (def?.typeName === \"ZodObject\" && def?.shape && jsonObj.properties) {\n const shape =\n typeof def.shape === \"function\"\n ? (def.shape as () => Record<string, ZodTypeAny>)()\n : def.shape;\n const properties = jsonObj.properties as Record<string, unknown>;\n merged.properties = { ...properties };\n for (const [key, fieldSchema] of Object.entries(shape as Record<string, ZodTypeAny>)) {\n if (properties[key]) {\n (merged.properties as Record<string, unknown>)[key] = merge(fieldSchema, properties[key]);\n }\n }\n }\n\n // Merge array items\n if (def?.typeName === \"ZodArray\" && def?.type && jsonObj.items) {\n merged.items = merge(def.type as ZodTypeAny, jsonObj.items);\n }\n\n // Handle optional/nullable wrapped types\n if ((def?.typeName === \"ZodOptional\" || def?.typeName === \"ZodNullable\") && def?.innerType) {\n return merge(def.innerType as ZodTypeAny, json);\n }\n\n // Handle default wrapped types\n if (def?.typeName === \"ZodDefault\" && def?.innerType) {\n return merge(def.innerType as ZodTypeAny, json);\n }\n\n return merged;\n }\n\n return merge(schema, jsonSchema) as Record<string, unknown>;\n}\n","import type { ZodTypeAny } from \"zod\";\n\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { schemaToJSONSchema } from \"./schema-to-json.js\";\nimport { validateGadgetSchema } from \"./schema-validator.js\";\nimport type { GadgetExample } from \"./types.js\";\n\n/**\n * Format parameters object as Block format.\n * Uses JSON Pointer paths for nested structures.\n *\n * @param params - The parameters object to format\n * @param prefix - Path prefix for nested structures (internal use)\n * @param argPrefix - The argument prefix marker (defaults to GADGET_ARG_PREFIX)\n */\nfunction formatParamsAsBlock(\n params: Record<string, unknown>,\n prefix: string = \"\",\n argPrefix: string = GADGET_ARG_PREFIX,\n): string {\n const lines: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n const fullPath = prefix ? `${prefix}/${key}` : key;\n\n if (Array.isArray(value)) {\n // Arrays: use numeric indices\n value.forEach((item, index) => {\n const itemPath = `${fullPath}/${index}`;\n if (typeof item === \"object\" && item !== null) {\n // Nested object in array\n lines.push(formatParamsAsBlock(item as Record<string, unknown>, itemPath, argPrefix));\n } else {\n lines.push(`${argPrefix}${itemPath}`);\n lines.push(String(item));\n }\n });\n } else if (typeof value === \"object\" && value !== null) {\n // Nested objects: recurse with path prefix\n lines.push(formatParamsAsBlock(value as Record<string, unknown>, fullPath, argPrefix));\n } else {\n // Simple values\n lines.push(`${argPrefix}${fullPath}`);\n lines.push(String(value));\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format JSON Schema as plain text description.\n * This presents parameters in a neutral, human-readable format\n * that complements the block format used for gadget invocation.\n */\nfunction formatSchemaAsPlainText(schema: Record<string, unknown>, indent = \"\"): string {\n const lines: string[] = [];\n const properties = (schema.properties || {}) as Record<string, unknown>;\n const required = (schema.required || []) as string[];\n\n for (const [key, prop] of Object.entries(properties)) {\n const propObj = prop as Record<string, unknown>;\n const type = propObj.type as string;\n const description = propObj.description as string | undefined;\n const isRequired = required.includes(key);\n const enumValues = propObj.enum as string[] | undefined;\n\n // Build the line\n let line = `${indent}- ${key}`;\n\n // Add type info\n if (type === \"array\") {\n const items = propObj.items as Record<string, unknown> | undefined;\n const itemType = items?.type || \"any\";\n line += ` (array of ${itemType})`;\n } else if (type === \"object\" && propObj.properties) {\n line += \" (object)\";\n } else {\n line += ` (${type})`;\n }\n\n // Add required marker\n if (isRequired) {\n line += \" [required]\";\n }\n\n // Add description\n if (description) {\n line += `: ${description}`;\n }\n\n // Add enum values if present\n if (enumValues) {\n line += ` - one of: ${enumValues.map((v) => `\"${v}\"`).join(\", \")}`;\n }\n\n lines.push(line);\n\n // Recurse for nested objects\n if (type === \"object\" && propObj.properties) {\n lines.push(formatSchemaAsPlainText(propObj, indent + \" \"));\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Internal base class for gadgets. Most users should use the `Gadget` class\n * (formerly TypedGadget) or `createGadget()` function instead, as they provide\n * better type safety and simpler APIs.\n *\n * @internal\n */\nexport abstract class BaseGadget {\n /**\n * The name of the gadget. Used for identification when LLM calls it.\n * If not provided, defaults to the class name.\n */\n name?: string;\n\n /**\n * Human-readable description of what the gadget does.\n */\n abstract description: string;\n\n /**\n * Optional Zod schema describing the expected input payload. When provided,\n * it will be validated before execution and transformed into a JSON Schema\n * representation that is surfaced to the LLM as part of the instructions.\n */\n parameterSchema?: ZodTypeAny;\n\n /**\n * Optional timeout in milliseconds for gadget execution.\n * If execution exceeds this timeout, a TimeoutException will be thrown.\n * If not set, the global defaultGadgetTimeoutMs from runtime options will be used.\n * Set to 0 or undefined to disable timeout for this gadget.\n */\n timeoutMs?: number;\n\n /**\n * Optional usage examples to help LLMs understand proper invocation.\n * Examples are rendered in getInstruction() alongside the schema.\n *\n * Note: Uses broader `unknown` type to allow typed examples from subclasses\n * while maintaining runtime compatibility.\n */\n examples?: GadgetExample<unknown>[];\n\n /**\n * Execute the gadget with the given parameters.\n * Can be synchronous or asynchronous.\n *\n * @param params - Parameters passed from the LLM\n * @returns Result as a string\n */\n abstract execute(params: Record<string, unknown>): string | Promise<string>;\n\n /**\n * Auto-generated instruction text for the LLM.\n * Combines name, description, and parameter schema into a formatted instruction.\n * @deprecated Use getInstruction() instead\n */\n get instruction(): string {\n return this.getInstruction();\n }\n\n /**\n * Generate instruction text for the LLM.\n * Combines name, description, and parameter schema into a formatted instruction.\n *\n * @param argPrefix - Optional custom argument prefix for block format examples\n * @returns Formatted instruction string\n */\n getInstruction(argPrefix?: string): string {\n const parts: string[] = [];\n\n // Add description\n parts.push(this.description);\n\n if (this.parameterSchema) {\n // Validate that the schema doesn't use z.unknown() and can be serialized\n const gadgetName = this.name ?? this.constructor.name;\n validateGadgetSchema(this.parameterSchema, gadgetName);\n\n const jsonSchema = schemaToJSONSchema(this.parameterSchema, {\n target: \"draft-7\",\n });\n\n // Use plain text schema description\n parts.push(\"\\n\\nParameters:\");\n parts.push(formatSchemaAsPlainText(jsonSchema));\n }\n\n // Render examples if present\n if (this.examples && this.examples.length > 0) {\n parts.push(\"\\n\\nExamples:\");\n\n // Use custom argPrefix if provided, otherwise use default\n const effectiveArgPrefix = argPrefix ?? GADGET_ARG_PREFIX;\n\n this.examples.forEach((example, index) => {\n // Add blank line between examples (but not before the first one)\n if (index > 0) {\n parts.push(\"\");\n }\n\n // Add comment if provided\n if (example.comment) {\n parts.push(`# ${example.comment}`);\n }\n\n // Render params in block format\n parts.push(\"Input:\");\n parts.push(formatParamsAsBlock(example.params as Record<string, unknown>, \"\", effectiveArgPrefix));\n\n // Render output if provided\n if (example.output !== undefined) {\n parts.push(\"Output:\");\n parts.push(example.output);\n }\n });\n }\n\n return parts.join(\"\\n\");\n }\n}\n","/**\n * Function-based gadget creation helper.\n *\n * For simple gadgets, use createGadget() instead of defining a class.\n * Parameters are automatically typed from the Zod schema.\n *\n * @example\n * ```typescript\n * const calculator = createGadget({\n * description: \"Performs arithmetic operations\",\n * schema: z.object({\n * operation: z.enum([\"add\", \"subtract\"]),\n * a: z.number(),\n * b: z.number(),\n * }),\n * execute: ({ operation, a, b }) => {\n * // Automatically typed!\n * return operation === \"add\" ? String(a + b) : String(a - b);\n * },\n * });\n * ```\n */\n\nimport type { ZodType } from \"zod\";\nimport { BaseGadget } from \"./gadget.js\";\nimport type { GadgetExample } from \"./types.js\";\n\n/**\n * Infer the TypeScript type from a Zod schema.\n */\ntype InferSchema<T> = T extends ZodType<infer U> ? U : never;\n\n/**\n * Configuration for creating a function-based gadget.\n */\nexport interface CreateGadgetConfig<TSchema extends ZodType> {\n /** Optional custom name (defaults to \"FunctionGadget\") */\n name?: string;\n\n /** Human-readable description of what the gadget does */\n description: string;\n\n /** Zod schema for parameter validation */\n schema: TSchema;\n\n /** Execution function with typed parameters */\n execute: (params: InferSchema<TSchema>) => string | Promise<string>;\n\n /** Optional timeout in milliseconds */\n timeoutMs?: number;\n\n /** Optional usage examples to help LLMs understand proper invocation */\n examples?: GadgetExample<InferSchema<TSchema>>[];\n}\n\n/**\n * Creates a gadget from a function (simpler than class-based approach).\n *\n * This is perfect for simple gadgets where you don't need the full\n * power of a class. Parameters are automatically typed from the schema.\n *\n * @param config - Configuration with execute function and schema\n * @returns Gadget instance ready to be registered\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { createGadget } from 'llmist';\n *\n * // Simple calculator gadget\n * const calculator = createGadget({\n * description: \"Performs arithmetic operations\",\n * schema: z.object({\n * operation: z.enum([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n * a: z.number().describe(\"First number\"),\n * b: z.number().describe(\"Second number\"),\n * }),\n * execute: ({ operation, a, b }) => {\n * // Parameters are automatically typed!\n * switch (operation) {\n * case \"add\": return String(a + b);\n * case \"subtract\": return String(a - b);\n * case \"multiply\": return String(a * b);\n * case \"divide\": return String(a / b);\n * }\n * },\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Async gadget with custom name and timeout\n * const weather = createGadget({\n * name: \"weather\",\n * description: \"Fetches current weather for a city\",\n * schema: z.object({\n * city: z.string().min(1).describe(\"City name\"),\n * }),\n * timeoutMs: 10000,\n * execute: async ({ city }) => {\n * const response = await fetch(`https://api.weather.com/${city}`);\n * const data = await response.json();\n * return `Weather in ${city}: ${data.description}, ${data.temp}°C`;\n * },\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Use with agent\n * const agent = LLMist.createAgent()\n * .withGadgets(calculator, weather)\n * .ask(\"What's the weather in Paris and what's 10 + 5?\");\n * ```\n */\nexport function createGadget<TSchema extends ZodType>(\n config: CreateGadgetConfig<TSchema>,\n): BaseGadget {\n class DynamicGadget extends BaseGadget {\n name = config.name;\n description = config.description;\n parameterSchema = config.schema;\n timeoutMs = config.timeoutMs;\n examples = config.examples;\n\n execute(params: Record<string, unknown>): string | Promise<string> {\n // Cast to inferred type and call user's function\n return config.execute(params as InferSchema<TSchema>);\n }\n }\n\n return new DynamicGadget();\n}\n","/**\n * GadgetOutputViewer - Browse stored outputs from gadgets that exceeded the size limit.\n *\n * When a gadget returns too much data, the output is stored and can be browsed\n * using this gadget with grep-like pattern filtering and line limiting.\n */\n\nimport { z } from \"zod\";\nimport type { GadgetOutputStore } from \"../agent/gadget-output-store.js\";\nimport { createGadget } from \"./create-gadget.js\";\n\n/**\n * Pattern filter configuration.\n */\ninterface PatternFilter {\n /** Regular expression to match */\n regex: string;\n /** true = keep matches, false = exclude matches */\n include: boolean;\n /** Context lines before match (like grep -B) */\n before: number;\n /** Context lines after match (like grep -A) */\n after: number;\n}\n\n/**\n * Apply a single pattern filter to lines.\n *\n * For include=true: keeps lines that match (with before/after context).\n * For include=false: removes lines that match.\n */\nfunction applyPattern(lines: string[], pattern: PatternFilter): string[] {\n const regex = new RegExp(pattern.regex);\n\n if (!pattern.include) {\n // Exclude mode: remove matching lines\n return lines.filter((line) => !regex.test(line));\n }\n\n // Include mode: keep matching lines with context\n const matchIndices = new Set<number>();\n\n // Find all matching line indices\n for (let i = 0; i < lines.length; i++) {\n if (regex.test(lines[i])) {\n // Add the matching line and its context\n const start = Math.max(0, i - pattern.before);\n const end = Math.min(lines.length - 1, i + pattern.after);\n for (let j = start; j <= end; j++) {\n matchIndices.add(j);\n }\n }\n }\n\n // Return lines at matching indices (preserving order)\n return lines.filter((_, index) => matchIndices.has(index));\n}\n\n/**\n * Apply multiple pattern filters in sequence (like piping through grep commands).\n */\nfunction applyPatterns(lines: string[], patterns: PatternFilter[]): string[] {\n let result = lines;\n for (const pattern of patterns) {\n result = applyPattern(result, pattern);\n }\n return result;\n}\n\n/**\n * Parse and apply a line limit string.\n *\n * Formats:\n * - \"100-\" → first 100 lines (slice 0 to 100)\n * - \"-25\" → last 25 lines (slice -25)\n * - \"50-100\" → lines 50-100 (1-indexed, so slice 49 to 100)\n */\nfunction applyLineLimit(lines: string[], limit: string): string[] {\n const trimmed = limit.trim();\n\n // Format: \"100-\" (first N lines)\n if (trimmed.endsWith(\"-\") && !trimmed.startsWith(\"-\")) {\n const n = parseInt(trimmed.slice(0, -1), 10);\n if (!isNaN(n) && n > 0) {\n return lines.slice(0, n);\n }\n }\n\n // Format: \"-25\" (last N lines)\n if (trimmed.startsWith(\"-\") && !trimmed.includes(\"-\", 1)) {\n const n = parseInt(trimmed, 10);\n if (!isNaN(n) && n < 0) {\n return lines.slice(n);\n }\n }\n\n // Format: \"50-100\" (range, 1-indexed)\n const rangeMatch = trimmed.match(/^(\\d+)-(\\d+)$/);\n if (rangeMatch) {\n const start = parseInt(rangeMatch[1], 10);\n const end = parseInt(rangeMatch[2], 10);\n if (!isNaN(start) && !isNaN(end) && start > 0 && end >= start) {\n // Convert from 1-indexed to 0-indexed\n return lines.slice(start - 1, end);\n }\n }\n\n // Invalid format - return unchanged\n return lines;\n}\n\n/**\n * Schema for pattern filter objects.\n */\nconst patternSchema = z.object({\n regex: z.string().describe(\"Regular expression to match\"),\n include: z\n .boolean()\n .default(true)\n .describe(\"true = keep matching lines, false = exclude matching lines\"),\n before: z\n .number()\n .int()\n .min(0)\n .default(0)\n .describe(\"Context lines before each match (like grep -B)\"),\n after: z\n .number()\n .int()\n .min(0)\n .default(0)\n .describe(\"Context lines after each match (like grep -A)\"),\n});\n\n/**\n * Create a GadgetOutputViewer gadget instance bound to a specific output store.\n *\n * This is a factory function because the gadget needs access to the output store,\n * which is created per-agent-run.\n *\n * @param store - The GadgetOutputStore to read outputs from\n * @returns A GadgetOutputViewer gadget instance\n *\n * @example\n * ```typescript\n * const store = new GadgetOutputStore();\n * const viewer = createGadgetOutputViewer(store);\n * registry.register(\"GadgetOutputViewer\", viewer);\n * ```\n */\nexport function createGadgetOutputViewer(store: GadgetOutputStore) {\n return createGadget({\n name: \"GadgetOutputViewer\",\n description:\n \"View stored output from gadgets that returned too much data. \" +\n \"Use patterns to filter lines (like grep) and limit to control output size. \" +\n \"Patterns are applied first in order, then the limit is applied to the result.\",\n schema: z.object({\n id: z.string().describe(\"ID of the stored output (from the truncation message)\"),\n patterns: z\n .array(patternSchema)\n .optional()\n .describe(\n \"Filter patterns applied in order (like piping through grep). \" +\n \"Each pattern can include or exclude lines with optional before/after context.\",\n ),\n limit: z\n .string()\n .optional()\n .describe(\n \"Line range to return after filtering. \" +\n \"Formats: '100-' (first 100), '-25' (last 25), '50-100' (lines 50-100)\",\n ),\n }),\n examples: [\n {\n comment: \"View first 50 lines of stored output\",\n params: { id: \"Search_abc12345\", limit: \"50-\" },\n },\n {\n comment: \"Filter for error lines with context\",\n params: {\n id: \"Search_abc12345\",\n patterns: [{ regex: \"error|Error|ERROR\", include: true, before: 2, after: 5 }],\n },\n },\n {\n comment: \"Exclude blank lines, then show first 100\",\n params: {\n id: \"Search_abc12345\",\n patterns: [{ regex: \"^\\\\s*$\", include: false, before: 0, after: 0 }],\n limit: \"100-\",\n },\n },\n {\n comment: \"Chain filters: find TODOs, exclude tests, limit to 50 lines\",\n params: {\n id: \"Search_abc12345\",\n patterns: [\n { regex: \"TODO\", include: true, before: 1, after: 1 },\n { regex: \"test|spec\", include: false, before: 0, after: 0 },\n ],\n limit: \"50-\",\n },\n },\n ],\n execute: ({ id, patterns, limit }) => {\n const stored = store.get(id);\n if (!stored) {\n return `Error: No stored output with id \"${id}\". Available IDs: ${store.getIds().join(\", \") || \"(none)\"}`;\n }\n\n let lines = stored.content.split(\"\\n\");\n\n // Step 1: Apply patterns in order (like piping through grep)\n if (patterns && patterns.length > 0) {\n lines = applyPatterns(\n lines,\n patterns.map((p) => ({\n regex: p.regex,\n include: p.include ?? true,\n before: p.before ?? 0,\n after: p.after ?? 0,\n })),\n );\n }\n\n // Step 2: Apply line limit AFTER all patterns\n if (limit) {\n lines = applyLineLimit(lines, limit);\n }\n\n // Return result with metadata\n const totalLines = stored.lineCount;\n const returnedLines = lines.length;\n\n if (returnedLines === 0) {\n return `No lines matched the filters. Original output had ${totalLines} lines.`;\n }\n\n const header =\n returnedLines < totalLines\n ? `[Showing ${returnedLines} of ${totalLines} lines]\\n`\n : `[Showing all ${totalLines} lines]\\n`;\n\n return header + lines.join(\"\\n\");\n },\n });\n}\n\n// Export helpers for testing\nexport { applyPattern, applyPatterns, applyLineLimit };\n","/**\n * Configuration types for the context compaction system.\n *\n * Context compaction automatically manages conversation history to prevent\n * context window overflow in long-running agent conversations.\n */\n\nimport type { CompactionStrategy } from \"./strategy.js\";\n\n/**\n * Event emitted when compaction occurs.\n * This is included in StreamEvent for UI visibility.\n */\nexport interface CompactionEvent {\n /** The strategy that performed the compaction */\n strategy: string;\n /** Token count before compaction */\n tokensBefore: number;\n /** Token count after compaction */\n tokensAfter: number;\n /** Number of messages before compaction */\n messagesBefore: number;\n /** Number of messages after compaction */\n messagesAfter: number;\n /** Summary text if summarization was used */\n summary?: string;\n /** Agent iteration when compaction occurred */\n iteration: number;\n}\n\n/**\n * Statistics about compaction activity.\n */\nexport interface CompactionStats {\n /** Total number of compactions performed */\n totalCompactions: number;\n /** Total tokens saved across all compactions */\n totalTokensSaved: number;\n /** Current context usage */\n currentUsage: {\n tokens: number;\n percent: number;\n };\n /** Model's context window size */\n contextWindow: number;\n}\n\n/**\n * Configuration for the context compaction system.\n *\n * @example\n * ```typescript\n * // Custom configuration\n * const agent = await LLMist.createAgent()\n * .withModel('sonnet')\n * .withCompaction({\n * triggerThresholdPercent: 70,\n * targetPercent: 40,\n * preserveRecentTurns: 10,\n * })\n * .ask('...');\n *\n * // Disable compaction\n * const agent = await LLMist.createAgent()\n * .withModel('sonnet')\n * .withoutCompaction()\n * .ask('...');\n * ```\n */\nexport interface CompactionConfig {\n /**\n * Enable or disable compaction.\n * @default true\n */\n enabled?: boolean;\n\n /**\n * The compaction strategy to use.\n * - 'sliding-window': Fast, drops oldest turns (no LLM call)\n * - 'summarization': LLM-based compression of old messages\n * - 'hybrid': Summarizes old messages + keeps recent turns (recommended)\n * - Or provide a custom CompactionStrategy instance\n * @default 'hybrid'\n */\n strategy?: \"sliding-window\" | \"summarization\" | \"hybrid\" | CompactionStrategy;\n\n /**\n * Context usage percentage that triggers compaction.\n * When token count exceeds this percentage of the context window,\n * compaction is performed before the next LLM call.\n * @default 80\n */\n triggerThresholdPercent?: number;\n\n /**\n * Target context usage percentage after compaction.\n * The compaction will aim to reduce tokens to this percentage.\n * @default 50\n */\n targetPercent?: number;\n\n /**\n * Number of recent turns to preserve during compaction.\n * A \"turn\" is a user message + assistant response pair.\n * Recent turns are kept verbatim while older ones are summarized/dropped.\n * @default 5\n */\n preserveRecentTurns?: number;\n\n /**\n * Model to use for summarization.\n * If not specified, uses the agent's model.\n * @default undefined (uses agent's model)\n */\n summarizationModel?: string;\n\n /**\n * Custom system prompt for summarization.\n * If not specified, uses a default prompt optimized for context preservation.\n */\n summarizationPrompt?: string;\n\n /**\n * Callback invoked when compaction occurs.\n * Useful for logging or analytics.\n */\n onCompaction?: (event: CompactionEvent) => void;\n}\n\n/**\n * Default configuration values for compaction.\n * Compaction is enabled by default with the hybrid strategy.\n */\nexport const DEFAULT_COMPACTION_CONFIG: Required<\n Omit<CompactionConfig, \"summarizationModel\" | \"summarizationPrompt\" | \"onCompaction\">\n> = {\n enabled: true,\n strategy: \"hybrid\",\n triggerThresholdPercent: 80,\n targetPercent: 50,\n preserveRecentTurns: 5,\n};\n\n/**\n * Default prompt used for summarization strategy.\n */\nexport const DEFAULT_SUMMARIZATION_PROMPT = `Summarize this conversation history concisely, preserving:\n1. Key decisions made and their rationale\n2. Important facts and data discovered\n3. Errors encountered and how they were resolved\n4. Current task context and goals\n\nFormat as a brief narrative paragraph, not bullet points.\nPrevious conversation:`;\n\n/**\n * Resolved configuration with all defaults applied.\n */\nexport interface ResolvedCompactionConfig {\n enabled: boolean;\n strategy: \"sliding-window\" | \"summarization\" | \"hybrid\";\n triggerThresholdPercent: number;\n targetPercent: number;\n preserveRecentTurns: number;\n summarizationModel?: string;\n summarizationPrompt: string;\n onCompaction?: (event: CompactionEvent) => void;\n}\n\n/**\n * Resolves partial configuration with defaults.\n */\nexport function resolveCompactionConfig(\n config: CompactionConfig = {},\n): ResolvedCompactionConfig {\n const trigger =\n config.triggerThresholdPercent ?? DEFAULT_COMPACTION_CONFIG.triggerThresholdPercent;\n const target = config.targetPercent ?? DEFAULT_COMPACTION_CONFIG.targetPercent;\n\n // Warn about potentially misconfigured thresholds\n if (target >= trigger) {\n console.warn(\n `[llmist/compaction] targetPercent (${target}) should be less than triggerThresholdPercent (${trigger}) to be effective.`,\n );\n }\n\n // Handle custom strategy instances vs string names\n const strategy = config.strategy ?? DEFAULT_COMPACTION_CONFIG.strategy;\n const strategyName =\n typeof strategy === \"object\" && \"name\" in strategy\n ? (strategy.name as \"sliding-window\" | \"summarization\" | \"hybrid\")\n : strategy;\n\n return {\n enabled: config.enabled ?? DEFAULT_COMPACTION_CONFIG.enabled,\n strategy: strategyName,\n triggerThresholdPercent: trigger,\n targetPercent: target,\n preserveRecentTurns:\n config.preserveRecentTurns ?? DEFAULT_COMPACTION_CONFIG.preserveRecentTurns,\n summarizationModel: config.summarizationModel,\n summarizationPrompt: config.summarizationPrompt ?? DEFAULT_SUMMARIZATION_PROMPT,\n onCompaction: config.onCompaction,\n };\n}\n","/**\n * Strategy interface for context compaction.\n *\n * Strategies define how conversation history is compressed to fit within\n * context window limits. Different strategies trade off between:\n * - Speed (LLM calls vs local processing)\n * - Context preservation (summary quality vs simple truncation)\n * - Cost (summarization model usage)\n */\n\nimport type { LLMist } from \"../../core/client.js\";\nimport type { LLMMessage } from \"../../core/messages.js\";\nimport type { ModelLimits } from \"../../core/model-catalog.js\";\nimport type { ResolvedCompactionConfig } from \"./config.js\";\n\n/**\n * Context provided to compaction strategies.\n */\nexport interface CompactionContext {\n /** Current token count of the conversation */\n currentTokens: number;\n /** Target token count after compaction */\n targetTokens: number;\n /** Model's context window limits */\n modelLimits: ModelLimits;\n /** LLMist client for summarization calls */\n client: LLMist;\n /** Model identifier for token counting and summarization */\n model: string;\n}\n\n/**\n * Result of a compaction operation.\n */\nexport interface CompactionResult {\n /** Compacted messages to replace history with */\n messages: LLMMessage[];\n /** Summary text if summarization was used */\n summary?: string;\n /** The name of the strategy that was ultimately executed */\n strategyName: string;\n /** Metadata about the compaction */\n metadata: {\n /** Number of messages before compaction */\n originalCount: number;\n /** Number of messages after compaction */\n compactedCount: number;\n /** Estimated tokens before compaction */\n tokensBefore: number;\n /** Estimated tokens after compaction */\n tokensAfter: number;\n };\n}\n\n/**\n * Interface for compaction strategy implementations.\n *\n * Strategies receive the conversation history (excluding base messages like\n * system prompt and gadget instructions) and must return a compacted version.\n *\n * @example\n * ```typescript\n * class MyCustomStrategy implements CompactionStrategy {\n * readonly name = 'my-custom';\n *\n * async compact(\n * messages: LLMMessage[],\n * config: ResolvedCompactionConfig,\n * context: CompactionContext\n * ): Promise<CompactionResult> {\n * // Custom compaction logic\n * return {\n * messages: compactedMessages,\n * metadata: { ... }\n * };\n * }\n * }\n * ```\n */\nexport interface CompactionStrategy {\n /** Human-readable name of the strategy */\n readonly name: string;\n\n /**\n * Compact the given messages to fit within target token count.\n *\n * @param messages - Conversation history messages (excludes system/gadget base)\n * @param config - Resolved compaction configuration\n * @param context - Context including token counts and LLM client\n * @returns Compacted messages with metadata\n */\n compact(\n messages: LLMMessage[],\n config: ResolvedCompactionConfig,\n context: CompactionContext,\n ): Promise<CompactionResult>;\n}\n\n/**\n * Utility to group messages into logical conversation turns.\n *\n * A \"turn\" is typically a user message followed by an assistant response.\n * Gadget calls are grouped with the preceding assistant message.\n */\nexport interface MessageTurn {\n /** Messages in this turn (user + assistant + any gadget results) */\n messages: LLMMessage[];\n /** Estimated token count for this turn */\n tokenEstimate: number;\n}\n\n/**\n * Groups messages into logical conversation turns.\n *\n * Rules:\n * - A turn starts with a user message\n * - A turn includes all subsequent assistant messages until the next user message\n * - The first message(s) before any user message are considered \"preamble\"\n *\n * @param messages - Array of conversation messages\n * @returns Array of message turns\n */\nexport function groupIntoTurns(messages: LLMMessage[]): MessageTurn[] {\n const turns: MessageTurn[] = [];\n let currentTurn: LLMMessage[] = [];\n\n for (const msg of messages) {\n if (msg.role === \"user\" && currentTurn.length > 0) {\n // Start new turn - save current one\n turns.push({\n messages: currentTurn,\n tokenEstimate: estimateTurnTokens(currentTurn),\n });\n currentTurn = [msg];\n } else {\n currentTurn.push(msg);\n }\n }\n\n // Don't forget the last turn\n if (currentTurn.length > 0) {\n turns.push({\n messages: currentTurn,\n tokenEstimate: estimateTurnTokens(currentTurn),\n });\n }\n\n return turns;\n}\n\n/**\n * Rough token estimation for a turn (4 chars per token).\n */\nfunction estimateTurnTokens(messages: LLMMessage[]): number {\n return Math.ceil(messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4);\n}\n\n/**\n * Flattens turns back into a message array.\n */\nexport function flattenTurns(turns: MessageTurn[]): LLMMessage[] {\n return turns.flatMap((turn) => turn.messages);\n}\n","/**\n * Sliding Window Compaction Strategy\n *\n * A fast, no-LLM-call strategy that simply keeps the most recent N turns\n * and drops older ones. Best for:\n * - Long-running conversations where older context becomes irrelevant\n * - Scenarios requiring minimal latency\n * - As a fallback when summarization is too slow\n */\n\nimport type { LLMMessage } from \"../../../core/messages.js\";\nimport type { ResolvedCompactionConfig } from \"../config.js\";\nimport {\n type CompactionContext,\n type CompactionResult,\n type CompactionStrategy,\n flattenTurns,\n groupIntoTurns,\n} from \"../strategy.js\";\n\n/**\n * Marker message inserted to indicate truncation.\n */\nconst TRUNCATION_MARKER_TEMPLATE = \"[Previous conversation truncated. Removed {count} turn(s) to fit context window.]\";\n\n/**\n * Sliding window strategy - keeps recent turns, drops older ones.\n *\n * This strategy:\n * 1. Groups messages into logical turns (user + assistant pairs)\n * 2. Keeps the `preserveRecentTurns` most recent turns\n * 3. Inserts a truncation marker at the beginning\n * 4. Requires no LLM call - very fast\n */\nexport class SlidingWindowStrategy implements CompactionStrategy {\n readonly name = \"sliding-window\";\n\n async compact(\n messages: LLMMessage[],\n config: ResolvedCompactionConfig,\n context: CompactionContext,\n ): Promise<CompactionResult> {\n const turns = groupIntoTurns(messages);\n const preserveCount = Math.min(config.preserveRecentTurns, turns.length);\n\n // If we have fewer turns than the preserve count, nothing to compact\n if (turns.length <= preserveCount) {\n return {\n messages,\n strategyName: this.name,\n metadata: {\n originalCount: messages.length,\n compactedCount: messages.length,\n tokensBefore: context.currentTokens,\n tokensAfter: context.currentTokens,\n },\n };\n }\n\n // Keep only the most recent turns\n const turnsToKeep = turns.slice(-preserveCount);\n const turnsRemoved = turns.length - preserveCount;\n\n // Create truncation marker\n const truncationMarker: LLMMessage = {\n role: \"user\",\n content: TRUNCATION_MARKER_TEMPLATE.replace(\"{count}\", turnsRemoved.toString()),\n };\n\n // Build compacted message list\n const compactedMessages: LLMMessage[] = [truncationMarker, ...flattenTurns(turnsToKeep)];\n\n // Estimate new token count\n const tokensAfter = Math.ceil(\n compactedMessages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4,\n );\n\n return {\n messages: compactedMessages,\n strategyName: this.name,\n metadata: {\n originalCount: messages.length,\n compactedCount: compactedMessages.length,\n tokensBefore: context.currentTokens,\n tokensAfter,\n },\n };\n }\n}\n","/**\n * Summarization Compaction Strategy\n *\n * Uses an LLM to summarize older conversation messages into a concise summary.\n * Best for:\n * - Tasks where historical context matters\n * - Complex multi-step reasoning\n * - When accuracy is more important than speed\n */\n\nimport type { LLMMessage } from \"../../../core/messages.js\";\nimport type { ResolvedCompactionConfig } from \"../config.js\";\nimport {\n type CompactionContext,\n type CompactionResult,\n type CompactionStrategy,\n flattenTurns,\n groupIntoTurns,\n} from \"../strategy.js\";\n\n/**\n * Summarization strategy - uses LLM to compress conversation history.\n *\n * This strategy:\n * 1. Groups messages into logical turns\n * 2. Keeps recent turns intact\n * 3. Summarizes older turns using LLM\n * 4. Returns summary + recent turns\n */\nexport class SummarizationStrategy implements CompactionStrategy {\n readonly name = \"summarization\";\n\n async compact(\n messages: LLMMessage[],\n config: ResolvedCompactionConfig,\n context: CompactionContext,\n ): Promise<CompactionResult> {\n const turns = groupIntoTurns(messages);\n const preserveCount = Math.min(config.preserveRecentTurns, turns.length);\n\n // If we have fewer turns than the preserve count, nothing to compact\n if (turns.length <= preserveCount) {\n return {\n messages,\n strategyName: this.name,\n metadata: {\n originalCount: messages.length,\n compactedCount: messages.length,\n tokensBefore: context.currentTokens,\n tokensAfter: context.currentTokens,\n },\n };\n }\n\n // Split into turns to summarize and turns to keep\n const turnsToSummarize = turns.slice(0, -preserveCount);\n const turnsToKeep = turns.slice(-preserveCount);\n\n // Build conversation text to summarize\n const conversationToSummarize = this.formatTurnsForSummary(flattenTurns(turnsToSummarize));\n\n // Generate summary using LLM\n const summary = await this.generateSummary(conversationToSummarize, config, context);\n\n // Create summary message\n const summaryMessage: LLMMessage = {\n role: \"user\",\n content: `[Previous conversation summary]\\n${summary}\\n[End of summary - conversation continues below]`,\n };\n\n // Build compacted message list\n const compactedMessages: LLMMessage[] = [summaryMessage, ...flattenTurns(turnsToKeep)];\n\n // Estimate new token count\n const tokensAfter = Math.ceil(\n compactedMessages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4,\n );\n\n return {\n messages: compactedMessages,\n summary,\n strategyName: this.name,\n metadata: {\n originalCount: messages.length,\n compactedCount: compactedMessages.length,\n tokensBefore: context.currentTokens,\n tokensAfter,\n },\n };\n }\n\n /**\n * Formats messages into a readable conversation format for summarization.\n */\n private formatTurnsForSummary(messages: LLMMessage[]): string {\n return messages\n .map((msg) => {\n const role = msg.role.charAt(0).toUpperCase() + msg.role.slice(1);\n return `${role}: ${msg.content}`;\n })\n .join(\"\\n\\n\");\n }\n\n /**\n * Generates a summary using the configured LLM.\n */\n private async generateSummary(\n conversation: string,\n config: ResolvedCompactionConfig,\n context: CompactionContext,\n ): Promise<string> {\n const model = config.summarizationModel ?? context.model;\n const prompt = `${config.summarizationPrompt}\\n\\n${conversation}`;\n\n // Use the LLMist client's complete method for summarization\n const response = await context.client.complete(prompt, {\n model,\n temperature: 0.3, // Low temperature for factual summarization\n });\n\n return response.trim();\n }\n}\n","/**\n * Hybrid Compaction Strategy\n *\n * Combines sliding window and summarization for the best of both worlds:\n * 1. Identifies which turns to compact vs keep (like sliding window)\n * 2. Summarizes the older turns (like summarization)\n * 3. Returns summary + recent turns intact\n *\n * Falls back to sliding window if there are too few turns to summarize.\n */\n\nimport type { LLMMessage } from \"../../../core/messages.js\";\nimport type { ResolvedCompactionConfig } from \"../config.js\";\nimport {\n type CompactionContext,\n type CompactionResult,\n type CompactionStrategy,\n groupIntoTurns,\n} from \"../strategy.js\";\nimport { SlidingWindowStrategy } from \"./sliding-window.js\";\nimport { SummarizationStrategy } from \"./summarization.js\";\n\n/**\n * Minimum turns needed to make summarization worthwhile.\n * Below this threshold, we fall back to sliding window.\n */\nconst MIN_TURNS_FOR_SUMMARIZATION = 3;\n\n/**\n * Hybrid strategy - summarizes old turns + keeps recent turns.\n *\n * This is the recommended default strategy as it:\n * - Preserves important historical context via summarization\n * - Keeps recent conversation turns verbatim for continuity\n * - Falls back gracefully to sliding window when appropriate\n */\nexport class HybridStrategy implements CompactionStrategy {\n readonly name = \"hybrid\";\n\n private readonly slidingWindow = new SlidingWindowStrategy();\n private readonly summarization = new SummarizationStrategy();\n\n async compact(\n messages: LLMMessage[],\n config: ResolvedCompactionConfig,\n context: CompactionContext,\n ): Promise<CompactionResult> {\n const turns = groupIntoTurns(messages);\n const preserveCount = Math.min(config.preserveRecentTurns, turns.length);\n\n // If we have fewer turns than the preserve count, nothing to compact\n if (turns.length <= preserveCount) {\n return {\n messages,\n strategyName: this.name,\n metadata: {\n originalCount: messages.length,\n compactedCount: messages.length,\n tokensBefore: context.currentTokens,\n tokensAfter: context.currentTokens,\n },\n };\n }\n\n // Calculate how many turns would be summarized\n const turnsToSummarize = turns.length - preserveCount;\n\n // If there are too few turns to summarize, use sliding window instead\n if (turnsToSummarize < MIN_TURNS_FOR_SUMMARIZATION) {\n // Delegate to sliding window - propagate its strategyName for accurate reporting\n return this.slidingWindow.compact(messages, config, context);\n }\n\n // Use summarization for older turns - propagate its strategyName\n return this.summarization.compact(messages, config, context);\n }\n}\n","/**\n * Compaction Strategy Implementations\n *\n * Available strategies:\n * - SlidingWindowStrategy: Fast, drops oldest turns (no LLM call)\n * - SummarizationStrategy: LLM-based compression\n * - HybridStrategy: Summarizes old + keeps recent (recommended)\n */\n\nexport { SlidingWindowStrategy } from \"./sliding-window.js\";\nexport { SummarizationStrategy } from \"./summarization.js\";\nexport { HybridStrategy } from \"./hybrid.js\";\n","/**\n * CompactionManager - Central orchestrator for context compaction.\n *\n * Monitors token usage and coordinates compaction strategies to keep\n * conversation context within model limits.\n */\n\nimport type { LLMist } from \"../../core/client.js\";\nimport type { ModelLimits } from \"../../core/model-catalog.js\";\nimport type { IConversationManager } from \"../interfaces.js\";\nimport {\n type CompactionConfig,\n type CompactionEvent,\n type CompactionStats,\n type ResolvedCompactionConfig,\n resolveCompactionConfig,\n} from \"./config.js\";\nimport type { CompactionStrategy } from \"./strategy.js\";\nimport type { LLMMessage } from \"../../core/messages.js\";\nimport { HybridStrategy, SlidingWindowStrategy, SummarizationStrategy } from \"./strategies/index.js\";\n\n/**\n * Pre-computed token counts to avoid redundant counting.\n * Passed from checkAndCompact to compact for efficiency.\n */\ninterface PrecomputedTokens {\n historyMessages: LLMMessage[];\n baseMessages: LLMMessage[];\n historyTokens: number;\n baseTokens: number;\n currentTokens: number;\n}\n\n/**\n * Creates a strategy instance from a strategy name.\n */\nfunction createStrategy(name: string): CompactionStrategy {\n switch (name) {\n case \"sliding-window\":\n return new SlidingWindowStrategy();\n case \"summarization\":\n return new SummarizationStrategy();\n case \"hybrid\":\n return new HybridStrategy();\n default:\n throw new Error(`Unknown compaction strategy: ${name}`);\n }\n}\n\n/**\n * CompactionManager orchestrates context compaction for an agent.\n *\n * It:\n * - Monitors token usage before each LLM call\n * - Triggers compaction when threshold is exceeded\n * - Coordinates with ConversationManager to update history\n * - Tracks statistics for observability\n */\nexport class CompactionManager {\n private readonly client: LLMist;\n private readonly model: string;\n private readonly config: ResolvedCompactionConfig;\n private readonly strategy: CompactionStrategy;\n private modelLimits?: ModelLimits;\n\n // Statistics\n private totalCompactions = 0;\n private totalTokensSaved = 0;\n private lastTokenCount = 0;\n\n constructor(client: LLMist, model: string, config: CompactionConfig = {}) {\n this.client = client;\n this.model = model;\n this.config = resolveCompactionConfig(config);\n\n // Create strategy instance (support both string name and custom instance)\n if (typeof config.strategy === \"object\" && \"compact\" in config.strategy) {\n this.strategy = config.strategy as CompactionStrategy;\n } else {\n this.strategy = createStrategy(this.config.strategy);\n }\n }\n\n /**\n * Check if compaction is needed and perform it if so.\n *\n * @param conversation - The conversation manager to compact\n * @param iteration - Current agent iteration (for event metadata)\n * @returns CompactionEvent if compaction was performed, null otherwise\n */\n async checkAndCompact(\n conversation: IConversationManager,\n iteration: number,\n ): Promise<CompactionEvent | null> {\n if (!this.config.enabled) {\n return null;\n }\n\n // Get model limits (cached after first call)\n if (!this.modelLimits) {\n this.modelLimits = this.client.modelRegistry.getModelLimits(this.model);\n if (!this.modelLimits) {\n // Model not found in registry, skip compaction silently\n // This is not an error - it just means we can't determine context limits\n return null;\n }\n }\n\n // Count current tokens (skip if client doesn't support token counting)\n if (!this.client.countTokens) {\n return null;\n }\n const messages = conversation.getMessages();\n const currentTokens = await this.client.countTokens(this.model, messages);\n this.lastTokenCount = currentTokens;\n\n // Calculate usage percentage\n const usagePercent = (currentTokens / this.modelLimits.contextWindow) * 100;\n\n // Check if we need to compact\n if (usagePercent < this.config.triggerThresholdPercent) {\n return null;\n }\n\n // Perform compaction with precomputed token counts to avoid redundant counting\n const historyMessages = conversation.getHistoryMessages();\n const baseMessages = conversation.getBaseMessages();\n const historyTokens = await this.client.countTokens(this.model, historyMessages);\n const baseTokens = await this.client.countTokens(this.model, baseMessages);\n\n return this.compact(conversation, iteration, {\n historyMessages,\n baseMessages,\n historyTokens,\n baseTokens,\n currentTokens: historyTokens + baseTokens,\n });\n }\n\n /**\n * Force compaction regardless of threshold.\n *\n * @param conversation - The conversation manager to compact\n * @param iteration - Current agent iteration (for event metadata). Use -1 for manual compaction.\n * @param precomputed - Optional pre-computed token counts (passed from checkAndCompact for efficiency)\n * @returns CompactionEvent with compaction details\n */\n async compact(\n conversation: IConversationManager,\n iteration: number,\n precomputed?: PrecomputedTokens,\n ): Promise<CompactionEvent | null> {\n if (!this.modelLimits) {\n this.modelLimits = this.client.modelRegistry.getModelLimits(this.model);\n if (!this.modelLimits) {\n return null;\n }\n }\n\n // Use precomputed values if available, otherwise compute them\n const historyMessages = precomputed?.historyMessages ?? conversation.getHistoryMessages();\n const baseMessages = precomputed?.baseMessages ?? conversation.getBaseMessages();\n const historyTokens =\n precomputed?.historyTokens ?? (await this.client.countTokens(this.model, historyMessages));\n const baseTokens =\n precomputed?.baseTokens ?? (await this.client.countTokens(this.model, baseMessages));\n const currentTokens = precomputed?.currentTokens ?? historyTokens + baseTokens;\n\n // Calculate target tokens for history (leaving room for base messages and output)\n const targetTotalTokens = Math.floor(\n (this.modelLimits.contextWindow * this.config.targetPercent) / 100,\n );\n const targetHistoryTokens = Math.max(0, targetTotalTokens - baseTokens);\n\n // Run the compaction strategy\n const result = await this.strategy.compact(historyMessages, this.config, {\n currentTokens: historyTokens,\n targetTokens: targetHistoryTokens,\n modelLimits: this.modelLimits,\n client: this.client,\n model: this.config.summarizationModel ?? this.model,\n });\n\n // Replace the conversation history\n conversation.replaceHistory(result.messages);\n\n // Count tokens after compaction\n const afterTokens = await this.client.countTokens(this.model, conversation.getMessages());\n const tokensSaved = currentTokens - afterTokens;\n\n // Update statistics\n this.totalCompactions++;\n this.totalTokensSaved += tokensSaved;\n this.lastTokenCount = afterTokens;\n\n // Create event - use result.strategyName for accurate reporting (e.g., when hybrid falls back to sliding-window)\n const event: CompactionEvent = {\n strategy: result.strategyName,\n tokensBefore: currentTokens,\n tokensAfter: afterTokens,\n messagesBefore: historyMessages.length + baseMessages.length,\n messagesAfter: result.messages.length + baseMessages.length,\n summary: result.summary,\n iteration,\n };\n\n // Call onCompaction callback if provided\n if (this.config.onCompaction) {\n try {\n this.config.onCompaction(event);\n } catch (err) {\n console.warn(\"[llmist/compaction] onCompaction callback error:\", err);\n }\n }\n\n return event;\n }\n\n /**\n * Get compaction statistics.\n */\n getStats(): CompactionStats {\n const contextWindow = this.modelLimits?.contextWindow ?? 0;\n return {\n totalCompactions: this.totalCompactions,\n totalTokensSaved: this.totalTokensSaved,\n currentUsage: {\n tokens: this.lastTokenCount,\n percent: contextWindow > 0 ? (this.lastTokenCount / contextWindow) * 100 : 0,\n },\n contextWindow,\n };\n }\n\n /**\n * Check if compaction is enabled.\n */\n isEnabled(): boolean {\n return this.config.enabled;\n }\n}\n","/**\n * Storage for large gadget outputs that exceed the configured limit.\n *\n * When a gadget returns more data than the configured limit, the output\n * is stored here and can be browsed later using GadgetOutputViewer.\n */\n\nimport { randomBytes } from \"node:crypto\";\n\n/**\n * Metadata and content for a stored gadget output.\n */\nexport interface StoredOutput {\n /** Unique identifier (e.g., \"Search_d34db33f\") */\n id: string;\n /** Name of the gadget that produced this output */\n gadgetName: string;\n /** Full output content */\n content: string;\n /** Size in bytes */\n byteSize: number;\n /** Number of lines */\n lineCount: number;\n /** When the output was stored */\n timestamp: Date;\n}\n\n/**\n * In-memory store for large gadget outputs.\n *\n * Outputs are stored with generated IDs in the format `{GadgetName}_{hex8}`.\n * The store is tied to an agent run and cleared when the agent completes.\n *\n * @example\n * ```typescript\n * const store = new GadgetOutputStore();\n * const id = store.store(\"Search\", largeOutput);\n * // id = \"Search_a1b2c3d4\"\n *\n * const stored = store.get(id);\n * console.log(stored?.lineCount); // 4200\n * ```\n */\nexport class GadgetOutputStore {\n private outputs = new Map<string, StoredOutput>();\n\n /**\n * Store a gadget output and return its ID.\n *\n * @param gadgetName - Name of the gadget that produced the output\n * @param content - Full output content to store\n * @returns Generated ID for retrieving the output later\n */\n store(gadgetName: string, content: string): string {\n const id = this.generateId(gadgetName);\n const encoder = new TextEncoder();\n\n const stored: StoredOutput = {\n id,\n gadgetName,\n content,\n byteSize: encoder.encode(content).length,\n lineCount: content.split(\"\\n\").length,\n timestamp: new Date(),\n };\n\n this.outputs.set(id, stored);\n return id;\n }\n\n /**\n * Retrieve a stored output by ID.\n *\n * @param id - The output ID (e.g., \"Search_d34db33f\")\n * @returns The stored output or undefined if not found\n */\n get(id: string): StoredOutput | undefined {\n return this.outputs.get(id);\n }\n\n /**\n * Check if an output exists.\n *\n * @param id - The output ID to check\n * @returns True if the output exists\n */\n has(id: string): boolean {\n return this.outputs.has(id);\n }\n\n /**\n * Get all stored output IDs.\n *\n * @returns Array of output IDs\n */\n getIds(): string[] {\n return Array.from(this.outputs.keys());\n }\n\n /**\n * Get the number of stored outputs.\n */\n get size(): number {\n return this.outputs.size;\n }\n\n /**\n * Clear all stored outputs.\n * Called when the agent run completes.\n */\n clear(): void {\n this.outputs.clear();\n }\n\n /**\n * Generate a unique ID for a stored output.\n * Format: {GadgetName}_{8 hex chars}\n */\n private generateId(gadgetName: string): string {\n const hex = randomBytes(4).toString(\"hex\");\n return `${gadgetName}_${hex}`;\n }\n}\n","/**\n * Internal key for Agent instantiation.\n * This Symbol is used to ensure only AgentBuilder can create Agent instances.\n *\n * @internal\n */\nexport const AGENT_INTERNAL_KEY = Symbol(\"AGENT_INTERNAL_KEY\");\n\n/**\n * Type guard to check if the key is the correct internal key\n * @internal\n */\nexport function isValidAgentKey(key: unknown): key is typeof AGENT_INTERNAL_KEY {\n return key === AGENT_INTERNAL_KEY;\n}\n","/**\n * ConversationManager handles conversation state and message building.\n * Extracted from AgentLoop to follow Single Responsibility Principle.\n */\n\nimport { type LLMMessage, LLMMessageBuilder } from \"../core/messages.js\";\nimport type { IConversationManager } from \"./interfaces.js\";\n\n/**\n * Options for ConversationManager constructor.\n */\nexport interface ConversationManagerOptions {\n /** Custom gadget start marker prefix */\n startPrefix?: string;\n /** Custom gadget end marker prefix */\n endPrefix?: string;\n /** Custom argument prefix for block format */\n argPrefix?: string;\n}\n\n/**\n * Default implementation of IConversationManager.\n * Manages conversation history by building on top of base messages (system prompt, gadget instructions).\n */\nexport class ConversationManager implements IConversationManager {\n private readonly baseMessages: LLMMessage[];\n private readonly initialMessages: LLMMessage[];\n private historyBuilder: LLMMessageBuilder;\n private readonly startPrefix?: string;\n private readonly endPrefix?: string;\n private readonly argPrefix?: string;\n\n constructor(\n baseMessages: LLMMessage[],\n initialMessages: LLMMessage[],\n options: ConversationManagerOptions = {},\n ) {\n this.baseMessages = baseMessages;\n this.initialMessages = initialMessages;\n this.historyBuilder = new LLMMessageBuilder();\n\n // Store prefixes for history replacement\n this.startPrefix = options.startPrefix;\n this.endPrefix = options.endPrefix;\n this.argPrefix = options.argPrefix;\n\n // Apply custom prefixes if provided (must match system prompt markers)\n if (options.startPrefix && options.endPrefix) {\n this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix, options.argPrefix);\n }\n }\n\n addUserMessage(content: string): void {\n this.historyBuilder.addUser(content);\n }\n\n addAssistantMessage(content: string): void {\n this.historyBuilder.addAssistant(content);\n }\n\n addGadgetCall(gadgetName: string, parameters: Record<string, unknown>, result: string): void {\n this.historyBuilder.addGadgetCall(gadgetName, parameters, result);\n }\n\n getMessages(): LLMMessage[] {\n return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];\n }\n\n getHistoryMessages(): LLMMessage[] {\n return this.historyBuilder.build();\n }\n\n getBaseMessages(): LLMMessage[] {\n return [...this.baseMessages, ...this.initialMessages];\n }\n\n replaceHistory(newHistory: LLMMessage[]): void {\n // Create a new builder with the same prefixes\n this.historyBuilder = new LLMMessageBuilder();\n if (this.startPrefix && this.endPrefix) {\n this.historyBuilder.withPrefixes(this.startPrefix, this.endPrefix, this.argPrefix);\n }\n\n // Add each message from the new history\n for (const msg of newHistory) {\n if (msg.role === \"user\") {\n this.historyBuilder.addUser(msg.content);\n } else if (msg.role === \"assistant\") {\n this.historyBuilder.addAssistant(msg.content);\n }\n // System messages are not added to history (they're in baseMessages)\n }\n }\n}\n","/**\n * Event handler sugar for cleaner event processing.\n *\n * Instead of verbose if/else chains, use named handlers\n * for each event type.\n *\n * @example\n * ```typescript\n * await agent.runWith({\n * onText: (content) => console.log(\"LLM:\", content),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\n\nimport type { StreamEvent } from \"../gadgets/types.js\";\n\n/**\n * Named event handlers for different event types.\n */\nexport interface EventHandlers {\n /** Called when text is generated by the LLM */\n onText?: (content: string) => void | Promise<void>;\n\n /** Called when a gadget is about to be executed */\n onGadgetCall?: (call: {\n gadgetName: string;\n parameters?: Record<string, unknown>;\n parametersRaw: string;\n }) => void | Promise<void>;\n\n /** Called when a gadget execution completes */\n onGadgetResult?: (result: {\n gadgetName: string;\n result?: string;\n error?: string;\n parameters: Record<string, unknown>;\n }) => void | Promise<void>;\n\n /** Called when human input is required */\n onHumanInputRequired?: (data: { question: string; gadgetName: string }) => void | Promise<void>;\n\n /** Called for any other event type */\n onOther?: (event: StreamEvent) => void | Promise<void>;\n}\n\n/**\n * Helper to run an agent with named event handlers.\n *\n * @param agentGenerator - Agent's run() async generator\n * @param handlers - Named event handlers\n *\n * @example\n * ```typescript\n * await runWithHandlers(agent.run(), {\n * onText: (text) => console.log(\"LLM:\", text),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\nexport async function runWithHandlers(\n agentGenerator: AsyncGenerator<StreamEvent>,\n handlers: EventHandlers,\n): Promise<void> {\n for await (const event of agentGenerator) {\n switch (event.type) {\n case \"text\":\n if (handlers.onText) {\n await handlers.onText(event.content);\n }\n break;\n\n case \"gadget_call\":\n if (handlers.onGadgetCall) {\n await handlers.onGadgetCall({\n gadgetName: event.call.gadgetName,\n parameters: event.call.parameters,\n parametersRaw: event.call.parametersRaw,\n });\n }\n break;\n\n case \"gadget_result\":\n if (handlers.onGadgetResult) {\n await handlers.onGadgetResult(event.result);\n }\n break;\n\n case \"human_input_required\":\n if (handlers.onHumanInputRequired) {\n await handlers.onHumanInputRequired({\n question: event.question,\n gadgetName: event.gadgetName,\n });\n }\n break;\n\n default:\n if (handlers.onOther) {\n await handlers.onOther(event);\n }\n break;\n }\n }\n}\n\n/**\n * Helper to collect events by type.\n *\n * @param agentGenerator - Agent's run() async generator\n * @param collect - Object specifying which event types to collect\n * @returns Object with collected events\n *\n * @example\n * ```typescript\n * const { text, gadgetResults } = await collectEvents(agent.run(), {\n * text: true,\n * gadgetResults: true,\n * });\n *\n * console.log(\"Full response:\", text.join(\"\"));\n * console.log(\"Gadget calls:\", gadgetResults.length);\n * ```\n */\nexport async function collectEvents(\n agentGenerator: AsyncGenerator<StreamEvent>,\n collect: {\n text?: boolean;\n gadgetCalls?: boolean;\n gadgetResults?: boolean;\n },\n): Promise<{\n text: string[];\n gadgetCalls: Array<{ gadgetName: string; parameters: Record<string, unknown> }>;\n gadgetResults: Array<{\n gadgetName: string;\n result?: string;\n error?: string;\n parameters: Record<string, unknown>;\n }>;\n}> {\n const result = {\n text: [] as string[],\n gadgetCalls: [] as Array<{ gadgetName: string; parameters: Record<string, unknown> }>,\n gadgetResults: [] as Array<{\n gadgetName: string;\n result?: string;\n error?: string;\n parameters: Record<string, unknown>;\n }>,\n };\n\n for await (const event of agentGenerator) {\n switch (event.type) {\n case \"text\":\n if (collect.text) {\n result.text.push(event.content);\n }\n break;\n\n case \"gadget_call\":\n if (collect.gadgetCalls && event.call.parameters) {\n result.gadgetCalls.push({\n gadgetName: event.call.gadgetName,\n parameters: event.call.parameters,\n });\n }\n break;\n\n case \"gadget_result\":\n if (collect.gadgetResults) {\n result.gadgetResults.push(event.result);\n }\n break;\n }\n }\n\n return result;\n}\n\n/**\n * Helper to collect only text from an agent run.\n *\n * @param agentGenerator - Agent's run() async generator\n * @returns Combined text response\n *\n * @example\n * ```typescript\n * const response = await collectText(agent.run());\n * console.log(response);\n * ```\n */\nexport async function collectText(agentGenerator: AsyncGenerator<StreamEvent>): Promise<string> {\n const chunks: string[] = [];\n\n for await (const event of agentGenerator) {\n if (event.type === \"text\") {\n chunks.push(event.content);\n }\n }\n\n return chunks.join(\"\");\n}\n","/**\n * Runtime validators for hook action types.\n *\n * These validators ensure that controllers return valid action objects,\n * catching common mistakes like missing required fields.\n */\n\nimport type {\n AfterGadgetExecutionAction,\n AfterLLMCallAction,\n AfterLLMErrorAction,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n} from \"./hooks.js\";\n\nexport class HookValidationError extends Error {\n constructor(hookName: string, message: string) {\n super(`Invalid action from ${hookName}: ${message}`);\n this.name = \"HookValidationError\";\n }\n}\n\n/**\n * Validate beforeLLMCall action.\n */\nexport function validateBeforeLLMCallAction(action: BeforeLLMCallAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"beforeLLMCall\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"proceed\" && actionType !== \"skip\") {\n throw new HookValidationError(\n \"beforeLLMCall\",\n `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n );\n }\n\n if (actionType === \"skip\" && !action.syntheticResponse) {\n throw new HookValidationError(\n \"beforeLLMCall\",\n \"When action is 'skip', syntheticResponse is required\",\n );\n }\n}\n\n/**\n * Validate afterLLMCall action.\n */\nexport function validateAfterLLMCallAction(action: AfterLLMCallAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n const validActions = [\"continue\", \"append_messages\", \"modify_and_continue\", \"append_and_modify\"];\n if (!validActions.includes(actionType)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Invalid action type: ${actionType}. Must be one of: ${validActions.join(\", \")}`,\n );\n }\n\n if (actionType === \"append_messages\" || actionType === \"append_and_modify\") {\n if (!(\"messages\" in action) || !action.messages || !Array.isArray(action.messages)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', messages array is required`,\n );\n }\n\n if (action.messages.length === 0) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', messages array must not be empty`,\n );\n }\n\n // Validate each message\n for (let i = 0; i < action.messages.length; i++) {\n const msg = action.messages[i];\n if (!msg || typeof msg !== \"object\") {\n throw new HookValidationError(\"afterLLMCall\", `Message at index ${i} must be an object`);\n }\n if (!msg.role || !msg.content) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Message at index ${i} must have 'role' and 'content' fields`,\n );\n }\n if (![\"system\", \"user\", \"assistant\"].includes(msg.role)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Message at index ${i} has invalid role: ${msg.role}`,\n );\n }\n }\n }\n\n if (actionType === \"modify_and_continue\" || actionType === \"append_and_modify\") {\n if (!(\"modifiedMessage\" in action) || !action.modifiedMessage) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', modifiedMessage is required`,\n );\n }\n }\n}\n\n/**\n * Validate afterLLMError action.\n */\nexport function validateAfterLLMErrorAction(action: AfterLLMErrorAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterLLMError\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"rethrow\" && actionType !== \"recover\") {\n throw new HookValidationError(\n \"afterLLMError\",\n `Invalid action type: ${actionType}. Must be 'rethrow' or 'recover'`,\n );\n }\n\n if (actionType === \"recover\" && !action.fallbackResponse) {\n throw new HookValidationError(\n \"afterLLMError\",\n \"When action is 'recover', fallbackResponse is required\",\n );\n }\n}\n\n/**\n * Validate beforeGadgetExecution action.\n */\nexport function validateBeforeGadgetExecutionAction(action: BeforeGadgetExecutionAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"proceed\" && actionType !== \"skip\") {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n );\n }\n\n if (actionType === \"skip\" && !action.syntheticResult) {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n \"When action is 'skip', syntheticResult is required\",\n );\n }\n}\n\n/**\n * Validate afterGadgetExecution action.\n */\nexport function validateAfterGadgetExecutionAction(action: AfterGadgetExecutionAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"continue\" && actionType !== \"recover\") {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n `Invalid action type: ${actionType}. Must be 'continue' or 'recover'`,\n );\n }\n\n if (actionType === \"recover\" && !action.fallbackResult) {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n \"When action is 'recover', fallbackResult is required\",\n );\n }\n}\n","import type { ZodTypeAny } from \"zod\";\n\n/**\n * Helper to safely access Zod's internal _def structure.\n * Zod's _def is not publicly typed, so we cast through unknown.\n */\nfunction getDef(schema: ZodTypeAny): Record<string, unknown> {\n return schema._def as unknown as Record<string, unknown>;\n}\n\n/**\n * Type hints that guide value coercion.\n * - 'string': Keep the value as a string, no coercion\n * - 'number': Coerce to number if possible\n * - 'boolean': Coerce to boolean if possible\n * - 'unknown': Use default auto-coercion logic (backwards compatible)\n */\nexport type TypeHint = \"string\" | \"number\" | \"boolean\" | \"unknown\";\n\n/**\n * Get the type name from a Zod schema's _def.\n * Handles both Zod v3 (typeName) and Zod v4 (type) structures.\n * Note: We cast _def to any since Zod's internal structure isn't publicly typed.\n */\nfunction getTypeName(schema: ZodTypeAny): string | undefined {\n const def = getDef(schema);\n // Zod v4 uses _def.type, Zod v3 uses _def.typeName\n return (def?.type ?? def?.typeName) as string | undefined;\n}\n\n/**\n * Get the shape from a Zod object schema's _def.\n * Handles both Zod v3 (shape()) and Zod v4 (shape) structures.\n * Note: We cast _def to any since Zod's internal structure isn't publicly typed.\n */\nfunction getShape(\n schema: ZodTypeAny\n): Record<string, ZodTypeAny> | undefined {\n const def = getDef(schema);\n // Zod v4 uses _def.shape directly, Zod v3 uses _def.shape()\n if (typeof def?.shape === \"function\") {\n return (def.shape as () => Record<string, ZodTypeAny>)();\n }\n return def?.shape as Record<string, ZodTypeAny> | undefined;\n}\n\n/**\n * Introspects Zod schemas to determine expected types at JSON pointer paths.\n *\n * This enables schema-aware type coercion - instead of blindly converting\n * \"1\" to a number, the parser can check if the schema expects a string\n * and preserve the original value.\n *\n * Design decisions:\n * - Union types prefer string over other primitives (preserves LLM intent)\n * - Transform/effect schemas return 'unknown' (let Zod handle transformation)\n * - Invalid paths return 'unknown' (fall back to auto-coercion)\n *\n * @example\n * ```typescript\n * const schema = z.object({\n * id: z.string(),\n * count: z.number(),\n * config: z.object({ timeout: z.number() })\n * });\n *\n * const introspector = new SchemaIntrospector(schema);\n * introspector.getTypeAtPath(\"id\"); // 'string'\n * introspector.getTypeAtPath(\"count\"); // 'number'\n * introspector.getTypeAtPath(\"config/timeout\"); // 'number'\n * introspector.getTypeAtPath(\"unknown\"); // 'unknown'\n * ```\n */\nexport class SchemaIntrospector {\n private readonly schema: ZodTypeAny;\n private readonly cache = new Map<string, TypeHint>();\n\n constructor(schema: ZodTypeAny) {\n this.schema = schema;\n }\n\n /**\n * Get the expected type at a JSON pointer path.\n *\n * @param pointer - JSON pointer path without leading / (e.g., \"config/timeout\", \"items/0\")\n * @returns Type hint for coercion decision\n */\n getTypeAtPath(pointer: string): TypeHint {\n // Check cache first\n const cached = this.cache.get(pointer);\n if (cached !== undefined) {\n return cached;\n }\n\n const result = this.resolveTypeAtPath(pointer);\n this.cache.set(pointer, result);\n return result;\n }\n\n /**\n * Internal method to resolve type at path without caching.\n */\n private resolveTypeAtPath(pointer: string): TypeHint {\n // Empty pointer means the root - shouldn't happen for parameters\n if (!pointer) {\n return this.getBaseType(this.schema);\n }\n\n const segments = pointer.split(\"/\");\n let current: ZodTypeAny = this.schema;\n\n for (const segment of segments) {\n // Unwrap any wrapper types (optional, default, nullable, etc.)\n current = this.unwrapSchema(current);\n\n // Navigate based on schema type\n const typeName = getTypeName(current);\n\n if (typeName === \"object\" || typeName === \"ZodObject\") {\n // Navigate into object property\n const shape = getShape(current);\n if (!shape || !(segment in shape)) {\n return \"unknown\"; // Property doesn't exist in schema\n }\n current = shape[segment];\n } else if (typeName === \"array\" || typeName === \"ZodArray\") {\n // For array indices, get element type\n if (!/^\\d+$/.test(segment)) {\n return \"unknown\"; // Not a numeric index\n }\n // Zod v4 uses _def.element, Zod v3 uses _def.type\n const def = getDef(current);\n const elementType = (def?.element ?? def?.type) as ZodTypeAny | undefined;\n if (!elementType) {\n return \"unknown\";\n }\n current = elementType;\n } else if (typeName === \"tuple\" || typeName === \"ZodTuple\") {\n // For tuples, get element at specific index\n if (!/^\\d+$/.test(segment)) {\n return \"unknown\";\n }\n const index = parseInt(segment, 10);\n const def = getDef(current);\n const items = def?.items as ZodTypeAny[] | undefined;\n if (!items || index >= items.length) {\n return \"unknown\";\n }\n current = items[index];\n } else if (typeName === \"record\" || typeName === \"ZodRecord\") {\n // For records, all values have the same type\n // Zod v4 uses _def.valueType, Zod v3 uses _def.valueType\n const def = getDef(current);\n const valueType = def?.valueType as ZodTypeAny | undefined;\n if (!valueType) {\n return \"unknown\";\n }\n current = valueType;\n } else {\n // Can't navigate further (e.g., trying to access property on a string)\n return \"unknown\";\n }\n }\n\n // Get the base type of the final schema\n return this.getBaseType(current);\n }\n\n /**\n * Unwrap schema modifiers (optional, default, nullable, branded, etc.)\n * to get to the underlying type.\n */\n private unwrapSchema(schema: ZodTypeAny): ZodTypeAny {\n let current = schema;\n let iterations = 0;\n const maxIterations = 20; // Prevent infinite loops\n\n while (iterations < maxIterations) {\n const typeName = getTypeName(current);\n\n // Check for wrapper types (both Zod v3 and v4 naming)\n const wrapperTypes = [\n \"optional\",\n \"nullable\",\n \"default\",\n \"catch\",\n \"branded\",\n \"readonly\",\n \"pipeline\",\n \"ZodOptional\",\n \"ZodNullable\",\n \"ZodDefault\",\n \"ZodCatch\",\n \"ZodBranded\",\n \"ZodReadonly\",\n \"ZodPipeline\",\n ];\n\n if (typeName && wrapperTypes.includes(typeName)) {\n const def = getDef(current);\n const inner = (def?.innerType ?? def?.in ?? def?.type) as ZodTypeAny | undefined;\n if (!inner || inner === current) break;\n current = inner;\n iterations++;\n continue;\n }\n\n break;\n }\n\n return current;\n }\n\n /**\n * Get the primitive type hint from an unwrapped schema.\n */\n private getBaseType(schema: ZodTypeAny): TypeHint {\n const unwrapped = this.unwrapSchema(schema);\n const typeName = getTypeName(unwrapped);\n\n // Map both Zod v3 (ZodString) and v4 (string) type names\n switch (typeName) {\n // Primitive types\n case \"string\":\n case \"ZodString\":\n return \"string\";\n case \"number\":\n case \"ZodNumber\":\n case \"bigint\":\n case \"ZodBigInt\":\n return \"number\";\n case \"boolean\":\n case \"ZodBoolean\":\n return \"boolean\";\n\n // Literal types - check the literal value type\n case \"literal\":\n case \"ZodLiteral\": {\n // Zod v4 uses _def.values (array), Zod v3 uses _def.value\n const def = getDef(unwrapped);\n const values = def?.values as unknown[] | undefined;\n const value = values?.[0] ?? def?.value;\n if (typeof value === \"string\") return \"string\";\n if (typeof value === \"number\" || typeof value === \"bigint\")\n return \"number\";\n if (typeof value === \"boolean\") return \"boolean\";\n return \"unknown\";\n }\n\n // Enum - always string keys\n case \"enum\":\n case \"ZodEnum\":\n case \"nativeEnum\":\n case \"ZodNativeEnum\":\n return \"string\";\n\n // Union - return 'unknown' to let auto-coercion decide\n // Since multiple types are valid, we can't definitively say what the LLM intended\n // Auto-coercion will handle common cases (numbers, booleans) appropriately\n case \"union\":\n case \"ZodUnion\":\n return \"unknown\";\n\n // Discriminated union - complex, return unknown\n case \"discriminatedUnion\":\n case \"ZodDiscriminatedUnion\":\n return \"unknown\";\n\n // Intersection - check both sides\n case \"intersection\":\n case \"ZodIntersection\": {\n const def = getDef(unwrapped);\n const left = def?.left as ZodTypeAny | undefined;\n const right = def?.right as ZodTypeAny | undefined;\n if (!left || !right) return \"unknown\";\n\n const leftType = this.getBaseType(left);\n const rightType = this.getBaseType(right);\n\n // If both are the same type, return it\n if (leftType === rightType) return leftType;\n // If one is string, prefer string\n if (leftType === \"string\" || rightType === \"string\") return \"string\";\n // Otherwise return unknown (complex intersection)\n return \"unknown\";\n }\n\n // Effects/transforms - return unknown to let Zod handle it\n case \"effects\":\n case \"ZodEffects\":\n // ZodEffects wraps transforms, refinements, etc.\n // The transform expects input in original format, so don't coerce\n return \"unknown\";\n\n // Lazy - can't resolve without evaluating\n case \"lazy\":\n case \"ZodLazy\":\n return \"unknown\";\n\n // Complex types - return unknown\n case \"object\":\n case \"ZodObject\":\n case \"array\":\n case \"ZodArray\":\n case \"tuple\":\n case \"ZodTuple\":\n case \"record\":\n case \"ZodRecord\":\n case \"map\":\n case \"ZodMap\":\n case \"set\":\n case \"ZodSet\":\n case \"function\":\n case \"ZodFunction\":\n case \"promise\":\n case \"ZodPromise\":\n case \"date\":\n case \"ZodDate\":\n return \"unknown\";\n\n // Unknown/any/never/void/undefined/null\n case \"unknown\":\n case \"ZodUnknown\":\n case \"any\":\n case \"ZodAny\":\n case \"never\":\n case \"ZodNever\":\n case \"void\":\n case \"ZodVoid\":\n case \"undefined\":\n case \"ZodUndefined\":\n case \"null\":\n case \"ZodNull\":\n return \"unknown\";\n\n default:\n return \"unknown\";\n }\n }\n}\n","import type { ZodTypeAny } from \"zod\";\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { SchemaIntrospector, type TypeHint } from \"./schema-introspector.js\";\n\nexport interface BlockParseOptions {\n /** Prefix that declares an argument. Default: \"!!!ARG:\" */\n argPrefix?: string;\n /** Optional Zod schema for schema-aware type coercion */\n schema?: ZodTypeAny;\n}\n\n/**\n * Parse block format parameters into an object.\n *\n * Block format uses !!!ARG:pointer syntax where pointer is a JSON Pointer\n * path (without leading /) that defines where to place the value.\n *\n * Example input:\n * ```\n * !!!ARG:filename\n * calculator.ts\n * !!!ARG:config/timeout\n * 30\n * !!!ARG:items/0\n * first\n * ```\n *\n * Produces:\n * ```json\n * {\n * \"filename\": \"calculator.ts\",\n * \"config\": { \"timeout\": 30 },\n * \"items\": [\"first\"]\n * }\n * ```\n *\n * Single-line values are automatically coerced:\n * - \"true\" / \"false\" → boolean\n * - Numeric strings → number\n * - Multiline values always stay as strings (for code/content)\n *\n * @param content - Raw parameter content (after gadget name line, before end marker)\n * @param options - Parser options\n * @returns Parsed parameters object with coerced values\n * @throws Error if duplicate pointers or invalid array indices\n */\nexport function parseBlockParams(\n content: string,\n options?: BlockParseOptions\n): Record<string, unknown> {\n const argPrefix = options?.argPrefix ?? GADGET_ARG_PREFIX;\n const result: Record<string, unknown> = {};\n const seenPointers = new Set<string>();\n\n // Create schema introspector if schema is provided\n const introspector = options?.schema\n ? new SchemaIntrospector(options.schema)\n : undefined;\n\n // Split content by arg prefix to get individual arg entries\n // First element will be empty or whitespace before first arg\n const parts = content.split(argPrefix);\n\n for (let i = 1; i < parts.length; i++) {\n const part = parts[i];\n\n // Find the pointer (first line) and value (rest)\n const newlineIndex = part.indexOf(\"\\n\");\n if (newlineIndex === -1) {\n // Arg with no value (just the pointer line)\n const pointer = part.trim();\n if (pointer) {\n if (seenPointers.has(pointer)) {\n throw new Error(`Duplicate pointer: ${pointer}`);\n }\n seenPointers.add(pointer);\n setByPointer(result, pointer, \"\", introspector);\n }\n continue;\n }\n\n const pointer = part.substring(0, newlineIndex).trim();\n let value = part.substring(newlineIndex + 1);\n\n // Strip single trailing newline if present (per spec)\n if (value.endsWith(\"\\n\")) {\n value = value.slice(0, -1);\n }\n\n if (!pointer) {\n continue; // Skip empty pointers\n }\n\n if (seenPointers.has(pointer)) {\n throw new Error(`Duplicate pointer: ${pointer}`);\n }\n seenPointers.add(pointer);\n\n setByPointer(result, pointer, value, introspector);\n }\n\n return result;\n}\n\n/**\n * Coerce a string value to its appropriate primitive type.\n *\n * When an `expectedType` hint is provided (from schema introspection), the coercion\n * respects the schema's expected type:\n * - 'string': Keep value as string, no coercion\n * - 'number': Coerce to number if valid\n * - 'boolean': Coerce to boolean if \"true\"/\"false\"\n * - 'unknown': Use auto-coercion logic (backwards compatible)\n *\n * Without a type hint (undefined), uses auto-coercion:\n * - \"true\" / \"false\" → boolean\n * - Numeric strings → number\n * - Everything else stays string\n *\n * Multiline values are never coerced (likely code/content).\n *\n * @param value - The string value to coerce\n * @param expectedType - Optional type hint from schema introspection\n * @returns Coerced value\n */\nfunction coerceValue(\n value: string,\n expectedType?: TypeHint\n): string | number | boolean {\n // Don't coerce multiline values - they're likely code/content\n if (value.includes(\"\\n\")) {\n return value;\n }\n\n const trimmed = value.trim();\n\n // If schema provides a type hint, respect it\n if (expectedType === \"string\") {\n // Keep as string - no coercion at all\n return value;\n }\n\n if (expectedType === \"boolean\") {\n // Only coerce recognized boolean strings\n if (trimmed === \"true\") return true;\n if (trimmed === \"false\") return false;\n // Invalid boolean - keep as string for Zod to report error\n return value;\n }\n\n if (expectedType === \"number\") {\n // Attempt to coerce to number\n const num = Number(trimmed);\n if (!isNaN(num) && isFinite(num) && trimmed !== \"\") {\n return num;\n }\n // Invalid number - keep as string for Zod to report error\n return value;\n }\n\n // expectedType === 'unknown' or undefined: use auto-coercion logic\n // This maintains backwards compatibility when no schema is provided\n // or when schema introspection can't determine the type\n\n // Boolean coercion\n if (trimmed === \"true\") return true;\n if (trimmed === \"false\") return false;\n\n // Number coercion - only for values that look clearly numeric\n // Avoid coercing things like \"123abc\" or empty strings\n if (trimmed !== \"\" && /^-?\\d+(\\.\\d+)?$/.test(trimmed)) {\n const num = Number(trimmed);\n if (!isNaN(num) && isFinite(num)) {\n return num;\n }\n }\n\n return value;\n}\n\n/**\n * Set a value in an object using a JSON Pointer path (without leading /).\n *\n * Handles:\n * - Simple keys: \"name\" → { name: value }\n * - Nested paths: \"config/timeout\" → { config: { timeout: value } }\n * - Array indices: \"items/0\" → { items: [value] }\n *\n * Values are coerced based on the schema's expected type when an introspector\n * is provided. Without a schema, falls back to auto-coercion (backwards compatible).\n *\n * @param obj - Target object to modify\n * @param pointer - JSON Pointer path without leading /\n * @param value - Value to set (string that may be coerced)\n * @param introspector - Optional schema introspector for type-aware coercion\n * @throws Error if array index gaps detected\n */\nfunction setByPointer(\n obj: Record<string, unknown>,\n pointer: string,\n value: string,\n introspector?: SchemaIntrospector\n): void {\n const segments = pointer.split(\"/\");\n let current: Record<string, unknown> | unknown[] = obj;\n\n for (let i = 0; i < segments.length - 1; i++) {\n const segment = segments[i];\n const nextSegment = segments[i + 1];\n const nextIsArrayIndex = /^\\d+$/.test(nextSegment);\n\n if (Array.isArray(current)) {\n const index = parseInt(segment, 10);\n if (isNaN(index) || index < 0) {\n throw new Error(`Invalid array index: ${segment}`);\n }\n // Validate no gaps\n if (index > current.length) {\n throw new Error(`Array index gap: expected ${current.length}, got ${index}`);\n }\n if (current[index] === undefined) {\n current[index] = nextIsArrayIndex ? [] : {};\n }\n current = current[index] as Record<string, unknown> | unknown[];\n } else {\n // current is an object\n const rec = current as Record<string, unknown>;\n if (rec[segment] === undefined) {\n rec[segment] = nextIsArrayIndex ? [] : {};\n }\n current = rec[segment] as Record<string, unknown> | unknown[];\n }\n }\n\n // Set the final value\n const lastSegment = segments[segments.length - 1];\n\n // Get expected type from schema if available, then coerce accordingly\n const expectedType = introspector?.getTypeAtPath(pointer);\n const coercedValue = coerceValue(value, expectedType);\n\n if (Array.isArray(current)) {\n const index = parseInt(lastSegment, 10);\n if (isNaN(index) || index < 0) {\n throw new Error(`Invalid array index: ${lastSegment}`);\n }\n // Validate no gaps\n if (index > current.length) {\n throw new Error(`Array index gap: expected ${current.length}, got ${index}`);\n }\n current[index] = coercedValue;\n } else {\n (current as Record<string, unknown>)[lastSegment] = coercedValue;\n }\n}\n","import type { ZodError } from \"zod\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { BaseGadget } from \"./gadget.js\";\n\nexport interface ErrorFormatterOptions {\n /** Custom argument prefix for block format examples. Default: \"!!!ARG:\" */\n argPrefix?: string;\n /** Custom start prefix for block format examples. Default: \"!!!GADGET_START:\" */\n startPrefix?: string;\n /** Custom end prefix for block format examples. Default: \"!!!GADGET_END\" */\n endPrefix?: string;\n}\n\n/**\n * Formats gadget errors with helpful context for LLMs.\n *\n * This class generates error messages that include:\n * - Clear error description\n * - Full gadget usage instructions (via getInstruction())\n * - Block format reference for parse errors\n *\n * The goal is to help LLMs self-correct on subsequent invocation attempts.\n */\nexport class GadgetErrorFormatter {\n private readonly argPrefix: string;\n private readonly startPrefix: string;\n private readonly endPrefix: string;\n\n constructor(options: ErrorFormatterOptions = {}) {\n this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;\n this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;\n this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;\n }\n\n /**\n * Format a Zod validation error with full gadget instructions.\n *\n * @param gadgetName - Name of the gadget that was called\n * @param zodError - The Zod validation error\n * @param gadget - The gadget instance (for generating instructions)\n * @returns Formatted error message with usage instructions\n */\n formatValidationError(gadgetName: string, zodError: ZodError, gadget: BaseGadget): string {\n const parts: string[] = [];\n\n // Error header\n parts.push(`Error: Invalid parameters for '${gadgetName}':`);\n\n // Format each validation issue\n for (const issue of zodError.issues) {\n const path = issue.path.join(\".\") || \"root\";\n parts.push(` - ${path}: ${issue.message}`);\n }\n\n // Add gadget usage instructions\n parts.push(\"\");\n parts.push(\"Gadget Usage:\");\n parts.push(gadget.getInstruction(this.argPrefix));\n\n return parts.join(\"\\n\");\n }\n\n /**\n * Format a parse error with block format reference.\n *\n * @param gadgetName - Name of the gadget that was called\n * @param parseError - The parse error message\n * @param gadget - The gadget instance if found (for generating instructions)\n * @returns Formatted error message with format reference\n */\n formatParseError(gadgetName: string, parseError: string, gadget: BaseGadget | undefined): string {\n const parts: string[] = [];\n\n // Error header\n parts.push(`Error: Failed to parse parameters for '${gadgetName}':`);\n parts.push(` ${parseError}`);\n\n // Add gadget usage instructions if gadget exists\n if (gadget) {\n parts.push(\"\");\n parts.push(\"Gadget Usage:\");\n parts.push(gadget.getInstruction(this.argPrefix));\n }\n\n // Always add block format reference\n parts.push(\"\");\n parts.push(\"Block Format Reference:\");\n parts.push(` ${this.startPrefix}${gadgetName}`);\n parts.push(` ${this.argPrefix}parameterName`);\n parts.push(\" parameter value here\");\n parts.push(` ${this.endPrefix}`);\n\n return parts.join(\"\\n\");\n }\n\n /**\n * Format a registry error (gadget not found) with available gadgets list.\n *\n * @param gadgetName - Name of the gadget that was not found\n * @param availableGadgets - List of available gadget names\n * @returns Formatted error message with available gadgets\n */\n formatRegistryError(gadgetName: string, availableGadgets: string[]): string {\n const parts: string[] = [];\n\n // Error header\n parts.push(`Error: Gadget '${gadgetName}' not found.`);\n\n // List available gadgets\n if (availableGadgets.length > 0) {\n parts.push(\"\");\n parts.push(`Available gadgets: ${availableGadgets.join(\", \")}`);\n } else {\n parts.push(\"\");\n parts.push(\"No gadgets are currently registered.\");\n }\n\n return parts.join(\"\\n\");\n }\n}\n\n/**\n * Create a pre-configured error formatter instance.\n *\n * @param options - Formatter options\n * @returns Configured GadgetErrorFormatter instance\n */\nexport function createErrorFormatter(options: ErrorFormatterOptions = {}): GadgetErrorFormatter {\n return new GadgetErrorFormatter(options);\n}\n","/**\n * Exception that gadgets can throw to signal the agent loop should terminate.\n *\n * When a gadget throws this exception, the agent loop will:\n * 1. Complete the current iteration\n * 2. Return the exception message as the gadget's result\n * 3. Exit the loop instead of continuing to the next iteration\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * class FinishGadget extends Gadget({\n * name: 'Finish',\n * description: 'Signals task completion',\n * schema: z.object({\n * message: z.string().optional(),\n * }),\n * }) {\n * execute(params: this['params']): string {\n * const message = params.message || 'Task completed';\n * throw new BreakLoopException(message);\n * }\n * }\n * ```\n */\nexport class BreakLoopException extends Error {\n constructor(message?: string) {\n super(message ?? \"Agent loop terminated by gadget\");\n this.name = \"BreakLoopException\";\n }\n}\n\n/**\n * Exception that gadgets can throw to request human input during execution.\n *\n * When a gadget throws this exception, the agent loop will:\n * 1. Pause execution and wait for human input\n * 2. If `onHumanInputRequired` callback is provided, call it and await the answer\n * 3. Return the user's answer as the gadget's result\n * 4. Continue the loop with the answer added to conversation history\n *\n * If no callback is provided, the loop will yield a `human_input_required` event\n * and the caller must handle it externally.\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * class AskUserGadget extends Gadget({\n * name: 'AskUser',\n * description: 'Ask the user a question and get their answer',\n * schema: z.object({\n * question: z.string().min(1, 'Question is required'),\n * }),\n * }) {\n * execute(params: this['params']): string {\n * throw new HumanInputException(params.question);\n * }\n * }\n * ```\n */\nexport class HumanInputException extends Error {\n public readonly question: string;\n\n constructor(question: string) {\n super(`Human input required: ${question}`);\n this.name = \"HumanInputException\";\n this.question = question;\n }\n}\n\n/**\n * Exception thrown when a gadget execution exceeds its timeout limit.\n *\n * When a gadget's execution time exceeds either:\n * - The gadget's own `timeoutMs` property, or\n * - The global `defaultGadgetTimeoutMs` configured in runtime/agent loop options\n *\n * The executor will automatically throw this exception and return it as an error.\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * class SlowApiGadget extends Gadget({\n * name: 'SlowApi',\n * description: 'Calls a slow external API',\n * timeoutMs: 5000, // 5 second timeout\n * schema: z.object({\n * endpoint: z.string(),\n * }),\n * }) {\n * async execute(params: this['params']): Promise<string> {\n * // If this takes longer than 5 seconds, execution will be aborted\n * const response = await fetch(params.endpoint);\n * return await response.text();\n * }\n * }\n * ```\n */\nexport class TimeoutException extends Error {\n public readonly timeoutMs: number;\n public readonly gadgetName: string;\n\n constructor(gadgetName: string, timeoutMs: number) {\n super(`Gadget '${gadgetName}' execution exceeded timeout of ${timeoutMs}ms`);\n this.name = \"TimeoutException\";\n this.gadgetName = gadgetName;\n this.timeoutMs = timeoutMs;\n }\n}\n","import { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { StreamEvent } from \"./types.js\";\nimport { parseBlockParams } from \"./block-params.js\";\n\nexport type ParameterFormat = \"block\";\n\n\n/**\n * Strip markdown code fences from parameter content.\n * LLMs sometimes wrap their parameters in ```toml, ```yaml, ```json, or plain ``` blocks.\n * This function removes those fences to allow successful parsing.\n *\n * @internal Exported for testing only\n */\nexport function stripMarkdownFences(content: string): string {\n let cleaned = content.trim();\n\n // Pattern: ```toml, ```yaml, ```json, or just ``` at start (case-insensitive)\n const openingFence = /^```(?:toml|yaml|json)?\\s*\\n/i;\n // Pattern: ``` at end (with optional preceding newline)\n const closingFence = /\\n?```\\s*$/;\n\n // Strip opening fence if present\n cleaned = cleaned.replace(openingFence, \"\");\n // Strip closing fence if present\n cleaned = cleaned.replace(closingFence, \"\");\n\n return cleaned.trim();\n}\n\nexport interface StreamParserOptions {\n startPrefix?: string;\n endPrefix?: string;\n /** Prefix for block format arguments. Default: \"!!!ARG:\" */\n argPrefix?: string;\n}\n\n// Global counter for generating unique invocation IDs across all parser instances\nlet globalInvocationCounter = 0;\n\n/**\n * Reset the global invocation counter. Only use this in tests!\n * @internal\n */\nexport function resetGlobalInvocationCounter(): void {\n globalInvocationCounter = 0;\n}\n\nexport class StreamParser {\n private buffer = \"\";\n private lastReportedTextLength = 0;\n private readonly startPrefix: string;\n private readonly endPrefix: string;\n private readonly argPrefix: string;\n\n constructor(options: StreamParserOptions = {}) {\n this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;\n this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;\n this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;\n }\n\n private takeTextUntil(index: number): string | undefined {\n if (index <= this.lastReportedTextLength) {\n return undefined;\n }\n\n const segment = this.buffer.slice(this.lastReportedTextLength, index);\n this.lastReportedTextLength = index;\n\n return segment.trim().length > 0 ? segment : undefined;\n }\n\n /**\n * Parse gadget name, handling both old format (name:invocationId) and new format (just name).\n * For new format, generates a unique invocation ID.\n */\n private parseGadgetName(gadgetName: string): { actualName: string; invocationId: string } {\n if (gadgetName.includes(\":\")) {\n // Old format: gadgetName:invocationId - support for backward compatibility\n const parts = gadgetName.split(\":\");\n return { actualName: parts[0], invocationId: parts[1] };\n }\n // New format: just gadget name, generate unique ID\n return { actualName: gadgetName, invocationId: `gadget_${++globalInvocationCounter}` };\n }\n\n /**\n * Extract the error message from a parse error.\n * Preserves full message since the error formatter adds contextual help\n * that benefits from precise, detailed error information.\n */\n private extractParseError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n }\n\n /**\n * Parse parameter string using block format\n */\n private parseParameters(raw: string): {\n parameters?: Record<string, unknown>;\n parseError?: string;\n } {\n // Strip markdown code fences if LLM wrapped the parameters\n const cleaned = stripMarkdownFences(raw);\n\n try {\n return { parameters: parseBlockParams(cleaned, { argPrefix: this.argPrefix }) };\n } catch (error) {\n return { parseError: this.extractParseError(error) };\n }\n }\n\n // Feed a chunk of text and get parsed events\n *feed(chunk: string): Generator<StreamEvent> {\n this.buffer += chunk;\n\n let startIndex = 0;\n while (true) {\n // Find next gadget start marker\n const partStartIndex = this.buffer.indexOf(this.startPrefix, startIndex);\n if (partStartIndex === -1) break;\n\n // Yield any text before the gadget\n const textBefore = this.takeTextUntil(partStartIndex);\n if (textBefore !== undefined) {\n yield { type: \"text\", content: textBefore };\n }\n\n // Extract gadget name (no more invocation ID)\n const metadataStartIndex = partStartIndex + this.startPrefix.length;\n const metadataEndIndex = this.buffer.indexOf(\"\\n\", metadataStartIndex);\n if (metadataEndIndex === -1) break; // Wait for more data\n\n const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);\n\n const contentStartIndex = metadataEndIndex + 1;\n\n let partEndIndex: number;\n let endMarkerLength = 0;\n\n if (gadgetName.includes(\":\")) {\n // Old format - look for old format end marker\n const oldEndMarker = `${this.endPrefix + actualGadgetName}:${invocationId}`;\n partEndIndex = this.buffer.indexOf(oldEndMarker, contentStartIndex);\n if (partEndIndex === -1) break; // Wait for more data\n endMarkerLength = oldEndMarker.length;\n } else {\n // New format - look for end marker OR next start marker (implicit end)\n // If a next gadget starts BEFORE an end marker, use that as implicit terminator\n\n // Look for next gadget start (potential implicit end)\n const nextStartPos = this.buffer.indexOf(this.startPrefix, contentStartIndex);\n\n // Look for proper end marker\n let validEndPos = -1;\n let searchPos = contentStartIndex;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const endPos = this.buffer.indexOf(this.endPrefix, searchPos);\n if (endPos === -1) break;\n\n // Check if this is a standalone end marker or part of old format\n const afterEnd = this.buffer.substring(endPos + this.endPrefix.length);\n if (\n afterEnd.startsWith(\"\\n\") ||\n afterEnd.startsWith(\"\\r\") ||\n afterEnd.startsWith(this.startPrefix) ||\n afterEnd.length === 0\n ) {\n // It's a standalone end marker\n validEndPos = endPos;\n break;\n } else {\n // It might be old format, skip this one\n searchPos = endPos + this.endPrefix.length;\n }\n }\n\n // Decide which terminator to use:\n // - If next start comes before end marker, use next start (implicit end)\n // - Otherwise use the end marker if found\n if (nextStartPos !== -1 && (validEndPos === -1 || nextStartPos < validEndPos)) {\n // Found next gadget start before any end marker - implicit end\n partEndIndex = nextStartPos;\n endMarkerLength = 0; // Don't consume the next start marker\n } else if (validEndPos !== -1) {\n // Found proper end marker\n partEndIndex = validEndPos;\n endMarkerLength = this.endPrefix.length;\n } else {\n // Neither end marker nor next start found - wait for more data\n break;\n }\n }\n\n // Extract parameters\n const parametersRaw = this.buffer.substring(contentStartIndex, partEndIndex).trim();\n\n // Parse parameters according to configured format\n const { parameters, parseError } = this.parseParameters(parametersRaw);\n\n yield {\n type: \"gadget_call\",\n call: {\n gadgetName: actualGadgetName,\n invocationId,\n parametersRaw,\n parameters,\n parseError,\n },\n };\n\n // Move past this gadget\n startIndex = partEndIndex + endMarkerLength;\n\n this.lastReportedTextLength = startIndex;\n }\n\n // Keep unprocessed data in buffer\n if (startIndex > 0) {\n this.buffer = this.buffer.substring(startIndex);\n this.lastReportedTextLength = 0;\n }\n }\n\n // Finalize parsing and return remaining text or incomplete gadgets\n *finalize(): Generator<StreamEvent> {\n // Check if there's an incomplete gadget in the buffer\n const startIndex = this.buffer.indexOf(this.startPrefix, this.lastReportedTextLength);\n\n if (startIndex !== -1) {\n // There's an incomplete gadget - try to parse it\n const textBefore = this.takeTextUntil(startIndex);\n if (textBefore !== undefined) {\n yield { type: \"text\", content: textBefore };\n }\n\n // Extract gadget name\n const metadataStartIndex = startIndex + this.startPrefix.length;\n const metadataEndIndex = this.buffer.indexOf(\"\\n\", metadataStartIndex);\n\n if (metadataEndIndex !== -1) {\n const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);\n const contentStartIndex = metadataEndIndex + 1;\n\n // Extract parameters (everything after the newline to end of buffer)\n const parametersRaw = this.buffer.substring(contentStartIndex).trim();\n\n const { parameters, parseError } = this.parseParameters(parametersRaw);\n\n yield {\n type: \"gadget_call\",\n call: {\n gadgetName: actualGadgetName,\n invocationId,\n parametersRaw: parametersRaw,\n parameters,\n parseError,\n },\n };\n\n return;\n }\n }\n\n // No incomplete gadget - just emit remaining text\n const remainingText = this.takeTextUntil(this.buffer.length);\n if (remainingText !== undefined) {\n yield { type: \"text\", content: remainingText };\n }\n }\n\n // Reset parser state (note: global invocation counter is NOT reset to ensure unique IDs)\n reset(): void {\n this.buffer = \"\";\n this.lastReportedTextLength = 0;\n }\n}\n","import type { ILogObj, Logger } from \"tslog\";\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { parseBlockParams } from \"./block-params.js\";\nimport { GadgetErrorFormatter, type ErrorFormatterOptions } from \"./error-formatter.js\";\nimport { BreakLoopException, HumanInputException, TimeoutException } from \"./exceptions.js\";\nimport { stripMarkdownFences } from \"./parser.js\";\nimport type { GadgetRegistry } from \"./registry.js\";\nimport type { GadgetExecutionResult, ParsedGadgetCall } from \"./types.js\";\n\nexport class GadgetExecutor {\n private readonly logger: Logger<ILogObj>;\n private readonly errorFormatter: GadgetErrorFormatter;\n private readonly argPrefix: string;\n\n constructor(\n private readonly registry: GadgetRegistry,\n private readonly onHumanInputRequired?: (question: string) => Promise<string>,\n logger?: Logger<ILogObj>,\n private readonly defaultGadgetTimeoutMs?: number,\n errorFormatterOptions?: ErrorFormatterOptions,\n ) {\n this.logger = logger ?? createLogger({ name: \"llmist:executor\" });\n this.errorFormatter = new GadgetErrorFormatter(errorFormatterOptions);\n this.argPrefix = errorFormatterOptions?.argPrefix ?? GADGET_ARG_PREFIX;\n }\n\n /**\n * Creates a promise that rejects with a TimeoutException after the specified timeout.\n */\n private createTimeoutPromise(gadgetName: string, timeoutMs: number): Promise<never> {\n return new Promise((_, reject) => {\n setTimeout(() => {\n reject(new TimeoutException(gadgetName, timeoutMs));\n }, timeoutMs);\n });\n }\n\n // Execute a gadget call asynchronously\n async execute(call: ParsedGadgetCall): Promise<GadgetExecutionResult> {\n const startTime = Date.now();\n\n this.logger.debug(\"Executing gadget\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters,\n });\n\n const rawParameters: Record<string, unknown> = call.parameters ?? {};\n let validatedParameters: Record<string, unknown> = rawParameters;\n\n try {\n // Check if gadget exists\n const gadget = this.registry.get(call.gadgetName);\n if (!gadget) {\n this.logger.error(\"Gadget not found\", { gadgetName: call.gadgetName });\n const availableGadgets = this.registry.getNames();\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n error: this.errorFormatter.formatRegistryError(call.gadgetName, availableGadgets),\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Check for parse errors\n if (call.parseError || !call.parameters) {\n this.logger.error(\"Gadget parameter parse error\", {\n gadgetName: call.gadgetName,\n parseError: call.parseError,\n rawParameters: call.parametersRaw,\n });\n const parseErrorMessage = call.parseError ?? \"Failed to parse parameters\";\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: {},\n error: this.errorFormatter.formatParseError(call.gadgetName, parseErrorMessage, gadget),\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Re-parse parameters with schema for type-aware coercion (Approach B)\n // This allows the parser to use the schema to determine correct types\n // (e.g., keeping \"1\" as string when schema expects z.string())\n // Only re-parse if:\n // 1. The raw content is in block format (contains configured arg prefix)\n // 2. Parameters weren't modified by an interceptor (compare with initial parse)\n let schemaAwareParameters: Record<string, unknown> = rawParameters;\n const hasBlockFormat = call.parametersRaw?.includes(this.argPrefix);\n if (gadget.parameterSchema && hasBlockFormat) {\n try {\n const cleanedRaw = stripMarkdownFences(call.parametersRaw);\n\n // First, parse without schema to get what initial parse would produce\n const initialParse = parseBlockParams(cleanedRaw, { argPrefix: this.argPrefix });\n\n // Check if parameters were modified by an interceptor\n // by comparing current parameters with what initial parse produces\n const parametersWereModified = !this.deepEquals(rawParameters, initialParse);\n\n if (parametersWereModified) {\n // Parameters were modified by an interceptor - keep the modifications\n this.logger.debug(\"Parameters modified by interceptor, skipping re-parse\", {\n gadgetName: call.gadgetName,\n });\n schemaAwareParameters = rawParameters;\n } else {\n // Re-parse with schema for type-aware coercion\n schemaAwareParameters = parseBlockParams(cleanedRaw, {\n argPrefix: this.argPrefix,\n schema: gadget.parameterSchema,\n });\n this.logger.debug(\"Re-parsed parameters with schema\", {\n gadgetName: call.gadgetName,\n original: rawParameters,\n schemaAware: schemaAwareParameters,\n });\n }\n } catch (error) {\n // If re-parsing fails, fall back to original parameters\n // This shouldn't happen if initial parse succeeded, but be safe\n this.logger.warn(\"Schema-aware re-parsing failed, using original parameters\", {\n gadgetName: call.gadgetName,\n error: error instanceof Error ? error.message : String(error),\n });\n schemaAwareParameters = rawParameters;\n }\n }\n\n if (gadget.parameterSchema) {\n const validationResult = gadget.parameterSchema.safeParse(schemaAwareParameters);\n if (!validationResult.success) {\n const validationError = this.errorFormatter.formatValidationError(\n call.gadgetName,\n validationResult.error,\n gadget,\n );\n this.logger.error(\"Gadget parameter validation failed\", {\n gadgetName: call.gadgetName,\n issueCount: validationResult.error.issues.length,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: schemaAwareParameters,\n error: validationError,\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n validatedParameters = validationResult.data as Record<string, unknown>;\n } else {\n // No schema - use the schema-aware parameters (which are same as raw if no schema)\n validatedParameters = schemaAwareParameters;\n }\n\n // Determine the timeout for this gadget\n // Priority: gadget's own timeoutMs > defaultGadgetTimeoutMs > no timeout\n const timeoutMs = gadget.timeoutMs ?? this.defaultGadgetTimeoutMs;\n\n // Execute gadget (handle both sync and async)\n let result: string;\n if (timeoutMs && timeoutMs > 0) {\n // Execute with timeout\n this.logger.debug(\"Executing gadget with timeout\", {\n gadgetName: call.gadgetName,\n timeoutMs,\n });\n result = await Promise.race([\n Promise.resolve(gadget.execute(validatedParameters)),\n this.createTimeoutPromise(call.gadgetName, timeoutMs),\n ]);\n } else {\n // Execute without timeout\n result = await Promise.resolve(gadget.execute(validatedParameters));\n }\n\n const executionTimeMs = Date.now() - startTime;\n this.logger.info(\"Gadget executed successfully\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n executionTimeMs,\n });\n\n this.logger.debug(\"Gadget result\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result,\n executionTimeMs,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result,\n executionTimeMs,\n };\n } catch (error) {\n // Check if this is a BreakLoopException\n if (error instanceof BreakLoopException) {\n this.logger.info(\"Gadget requested loop termination\", {\n gadgetName: call.gadgetName,\n message: error.message,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result: error.message,\n breaksLoop: true,\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Check if this is a TimeoutException\n if (error instanceof TimeoutException) {\n this.logger.error(\"Gadget execution timed out\", {\n gadgetName: call.gadgetName,\n timeoutMs: error.timeoutMs,\n executionTimeMs: Date.now() - startTime,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: error.message,\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Check if this is a HumanInputException\n if (error instanceof HumanInputException) {\n this.logger.info(\"Gadget requested human input\", {\n gadgetName: call.gadgetName,\n question: error.question,\n });\n\n // If callback is provided, call it and wait for answer\n if (this.onHumanInputRequired) {\n try {\n const answer = await this.onHumanInputRequired(error.question);\n this.logger.debug(\"Human input received\", {\n gadgetName: call.gadgetName,\n answerLength: answer.length,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result: answer,\n executionTimeMs: Date.now() - startTime,\n };\n } catch (inputError) {\n this.logger.error(\"Human input callback error\", {\n gadgetName: call.gadgetName,\n error: inputError instanceof Error ? inputError.message : String(inputError),\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: inputError instanceof Error ? inputError.message : String(inputError),\n executionTimeMs: Date.now() - startTime,\n };\n }\n }\n\n // No callback - return error since we can't get human input\n this.logger.warn(\"Human input required but no callback provided\", {\n gadgetName: call.gadgetName,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: \"Human input required but not available (stdin is not interactive)\",\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n const executionTimeMs = Date.now() - startTime;\n this.logger.error(\"Gadget execution failed\", {\n gadgetName: call.gadgetName,\n error: error instanceof Error ? error.message : String(error),\n executionTimeMs,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: error instanceof Error ? error.message : String(error),\n executionTimeMs,\n };\n }\n }\n\n // Execute multiple gadget calls in parallel\n async executeAll(calls: ParsedGadgetCall[]): Promise<GadgetExecutionResult[]> {\n return Promise.all(calls.map((call) => this.execute(call)));\n }\n\n /**\n * Deep equality check for objects/arrays.\n * Used to detect if parameters were modified by an interceptor.\n */\n private deepEquals(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a === null || b === null) return a === b;\n if (typeof a !== typeof b) return false;\n\n if (typeof a !== \"object\") return a === b;\n\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n return a.every((val, i) => this.deepEquals(val, b[i]));\n }\n\n const aObj = a as Record<string, unknown>;\n const bObj = b as Record<string, unknown>;\n\n const aKeys = Object.keys(aObj);\n const bKeys = Object.keys(bObj);\n\n if (aKeys.length !== bKeys.length) return false;\n\n return aKeys.every((key) => this.deepEquals(aObj[key], bObj[key]));\n }\n}\n","/**\n * StreamProcessor: The heart of the new hooks architecture.\n *\n * Replaces the complex wiring between Agent, ResponseProcessor, and GadgetRuntime.\n * Owns ALL stream processing and hook coordination with a clean, predictable flow.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMStreamChunk, TokenUsage } from \"../core/options.js\";\nimport { GadgetExecutor } from \"../gadgets/executor.js\";\nimport { StreamParser } from \"../gadgets/parser.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { GadgetExecutionResult, ParsedGadgetCall, StreamEvent } from \"../gadgets/types.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport {\n validateAfterGadgetExecutionAction,\n validateBeforeGadgetExecutionAction,\n} from \"./hook-validators.js\";\nimport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AgentHooks,\n BeforeGadgetExecutionAction,\n ChunkInterceptorContext,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetStartContext,\n} from \"./hooks.js\";\n\n/**\n * Configuration for the StreamProcessor.\n */\nexport interface StreamProcessorOptions {\n /** Current iteration number */\n iteration: number;\n\n /** Gadget registry for execution */\n registry: GadgetRegistry;\n\n /** Custom gadget start prefix */\n gadgetStartPrefix?: string;\n\n /** Custom gadget end prefix */\n gadgetEndPrefix?: string;\n\n /** Custom argument prefix for block format */\n gadgetArgPrefix?: string;\n\n /** Hooks for lifecycle events */\n hooks?: AgentHooks;\n\n /** Logger instance */\n logger?: Logger<ILogObj>;\n\n /** Callback for human input */\n onHumanInputRequired?: (question: string) => Promise<string>;\n\n /** Whether to stop on gadget errors */\n stopOnGadgetError?: boolean;\n\n /** Custom error continuation logic */\n shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n\n /** Default gadget timeout */\n defaultGadgetTimeoutMs?: number;\n}\n\n/**\n * Result of stream processing.\n */\nexport interface StreamProcessingResult {\n /** All emitted events */\n outputs: StreamEvent[];\n\n /** Whether the loop should break */\n shouldBreakLoop: boolean;\n\n /** Whether any gadgets were executed */\n didExecuteGadgets: boolean;\n\n /** LLM finish reason */\n finishReason: string | null;\n\n /** Token usage (including cached token counts when available) */\n usage?: TokenUsage;\n\n /** The raw accumulated response text */\n rawResponse: string;\n\n /** The final message (after interceptors) */\n finalMessage: string;\n}\n\n/**\n * StreamProcessor: Coordinates all stream processing and hook execution.\n *\n * Execution order:\n * 1. Raw chunk arrives from LLM\n * 2. Interceptor: interceptRawChunk (transform raw text)\n * 3. Observer: onStreamChunk (logging)\n * 4. Parse for gadgets\n * 5. If gadget found:\n * a. Interceptor: interceptGadgetParameters (transform params)\n * b. Controller: beforeGadgetExecution (can skip)\n * c. Observer: onGadgetExecutionStart\n * d. Execute gadget\n * e. Interceptor: interceptGadgetResult (transform result)\n * f. Controller: afterGadgetExecution (can provide fallback)\n * g. Observer: onGadgetExecutionComplete\n * 6. If text chunk:\n * a. Interceptor: interceptTextChunk (transform display text)\n * b. Yield to user\n * 7. Stream complete\n * 8. Interceptor: interceptAssistantMessage (transform final message)\n */\nexport class StreamProcessor {\n private readonly iteration: number;\n private readonly registry: GadgetRegistry;\n private readonly hooks: AgentHooks;\n private readonly logger: Logger<ILogObj>;\n private readonly parser: StreamParser;\n private readonly executor: GadgetExecutor;\n private readonly stopOnGadgetError: boolean;\n private readonly shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n\n private accumulatedText = \"\";\n private shouldStopExecution = false;\n private observerFailureCount = 0;\n\n constructor(options: StreamProcessorOptions) {\n this.iteration = options.iteration;\n this.registry = options.registry;\n this.hooks = options.hooks ?? {};\n this.logger = options.logger ?? createLogger({ name: \"llmist:stream-processor\" });\n this.stopOnGadgetError = options.stopOnGadgetError ?? true;\n this.shouldContinueAfterError = options.shouldContinueAfterError;\n\n this.parser = new StreamParser({\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n argPrefix: options.gadgetArgPrefix,\n });\n\n this.executor = new GadgetExecutor(\n options.registry,\n options.onHumanInputRequired,\n this.logger.getSubLogger({ name: \"executor\" }),\n options.defaultGadgetTimeoutMs,\n { argPrefix: options.gadgetArgPrefix },\n );\n }\n\n /**\n * Process an LLM stream and return structured results.\n */\n async process(stream: AsyncIterable<LLMStreamChunk>): Promise<StreamProcessingResult> {\n const outputs: StreamEvent[] = [];\n let finishReason: string | null = null;\n let usage: TokenUsage | undefined;\n let didExecuteGadgets = false;\n let shouldBreakLoop = false;\n\n // Process stream chunks\n for await (const chunk of stream) {\n // Capture metadata\n if (chunk.finishReason) finishReason = chunk.finishReason;\n if (chunk.usage) usage = chunk.usage;\n\n // Process text content if present\n let processedChunk = \"\";\n if (chunk.text) {\n // Step 1: Interceptor - Transform raw chunk\n processedChunk = chunk.text;\n if (this.hooks.interceptors?.interceptRawChunk) {\n const context: ChunkInterceptorContext = {\n iteration: this.iteration,\n accumulatedText: this.accumulatedText,\n logger: this.logger,\n };\n const intercepted = this.hooks.interceptors.interceptRawChunk(processedChunk, context);\n if (intercepted === null) {\n // Chunk suppressed\n processedChunk = \"\";\n } else {\n processedChunk = intercepted;\n }\n }\n\n // Accumulate text\n if (processedChunk) {\n this.accumulatedText += processedChunk;\n }\n }\n\n // Step 2: Observer - Observe chunk (called for text OR usage updates)\n if (this.hooks.observers?.onStreamChunk && (processedChunk || chunk.usage)) {\n const chunkObservers: Array<() => void | Promise<void>> = [];\n chunkObservers.push(async () => {\n const context: ObserveChunkContext = {\n iteration: this.iteration,\n rawChunk: processedChunk,\n accumulatedText: this.accumulatedText,\n usage,\n logger: this.logger,\n };\n await this.hooks.observers!.onStreamChunk!(context);\n });\n await this.runObserversInParallel(chunkObservers);\n }\n\n // Skip further processing if no text\n if (!processedChunk) {\n continue;\n }\n\n // Step 3: Parse and process events\n for (const event of this.parser.feed(processedChunk)) {\n const processedEvents = await this.processEvent(event);\n outputs.push(...processedEvents);\n\n // Check if any gadget was executed\n if (processedEvents.some((e) => e.type === \"gadget_result\")) {\n didExecuteGadgets = true;\n }\n\n // Check for loop termination signals\n for (const evt of processedEvents) {\n if (evt.type === \"gadget_result\" && evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n\n // Break if we should stop execution\n if (this.shouldStopExecution) {\n this.logger.info(\"Breaking from LLM stream due to gadget error\");\n break;\n }\n }\n\n // Finalize parsing\n if (!this.shouldStopExecution) {\n for (const event of this.parser.finalize()) {\n const processedEvents = await this.processEvent(event);\n outputs.push(...processedEvents);\n\n if (processedEvents.some((e) => e.type === \"gadget_result\")) {\n didExecuteGadgets = true;\n }\n\n for (const evt of processedEvents) {\n if (evt.type === \"gadget_result\" && evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n }\n\n // Step 4: Interceptor - Transform final message\n let finalMessage = this.accumulatedText;\n if (this.hooks.interceptors?.interceptAssistantMessage) {\n const context: MessageInterceptorContext = {\n iteration: this.iteration,\n rawResponse: this.accumulatedText,\n logger: this.logger,\n };\n finalMessage = this.hooks.interceptors.interceptAssistantMessage(finalMessage, context);\n }\n\n return {\n outputs,\n shouldBreakLoop,\n didExecuteGadgets,\n finishReason,\n usage,\n rawResponse: this.accumulatedText,\n finalMessage,\n };\n }\n\n /**\n * Process a single parsed event (text or gadget call).\n */\n private async processEvent(event: StreamEvent): Promise<StreamEvent[]> {\n if (event.type === \"text\") {\n return this.processTextEvent(event);\n } else if (event.type === \"gadget_call\") {\n return this.processGadgetCall(event.call);\n }\n return [event];\n }\n\n /**\n * Process a text event through interceptors.\n */\n private async processTextEvent(event: { type: \"text\"; content: string }): Promise<StreamEvent[]> {\n let content = event.content;\n\n // Interceptor: Transform text chunk\n if (this.hooks.interceptors?.interceptTextChunk) {\n const context: ChunkInterceptorContext = {\n iteration: this.iteration,\n accumulatedText: this.accumulatedText,\n logger: this.logger,\n };\n const intercepted = this.hooks.interceptors.interceptTextChunk(content, context);\n if (intercepted === null) {\n // Chunk suppressed\n return [];\n }\n content = intercepted;\n }\n\n return [{ type: \"text\", content }];\n }\n\n /**\n * Process a gadget call through the full lifecycle.\n */\n private async processGadgetCall(call: ParsedGadgetCall): Promise<StreamEvent[]> {\n // Check if we should skip due to previous error\n if (this.shouldStopExecution) {\n this.logger.debug(\"Skipping gadget execution due to previous error\", {\n gadgetName: call.gadgetName,\n });\n return [];\n }\n\n const events: StreamEvent[] = [];\n\n // Emit gadget call event\n events.push({ type: \"gadget_call\", call });\n\n // Check for parse errors\n if (call.parseError) {\n this.logger.warn(\"Gadget has parse error\", {\n gadgetName: call.gadgetName,\n error: call.parseError,\n rawParameters: call.parametersRaw,\n });\n\n const shouldContinue = await this.checkContinueAfterError(\n call.parseError,\n call.gadgetName,\n \"parse\",\n call.parameters,\n );\n\n if (!shouldContinue) {\n this.shouldStopExecution = true;\n }\n }\n\n // Step 1: Interceptor - Transform parameters\n let parameters = call.parameters ?? {};\n if (this.hooks.interceptors?.interceptGadgetParameters) {\n const context: GadgetParameterInterceptorContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n logger: this.logger,\n };\n parameters = this.hooks.interceptors.interceptGadgetParameters(parameters, context);\n }\n\n // Update call with intercepted parameters\n call.parameters = parameters;\n\n // Step 2: Controller - Before execution\n let shouldSkip = false;\n let syntheticResult: string | undefined;\n\n if (this.hooks.controllers?.beforeGadgetExecution) {\n const context: GadgetExecutionControllerContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters,\n logger: this.logger,\n };\n const action: BeforeGadgetExecutionAction =\n await this.hooks.controllers.beforeGadgetExecution(context);\n\n // Validate the action\n validateBeforeGadgetExecutionAction(action);\n\n if (action.action === \"skip\") {\n shouldSkip = true;\n syntheticResult = action.syntheticResult;\n this.logger.info(\"Controller skipped gadget execution\", {\n gadgetName: call.gadgetName,\n });\n }\n }\n\n // Step 3: Observer - Execution start\n const startObservers: Array<() => void | Promise<void>> = [];\n if (this.hooks.observers?.onGadgetExecutionStart) {\n startObservers.push(async () => {\n const context: ObserveGadgetStartContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters,\n logger: this.logger,\n };\n await this.hooks.observers!.onGadgetExecutionStart!(context);\n });\n }\n await this.runObserversInParallel(startObservers);\n\n // Step 4: Execute or use synthetic result\n let result: GadgetExecutionResult;\n if (shouldSkip) {\n result = {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters,\n result: syntheticResult ?? \"Execution skipped\",\n executionTimeMs: 0,\n };\n } else {\n result = await this.executor.execute(call);\n }\n\n const originalResult = result.result;\n\n // Step 5: Interceptor - Transform result\n if (result.result && this.hooks.interceptors?.interceptGadgetResult) {\n const context: GadgetResultInterceptorContext = {\n iteration: this.iteration,\n gadgetName: result.gadgetName,\n invocationId: result.invocationId,\n parameters,\n executionTimeMs: result.executionTimeMs,\n logger: this.logger,\n };\n result.result = this.hooks.interceptors.interceptGadgetResult(result.result, context);\n }\n\n // Step 6: Controller - After execution\n if (this.hooks.controllers?.afterGadgetExecution) {\n const context: AfterGadgetExecutionControllerContext = {\n iteration: this.iteration,\n gadgetName: result.gadgetName,\n invocationId: result.invocationId,\n parameters,\n result: result.result,\n error: result.error,\n executionTimeMs: result.executionTimeMs,\n logger: this.logger,\n };\n const action: AfterGadgetExecutionAction =\n await this.hooks.controllers.afterGadgetExecution(context);\n\n // Validate the action\n validateAfterGadgetExecutionAction(action);\n\n if (action.action === \"recover\" && result.error) {\n this.logger.info(\"Controller recovered from gadget error\", {\n gadgetName: result.gadgetName,\n originalError: result.error,\n });\n result = {\n ...result,\n error: undefined,\n result: action.fallbackResult,\n };\n }\n }\n\n // Step 7: Observer - Execution complete\n const completeObservers: Array<() => void | Promise<void>> = [];\n if (this.hooks.observers?.onGadgetExecutionComplete) {\n completeObservers.push(async () => {\n const context: ObserveGadgetCompleteContext = {\n iteration: this.iteration,\n gadgetName: result.gadgetName,\n invocationId: result.invocationId,\n parameters,\n originalResult,\n finalResult: result.result,\n error: result.error,\n executionTimeMs: result.executionTimeMs,\n breaksLoop: result.breaksLoop,\n logger: this.logger,\n };\n await this.hooks.observers!.onGadgetExecutionComplete!(context);\n });\n }\n await this.runObserversInParallel(completeObservers);\n\n // Emit result event\n events.push({ type: \"gadget_result\", result });\n\n // Check if we should stop after error\n if (result.error) {\n const errorType = this.determineErrorType(call, result);\n const shouldContinue = await this.checkContinueAfterError(\n result.error,\n result.gadgetName,\n errorType,\n result.parameters,\n );\n\n if (!shouldContinue) {\n this.shouldStopExecution = true;\n }\n }\n\n return events;\n }\n\n /**\n * Safely execute an observer, catching and logging any errors.\n * Observers are non-critical, so errors are logged but don't crash the system.\n */\n private async safeObserve(fn: () => void | Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (error) {\n this.observerFailureCount++;\n this.logger.error(\"Observer threw error (ignoring)\", {\n error: error instanceof Error ? error.message : String(error),\n failureCount: this.observerFailureCount,\n });\n }\n }\n\n /**\n * Execute multiple observers in parallel.\n * All observers run concurrently and failures are tracked but don't crash.\n */\n private async runObserversInParallel(\n observers: Array<() => void | Promise<void>>,\n ): Promise<void> {\n if (observers.length === 0) return;\n\n const results = await Promise.allSettled(\n observers.map((observer) => this.safeObserve(observer)),\n );\n\n // All errors are already logged in safeObserve, no need to handle rejected promises\n // This just ensures we wait for all observers to complete\n }\n\n /**\n * Check if execution should continue after an error.\n *\n * Returns true if we should continue processing subsequent gadgets, false if we should stop.\n *\n * Logic:\n * - If custom shouldContinueAfterError is provided, use it\n * - Otherwise, use stopOnGadgetError config:\n * - stopOnGadgetError=true → return false (stop execution)\n * - stopOnGadgetError=false → return true (continue execution)\n */\n private async checkContinueAfterError(\n error: string,\n gadgetName: string,\n errorType: \"parse\" | \"validation\" | \"execution\",\n parameters?: Record<string, unknown>,\n ): Promise<boolean> {\n // Custom error continuation logic takes precedence\n if (this.shouldContinueAfterError) {\n return await this.shouldContinueAfterError({\n error,\n gadgetName,\n errorType,\n parameters,\n });\n }\n\n // Default behavior based on stopOnGadgetError config\n // If stopOnGadgetError=true, we want to STOP (return false to stop continuing)\n // If stopOnGadgetError=false, we want to CONTINUE (return true to keep going)\n const shouldContinue = !this.stopOnGadgetError;\n\n this.logger.debug(\"Checking if should continue after error\", {\n error,\n gadgetName,\n errorType,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinue,\n });\n\n return shouldContinue;\n }\n\n /**\n * Determine the type of error from a gadget execution.\n */\n private determineErrorType(\n call: ParsedGadgetCall,\n result: GadgetExecutionResult,\n ): \"parse\" | \"validation\" | \"execution\" {\n if (call.parseError) {\n return \"parse\";\n }\n if (result.error?.includes(\"Invalid parameters:\")) {\n return \"validation\";\n }\n return \"execution\";\n }\n}\n","/**\n * Agent: Lean orchestrator using the clean hooks architecture.\n *\n * The Agent delegates ALL stream processing and hook coordination to StreamProcessor,\n * making it a simple loop orchestrator with clear responsibilities.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport {\n CHARS_PER_TOKEN,\n DEFAULT_GADGET_OUTPUT_LIMIT,\n DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT,\n FALLBACK_CONTEXT_WINDOW,\n} from \"../core/constants.js\";\nimport { LLMMessageBuilder } from \"../core/messages.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { LLMGenerationOptions } from \"../core/options.js\";\nimport type { PromptConfig } from \"../core/prompt-config.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { StreamEvent, TextOnlyHandler } from \"../gadgets/types.js\";\nimport { createGadgetOutputViewer } from \"../gadgets/output-viewer.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport type { CompactionConfig, CompactionEvent, CompactionStats } from \"./compaction/config.js\";\nimport { CompactionManager } from \"./compaction/manager.js\";\nimport { GadgetOutputStore } from \"./gadget-output-store.js\";\nimport type { GadgetResultInterceptorContext } from \"./hooks.js\";\nimport { type AGENT_INTERNAL_KEY, isValidAgentKey } from \"./agent-internal-key.js\";\nimport { ConversationManager } from \"./conversation-manager.js\";\nimport { type EventHandlers, runWithHandlers } from \"./event-handlers.js\";\nimport {\n validateAfterLLMCallAction,\n validateAfterLLMErrorAction,\n validateBeforeLLMCallAction,\n} from \"./hook-validators.js\";\nimport type {\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n BeforeLLMCallAction,\n LLMCallControllerContext,\n LLMErrorControllerContext,\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n} from \"./hooks.js\";\nimport { StreamProcessor } from \"./stream-processor.js\";\n\n/**\n * Configuration options for the Agent.\n */\nexport interface AgentOptions {\n /** The LLM client */\n client: LLMist;\n\n /** The model ID */\n model: string;\n\n /** System prompt */\n systemPrompt?: string;\n\n /** Initial user prompt (optional if using build()) */\n userPrompt?: string;\n\n /** Maximum iterations */\n maxIterations?: number;\n\n /** Temperature */\n temperature?: number;\n\n /** Gadget registry */\n registry: GadgetRegistry;\n\n /** Logger */\n logger?: Logger<ILogObj>;\n\n /** Clean hooks system */\n hooks?: AgentHooks;\n\n /** Callback for human input */\n onHumanInputRequired?: (question: string) => Promise<string>;\n\n /** Custom gadget start prefix */\n gadgetStartPrefix?: string;\n\n /** Custom gadget end prefix */\n gadgetEndPrefix?: string;\n\n /** Custom gadget argument prefix for block format parameters */\n gadgetArgPrefix?: string;\n\n /** Initial messages */\n initialMessages?: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>;\n\n /** Text-only handler */\n textOnlyHandler?: TextOnlyHandler;\n\n /**\n * Handler for text content that appears alongside gadget calls.\n * When set, text accompanying gadgets will be wrapped as a synthetic gadget call.\n */\n textWithGadgetsHandler?: {\n /** Name of the gadget to use for wrapping text */\n gadgetName: string;\n /** Maps text content to gadget parameters */\n parameterMapping: (text: string) => Record<string, unknown>;\n /** Maps text content to the result string (optional, defaults to text) */\n resultMapping?: (text: string) => string;\n };\n\n /** Stop on gadget error */\n stopOnGadgetError?: boolean;\n\n /** Custom error continuation logic */\n shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n\n /** Default gadget timeout */\n defaultGadgetTimeoutMs?: number;\n\n /** Custom prompt configuration for gadget system prompts */\n promptConfig?: PromptConfig;\n\n /** Enable gadget output limiting (default: true) */\n gadgetOutputLimit?: boolean;\n\n /** Max gadget output as % of model context window (default: 15) */\n gadgetOutputLimitPercent?: number;\n\n /** Context compaction configuration (enabled by default) */\n compactionConfig?: CompactionConfig;\n}\n\n/**\n * Agent: Lean orchestrator that delegates to StreamProcessor.\n *\n * Responsibilities:\n * - Run the main agent loop\n * - Call LLM API\n * - Delegate stream processing to StreamProcessor\n * - Coordinate conversation management\n * - Execute top-level lifecycle controllers\n *\n * NOT responsible for:\n * - Stream parsing (StreamProcessor)\n * - Hook coordination (StreamProcessor)\n * - Gadget execution (StreamProcessor -> GadgetExecutor)\n */\nexport class Agent {\n private readonly client: LLMist;\n private readonly model: string;\n private readonly maxIterations: number;\n private readonly temperature?: number;\n private readonly logger: Logger<ILogObj>;\n private readonly hooks: AgentHooks;\n private readonly conversation: ConversationManager;\n private readonly registry: GadgetRegistry;\n private readonly gadgetStartPrefix?: string;\n private readonly gadgetEndPrefix?: string;\n private readonly gadgetArgPrefix?: string;\n private readonly onHumanInputRequired?: (question: string) => Promise<string>;\n private readonly textOnlyHandler: TextOnlyHandler;\n private readonly textWithGadgetsHandler?: {\n gadgetName: string;\n parameterMapping: (text: string) => Record<string, unknown>;\n resultMapping?: (text: string) => string;\n };\n private readonly stopOnGadgetError: boolean;\n private readonly shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n private readonly defaultGadgetTimeoutMs?: number;\n private readonly defaultMaxTokens?: number;\n private userPromptProvided: boolean;\n\n // Gadget output limiting\n private readonly outputStore: GadgetOutputStore;\n private readonly outputLimitEnabled: boolean;\n private readonly outputLimitCharLimit: number;\n\n // Context compaction\n private readonly compactionManager?: CompactionManager;\n\n /**\n * Creates a new Agent instance.\n * @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.\n */\n constructor(key: typeof AGENT_INTERNAL_KEY, options: AgentOptions) {\n if (!isValidAgentKey(key)) {\n throw new Error(\n \"Agent cannot be instantiated directly. Use LLMist.createAgent() or new AgentBuilder() instead.\",\n );\n }\n\n this.client = options.client;\n this.model = resolveModel(options.model);\n this.maxIterations = options.maxIterations ?? 10;\n this.temperature = options.temperature;\n this.logger = options.logger ?? createLogger({ name: \"llmist:agent\" });\n this.registry = options.registry;\n this.gadgetStartPrefix = options.gadgetStartPrefix;\n this.gadgetEndPrefix = options.gadgetEndPrefix;\n this.gadgetArgPrefix = options.gadgetArgPrefix;\n this.onHumanInputRequired = options.onHumanInputRequired;\n this.textOnlyHandler = options.textOnlyHandler ?? \"terminate\";\n this.textWithGadgetsHandler = options.textWithGadgetsHandler;\n this.stopOnGadgetError = options.stopOnGadgetError ?? true;\n this.shouldContinueAfterError = options.shouldContinueAfterError;\n this.defaultGadgetTimeoutMs = options.defaultGadgetTimeoutMs;\n this.defaultMaxTokens = this.resolveMaxTokensFromCatalog(options.model);\n\n // Initialize gadget output limiting\n this.outputLimitEnabled = options.gadgetOutputLimit ?? DEFAULT_GADGET_OUTPUT_LIMIT;\n this.outputStore = new GadgetOutputStore();\n\n // Calculate character limit from model context window\n const limitPercent = options.gadgetOutputLimitPercent ?? DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT;\n const limits = this.client.modelRegistry.getModelLimits(this.model);\n const contextWindow = limits?.contextWindow ?? FALLBACK_CONTEXT_WINDOW;\n this.outputLimitCharLimit = Math.floor(contextWindow * (limitPercent / 100) * CHARS_PER_TOKEN);\n\n // Auto-register GadgetOutputViewer when limiting is enabled\n if (this.outputLimitEnabled) {\n this.registry.register(\"GadgetOutputViewer\", createGadgetOutputViewer(this.outputStore));\n }\n\n // Merge output limiter interceptor into hooks\n this.hooks = this.mergeOutputLimiterHook(options.hooks);\n\n // Build conversation\n const baseBuilder = new LLMMessageBuilder(options.promptConfig);\n if (options.systemPrompt) {\n baseBuilder.addSystem(options.systemPrompt);\n }\n\n baseBuilder.addGadgets(this.registry.getAll(), {\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n argPrefix: options.gadgetArgPrefix,\n });\n const baseMessages = baseBuilder.build();\n\n const initialMessages = (options.initialMessages ?? []).map((message) => ({\n role: message.role,\n content: message.content,\n }));\n\n this.conversation = new ConversationManager(baseMessages, initialMessages, {\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n argPrefix: options.gadgetArgPrefix,\n });\n this.userPromptProvided = !!options.userPrompt;\n if (options.userPrompt) {\n this.conversation.addUserMessage(options.userPrompt);\n }\n\n // Initialize context compaction (enabled by default)\n const compactionEnabled = options.compactionConfig?.enabled ?? true;\n if (compactionEnabled) {\n this.compactionManager = new CompactionManager(\n this.client,\n this.model,\n options.compactionConfig,\n );\n }\n }\n\n /**\n * Get the gadget registry for this agent.\n *\n * Useful for inspecting registered gadgets in tests or advanced use cases.\n *\n * @returns The GadgetRegistry instance\n *\n * @example\n * ```typescript\n * const agent = new AgentBuilder()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator, Weather)\n * .build();\n *\n * // Inspect registered gadgets\n * console.log(agent.getRegistry().getNames()); // ['Calculator', 'Weather']\n * ```\n */\n getRegistry(): GadgetRegistry {\n return this.registry;\n }\n\n /**\n * Manually trigger context compaction.\n *\n * Forces compaction regardless of threshold. Useful for:\n * - Pre-emptive context management before expected long operations\n * - Testing compaction behavior\n *\n * @returns CompactionEvent if compaction was performed, null if not configured or no history\n *\n * @example\n * ```typescript\n * const agent = await LLMist.createAgent()\n * .withModel('sonnet')\n * .withCompaction()\n * .ask('...');\n *\n * // Manually compact before a long operation\n * const event = await agent.compact();\n * if (event) {\n * console.log(`Saved ${event.tokensBefore - event.tokensAfter} tokens`);\n * }\n * ```\n */\n async compact(): Promise<CompactionEvent | null> {\n if (!this.compactionManager) {\n return null;\n }\n // Use -1 to indicate manual (out-of-band) compaction, not part of the normal iteration cycle\n return this.compactionManager.compact(this.conversation, -1);\n }\n\n /**\n * Get compaction statistics.\n *\n * @returns CompactionStats if compaction is enabled, null otherwise\n *\n * @example\n * ```typescript\n * const stats = agent.getCompactionStats();\n * if (stats) {\n * console.log(`Total compactions: ${stats.totalCompactions}`);\n * console.log(`Tokens saved: ${stats.totalTokensSaved}`);\n * console.log(`Current usage: ${stats.currentUsage.percent.toFixed(1)}%`);\n * }\n * ```\n */\n getCompactionStats(): CompactionStats | null {\n return this.compactionManager?.getStats() ?? null;\n }\n\n /**\n * Run the agent loop.\n * Clean, simple orchestration - all complexity is in StreamProcessor.\n *\n * @throws {Error} If no user prompt was provided (when using build() without ask())\n */\n async *run(): AsyncGenerator<StreamEvent> {\n if (!this.userPromptProvided) {\n throw new Error(\n \"No user prompt provided. Use .ask(prompt) instead of .build(), or call agent.run() after providing a prompt.\",\n );\n }\n\n let currentIteration = 0;\n\n this.logger.info(\"Starting agent loop\", {\n model: this.model,\n maxIterations: this.maxIterations,\n });\n\n while (currentIteration < this.maxIterations) {\n this.logger.debug(\"Starting iteration\", { iteration: currentIteration });\n\n try {\n // Check and perform context compaction if needed\n if (this.compactionManager) {\n const compactionEvent = await this.compactionManager.checkAndCompact(\n this.conversation,\n currentIteration,\n );\n if (compactionEvent) {\n this.logger.info(\"Context compacted\", {\n strategy: compactionEvent.strategy,\n tokensBefore: compactionEvent.tokensBefore,\n tokensAfter: compactionEvent.tokensAfter,\n });\n yield { type: \"compaction\", event: compactionEvent } as StreamEvent;\n\n // Observer: Compaction occurred\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onCompaction) {\n await this.hooks.observers.onCompaction({\n iteration: currentIteration,\n event: compactionEvent,\n stats: this.compactionManager!.getStats(),\n logger: this.logger,\n });\n }\n });\n }\n }\n\n // Prepare LLM call options\n let llmOptions: LLMGenerationOptions = {\n model: this.model,\n messages: this.conversation.getMessages(),\n temperature: this.temperature,\n maxTokens: this.defaultMaxTokens,\n };\n\n // Observer: LLM call start\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onLLMCallStart) {\n const context: ObserveLLMCallContext = {\n iteration: currentIteration,\n options: llmOptions,\n logger: this.logger,\n };\n await this.hooks.observers.onLLMCallStart(context);\n }\n });\n\n // Controller: Before LLM call\n if (this.hooks.controllers?.beforeLLMCall) {\n const context: LLMCallControllerContext = {\n iteration: currentIteration,\n maxIterations: this.maxIterations,\n options: llmOptions,\n logger: this.logger,\n };\n const action: BeforeLLMCallAction = await this.hooks.controllers.beforeLLMCall(context);\n\n // Validate the action\n validateBeforeLLMCallAction(action);\n\n if (action.action === \"skip\") {\n this.logger.info(\"Controller skipped LLM call, using synthetic response\");\n // Add synthetic response to conversation\n this.conversation.addAssistantMessage(action.syntheticResponse);\n // Yield as text event\n yield { type: \"text\", content: action.syntheticResponse };\n break;\n } else if (action.action === \"proceed\" && action.modifiedOptions) {\n llmOptions = { ...llmOptions, ...action.modifiedOptions };\n }\n }\n\n // Call LLM\n this.logger.info(\"Calling LLM\", { model: this.model });\n this.logger.silly(\"LLM request details\", {\n model: llmOptions.model,\n temperature: llmOptions.temperature,\n maxTokens: llmOptions.maxTokens,\n messageCount: llmOptions.messages.length,\n messages: llmOptions.messages,\n });\n const stream = this.client.stream(llmOptions);\n\n // Process stream - ALL complexity delegated to StreamProcessor\n const processor = new StreamProcessor({\n iteration: currentIteration,\n registry: this.registry,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n hooks: this.hooks,\n logger: this.logger.getSubLogger({ name: \"stream-processor\" }),\n onHumanInputRequired: this.onHumanInputRequired,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinueAfterError: this.shouldContinueAfterError,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n });\n\n const result = await processor.process(stream);\n\n // Yield all outputs to user\n for (const output of result.outputs) {\n yield output;\n }\n\n this.logger.info(\"LLM response completed\", {\n finishReason: result.finishReason,\n usage: result.usage,\n didExecuteGadgets: result.didExecuteGadgets,\n });\n this.logger.silly(\"LLM response details\", {\n rawResponse: result.rawResponse,\n });\n\n // Observer: LLM call complete\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onLLMCallComplete) {\n const context: ObserveLLMCompleteContext = {\n iteration: currentIteration,\n options: llmOptions,\n finishReason: result.finishReason,\n usage: result.usage,\n rawResponse: result.rawResponse,\n finalMessage: result.finalMessage,\n logger: this.logger,\n };\n await this.hooks.observers.onLLMCallComplete(context);\n }\n });\n\n // Controller: After LLM call\n let finalMessage = result.finalMessage;\n if (this.hooks.controllers?.afterLLMCall) {\n // Count gadget calls in this response\n const gadgetCallCount = result.outputs.filter(\n (output) => output.type === \"gadget_result\",\n ).length;\n\n const context: AfterLLMCallControllerContext = {\n iteration: currentIteration,\n maxIterations: this.maxIterations,\n options: llmOptions,\n finishReason: result.finishReason,\n usage: result.usage,\n finalMessage: result.finalMessage,\n gadgetCallCount,\n logger: this.logger,\n };\n const action: AfterLLMCallAction = await this.hooks.controllers.afterLLMCall(context);\n\n // Validate the action\n validateAfterLLMCallAction(action);\n\n if (action.action === \"modify_and_continue\" || action.action === \"append_and_modify\") {\n finalMessage = action.modifiedMessage;\n }\n\n if (action.action === \"append_messages\" || action.action === \"append_and_modify\") {\n for (const msg of action.messages) {\n if (msg.role === \"user\") {\n this.conversation.addUserMessage(msg.content);\n } else if (msg.role === \"assistant\") {\n this.conversation.addAssistantMessage(msg.content);\n } else if (msg.role === \"system\") {\n // System messages can't be added mid-conversation, treat as user\n this.conversation.addUserMessage(`[System] ${msg.content}`);\n }\n }\n }\n }\n\n // Add gadget results to conversation (if any were executed)\n if (result.didExecuteGadgets) {\n // If configured, wrap accompanying text as a synthetic gadget call (before actual gadgets)\n if (this.textWithGadgetsHandler) {\n const textContent = result.outputs\n .filter((output): output is { type: \"text\"; content: string } => output.type === \"text\")\n .map((output) => output.content)\n .join(\"\");\n\n if (textContent.trim()) {\n const { gadgetName, parameterMapping, resultMapping } = this.textWithGadgetsHandler;\n this.conversation.addGadgetCall(\n gadgetName,\n parameterMapping(textContent),\n resultMapping ? resultMapping(textContent) : textContent,\n );\n }\n }\n\n // Extract and add all gadget results to conversation\n for (const output of result.outputs) {\n if (output.type === \"gadget_result\") {\n const gadgetResult = output.result;\n this.conversation.addGadgetCall(\n gadgetResult.gadgetName,\n gadgetResult.parameters,\n gadgetResult.error ?? gadgetResult.result ?? \"\",\n );\n }\n }\n } else {\n // No gadgets executed - wrap text as synthetic TellUser result\n // This keeps conversation history consistent (gadget-oriented) and\n // helps LLMs stay in the \"gadget invocation\" mindset\n if (finalMessage.trim()) {\n this.conversation.addGadgetCall(\n \"TellUser\",\n { message: finalMessage, done: false, type: \"info\" },\n `ℹ️ ${finalMessage}`,\n );\n }\n // Empty responses: don't add anything, just check if we should continue\n\n // Handle text-only responses\n const shouldBreak = await this.handleTextOnlyResponse(finalMessage);\n if (shouldBreak) {\n break;\n }\n }\n\n // Check if loop should break\n if (result.shouldBreakLoop) {\n this.logger.info(\"Loop terminated by gadget or processor\");\n break;\n }\n } catch (error) {\n // Handle LLM error\n const errorHandled = await this.handleLLMError(error as Error, currentIteration);\n\n // Observer: LLM error\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onLLMCallError) {\n const context: ObserveLLMErrorContext = {\n iteration: currentIteration,\n options: {\n model: this.model,\n messages: this.conversation.getMessages(),\n temperature: this.temperature,\n maxTokens: this.defaultMaxTokens,\n },\n error: error as Error,\n recovered: errorHandled,\n logger: this.logger,\n };\n await this.hooks.observers.onLLMCallError(context);\n }\n });\n\n if (!errorHandled) {\n throw error;\n }\n }\n\n currentIteration++;\n }\n\n this.logger.info(\"Agent loop completed\", {\n totalIterations: currentIteration,\n reason: currentIteration >= this.maxIterations ? \"max_iterations\" : \"natural_completion\",\n });\n }\n\n /**\n * Handle LLM error through controller.\n */\n private async handleLLMError(error: Error, iteration: number): Promise<boolean> {\n this.logger.error(\"LLM call failed\", { error: error.message });\n\n if (this.hooks.controllers?.afterLLMError) {\n const context: LLMErrorControllerContext = {\n iteration,\n options: {\n model: this.model,\n messages: this.conversation.getMessages(),\n temperature: this.temperature,\n maxTokens: this.defaultMaxTokens,\n },\n error,\n logger: this.logger,\n };\n const action: AfterLLMErrorAction = await this.hooks.controllers.afterLLMError(context);\n\n // Validate the action\n validateAfterLLMErrorAction(action);\n\n if (action.action === \"recover\") {\n this.logger.info(\"Controller recovered from LLM error\");\n this.conversation.addAssistantMessage(action.fallbackResponse);\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Handle text-only response (no gadgets called).\n */\n private async handleTextOnlyResponse(_text: string): Promise<boolean> {\n const handler = this.textOnlyHandler;\n\n if (typeof handler === \"string\") {\n switch (handler) {\n case \"terminate\":\n this.logger.info(\"No gadgets called, ending loop\");\n return true;\n case \"acknowledge\":\n this.logger.info(\"No gadgets called, continuing loop\");\n return false;\n case \"wait_for_input\":\n this.logger.info(\"No gadgets called, waiting for input\");\n return true;\n default:\n this.logger.warn(`Unknown text-only strategy: ${handler}, defaulting to terminate`);\n return true;\n }\n }\n\n // For gadget and custom handlers, they would need to be implemented\n // This is simplified for now\n return true;\n }\n\n /**\n * Safely execute an observer, catching and logging any errors.\n */\n private async safeObserve(fn: () => void | Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (error) {\n this.logger.error(\"Observer threw error (ignoring)\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n /**\n * Resolve max tokens from model catalog.\n */\n private resolveMaxTokensFromCatalog(modelId: string): number | undefined {\n const limits = this.client.modelRegistry.getModelLimits(modelId);\n if (limits?.maxOutputTokens !== undefined) {\n return limits.maxOutputTokens;\n }\n\n const separatorIndex = modelId.indexOf(\":\");\n if (separatorIndex === -1) {\n return undefined;\n }\n\n const unprefixedModelId = modelId.slice(separatorIndex + 1).trim();\n if (!unprefixedModelId) {\n return undefined;\n }\n\n return this.client.modelRegistry.getModelLimits(unprefixedModelId)?.maxOutputTokens;\n }\n\n /**\n * Merge the output limiter interceptor into user-provided hooks.\n * The limiter runs first, then chains to any user interceptor.\n */\n private mergeOutputLimiterHook(userHooks?: AgentHooks): AgentHooks {\n if (!this.outputLimitEnabled) {\n return userHooks ?? {};\n }\n\n const limiterInterceptor = (\n result: string,\n ctx: GadgetResultInterceptorContext,\n ): string => {\n // Skip limiting for GadgetOutputViewer itself to avoid recursion\n if (ctx.gadgetName === \"GadgetOutputViewer\") {\n return result;\n }\n\n if (result.length > this.outputLimitCharLimit) {\n const id = this.outputStore.store(ctx.gadgetName, result);\n const lines = result.split(\"\\n\").length;\n const bytes = new TextEncoder().encode(result).length;\n\n this.logger.info(\"Gadget output exceeded limit, stored for browsing\", {\n gadgetName: ctx.gadgetName,\n outputId: id,\n bytes,\n lines,\n charLimit: this.outputLimitCharLimit,\n });\n\n return (\n `[Gadget \"${ctx.gadgetName}\" returned too much data: ` +\n `${bytes.toLocaleString()} bytes, ${lines.toLocaleString()} lines. ` +\n `Use GadgetOutputViewer with id \"${id}\" to read it]`\n );\n }\n\n return result;\n };\n\n // Chain with any user-provided interceptor (limiter runs first)\n const userInterceptor = userHooks?.interceptors?.interceptGadgetResult;\n const chainedInterceptor = userInterceptor\n ? (result: string, ctx: GadgetResultInterceptorContext) =>\n userInterceptor(limiterInterceptor(result, ctx), ctx)\n : limiterInterceptor;\n\n return {\n ...userHooks,\n interceptors: {\n ...userHooks?.interceptors,\n interceptGadgetResult: chainedInterceptor,\n },\n };\n }\n\n /**\n * Run agent with named event handlers (syntactic sugar).\n *\n * Instead of verbose if/else chains, use named handlers for cleaner code.\n *\n * @param handlers - Named event handlers\n *\n * @example\n * ```typescript\n * await agent.runWith({\n * onText: (text) => console.log(\"LLM:\", text),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * onGadgetCall: (call) => console.log(\"Calling:\", call.gadgetName),\n * });\n * ```\n */\n async runWith(handlers: EventHandlers): Promise<void> {\n return runWithHandlers(this.run(), handlers);\n }\n}\n","/**\n * Anthropic Claude Model Specifications\n *\n * Model data for Anthropic Claude models including Sonnet and Opus variants\n * with their specifications, pricing, and capabilities.\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const ANTHROPIC_MODELS: ModelSpec[] = [\n {\n provider: \"anthropic\",\n modelId: \"claude-sonnet-4-5-20250929\",\n displayName: \"Claude Sonnet 4.5\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 3.0,\n output: 15.0,\n cachedInput: 0.3,\n cacheWriteInput: 3.75,\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-09-29\",\n notes: \"Smartest model for complex agents and coding. Extended thinking. 1M context in beta.\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-haiku-4-5-20251001\",\n displayName: \"Claude Haiku 4.5\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 1.0,\n output: 5.0,\n cachedInput: 0.1,\n cacheWriteInput: 1.25,\n },\n knowledgeCutoff: \"2025-02\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-10-01\",\n notes:\n \"Fastest model with near-frontier intelligence. Excellent for coding (73.3% SWE-bench).\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-sonnet-4-20250514\",\n displayName: \"Claude Sonnet 4\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 3.0,\n output: 15.0,\n cachedInput: 0.3,\n cacheWriteInput: 3.75,\n },\n knowledgeCutoff: \"2025-03\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-05-14\",\n notes: \"High performance with vision and extended thinking\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-3-7-sonnet-20250219\",\n displayName: \"Claude Sonnet 3.7\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 3.0,\n output: 15.0,\n cachedInput: 0.3,\n cacheWriteInput: 3.75,\n },\n knowledgeCutoff: \"2024-11\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 3\",\n releaseDate: \"2025-02-19\",\n notes: \"Legacy model - consider upgrading to Claude 4 family\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-opus-4-1-20250805\",\n displayName: \"Claude Opus 4.1\",\n contextWindow: 200_000,\n maxOutputTokens: 32_000,\n pricing: {\n input: 15.0,\n output: 75.0,\n cachedInput: 1.5,\n cacheWriteInput: 18.75,\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-08-05\",\n notes: \"Exceptional for specialized reasoning tasks. Extended thinking support.\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-opus-4-20250514\",\n displayName: \"Claude Opus 4\",\n contextWindow: 200_000,\n maxOutputTokens: 32_000,\n pricing: {\n input: 15.0,\n output: 75.0,\n cachedInput: 1.5,\n cacheWriteInput: 18.75,\n },\n knowledgeCutoff: \"2025-03\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-05-14\",\n notes: \"Legacy Opus model - consider Opus 4.1 for improved reasoning\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-3-5-haiku-20241022\",\n displayName: \"Claude Haiku 3.5\",\n contextWindow: 200_000,\n maxOutputTokens: 8_192,\n pricing: {\n input: 0.8,\n output: 4.0,\n cachedInput: 0.08,\n cacheWriteInput: 1.0,\n },\n knowledgeCutoff: \"2024-07\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n },\n metadata: {\n family: \"Claude 3\",\n releaseDate: \"2024-10-22\",\n notes: \"Legacy model - upgrade to Haiku 4.5 for better performance\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-3-haiku-20240307\",\n displayName: \"Claude Haiku 3\",\n contextWindow: 200_000,\n maxOutputTokens: 4_096,\n pricing: {\n input: 0.25,\n output: 1.25,\n cachedInput: 0.025,\n cacheWriteInput: 0.3125,\n },\n knowledgeCutoff: \"2023-08\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n },\n metadata: {\n family: \"Claude 3\",\n releaseDate: \"2024-03-07\",\n notes: \"Legacy model - upgrade to Haiku 4.5 for better performance\",\n },\n },\n // Modern aliases (recommended by Anthropic)\n {\n provider: \"anthropic\",\n modelId: \"claude-haiku-4-5\",\n displayName: \"Claude Haiku 4.5\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 1.0,\n output: 5.0,\n cachedInput: 0.1,\n cacheWriteInput: 1.25,\n },\n knowledgeCutoff: \"2025-02\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-10-01\",\n notes: \"Alias for claude-haiku-4-5-20251001. Fastest model with near-frontier intelligence.\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-sonnet-4-5\",\n displayName: \"Claude Sonnet 4.5\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 3.0,\n output: 15.0,\n cachedInput: 0.3,\n cacheWriteInput: 3.75,\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-09-29\",\n notes: \"Alias for claude-sonnet-4-5-20250929. Smartest model for complex agents and coding.\",\n },\n },\n {\n provider: \"anthropic\",\n modelId: \"claude-opus-4-5\",\n displayName: \"Claude Opus 4.5\",\n contextWindow: 200_000,\n maxOutputTokens: 64_000,\n pricing: {\n input: 5.0,\n output: 25.0,\n cachedInput: 0.5,\n cacheWriteInput: 6.25,\n },\n knowledgeCutoff: \"2025-03\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n },\n metadata: {\n family: \"Claude 4\",\n releaseDate: \"2025-11-24\",\n notes: \"Alias for claude-opus-4-5-20251124. Most powerful model for coding and computer use.\",\n },\n },\n];\n","/**\n * Base Provider Adapter\n *\n * Abstract base class for provider adapters that implements the Template Method pattern.\n * This class defines the skeleton of the streaming algorithm, leaving provider-specific\n * details to be implemented by concrete subclasses.\n *\n * The streaming workflow consists of four main steps:\n * 1. Prepare messages (optional transformation for provider-specific requirements)\n * 2. Build the request payload (provider-specific formatting)\n * 3. Execute the stream request (call the provider's SDK)\n * 4. Wrap the stream (transform provider-specific chunks into universal format)\n */\n\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport type { ProviderAdapter } from \"./provider.js\";\n\nexport abstract class BaseProviderAdapter implements ProviderAdapter {\n abstract readonly providerId: string;\n\n constructor(protected readonly client: unknown) {}\n\n abstract supports(descriptor: ModelDescriptor): boolean;\n\n /**\n * Optionally provide model specifications for this provider.\n * This allows the model registry to discover available models and their capabilities.\n */\n getModelSpecs?(): ModelSpec[];\n\n /**\n * Template method that defines the skeleton of the streaming algorithm.\n * This orchestrates the four-step process without dictating provider-specific details.\n */\n async *stream(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n spec?: ModelSpec,\n ): LLMStream {\n // Step 1: Prepare messages (can be overridden for special cases like Gemini)\n const preparedMessages = this.prepareMessages(options.messages);\n\n // Step 2: Build the provider-specific request payload\n const payload = this.buildRequestPayload(options, descriptor, spec, preparedMessages);\n\n // Step 3: Execute the stream request using the provider's SDK\n const rawStream = await this.executeStreamRequest(payload);\n\n // Step 4: Transform the provider-specific stream into universal format\n yield* this.wrapStream(rawStream);\n }\n\n /**\n * Prepare messages for the request.\n * Default implementation returns messages unchanged.\n * Override this to implement provider-specific message transformations\n * (e.g., Gemini's consecutive message merging, Anthropic's system message extraction).\n *\n * @param messages - The input messages\n * @returns Prepared messages\n */\n protected prepareMessages(messages: LLMMessage[]): LLMMessage[] {\n return messages;\n }\n\n /**\n * Build the provider-specific request payload.\n * This method must be implemented by each concrete provider.\n *\n * @param options - The generation options\n * @param descriptor - The model descriptor\n * @param spec - Optional model specification with metadata\n * @param messages - The prepared messages\n * @returns Provider-specific payload ready for the API call\n */\n protected abstract buildRequestPayload(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n spec: ModelSpec | undefined,\n messages: LLMMessage[],\n ): unknown;\n\n /**\n * Execute the stream request using the provider's SDK.\n * This method must be implemented by each concrete provider.\n *\n * @param payload - The provider-specific payload\n * @returns An async iterable of provider-specific chunks\n */\n protected abstract executeStreamRequest(payload: unknown): Promise<AsyncIterable<unknown>>;\n\n /**\n * Wrap the provider-specific stream into the universal LLMStream format.\n * This method must be implemented by each concrete provider.\n *\n * @param rawStream - The provider-specific stream\n * @returns Universal LLMStream\n */\n protected abstract wrapStream(rawStream: AsyncIterable<unknown>): LLMStream;\n}\n","/**\n * Provider-specific constants and default values.\n *\n * This file centralizes magic numbers and hardcoded defaults to improve\n * maintainability and documentation. Each constant includes a comment\n * explaining its purpose and rationale.\n */\n\n/**\n * Default maximum output tokens for Anthropic models.\n *\n * Rationale: Most Anthropic models (Claude 3 Opus, Sonnet, Haiku) support\n * at least 4096 output tokens. This is used as a fallback when:\n * - The user doesn't specify maxTokens explicitly\n * - The model spec doesn't define maxOutputTokens\n *\n * Note: Anthropic's API requires the max_tokens parameter, unlike OpenAI\n * which can infer it from the context window. This default ensures the API\n * call succeeds while allowing substantial output.\n *\n * Reference: https://docs.anthropic.com/en/docs/about-claude/models\n */\nexport const ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS = 4096;\n\n/**\n * Character-to-token ratio for fallback token estimation.\n *\n * Rationale: When native token counting APIs fail, we estimate tokens using\n * a rough heuristic of 4 characters per token. This is based on empirical\n * observations across multiple LLM providers:\n * - OpenAI's GPT models average ~4 chars/token for English text\n * - Anthropic's Claude models have similar characteristics\n * - Gemini models also approximate this ratio\n *\n * This is intentionally conservative to avoid underestimating token usage.\n * While not perfectly accurate, it provides a reasonable fallback when\n * precise tokenization is unavailable.\n *\n * Reference: https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them\n */\nexport const FALLBACK_CHARS_PER_TOKEN = 4;\n\n/**\n * OpenAI message structure overhead in tokens.\n *\n * Rationale: OpenAI's chat completion format adds tokens for message\n * boundaries and structure. Each message follows the pattern:\n * <im_start>{role/name}\\n{content}<im_end>\\n\n *\n * This overhead accounts for:\n * - <im_start> token\n * - Role/name field tokens\n * - Newline and separator tokens\n * - <im_end> token\n *\n * The value of 4 tokens per message is based on OpenAI's official\n * tokenization examples and testing.\n *\n * Reference: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n */\nexport const OPENAI_MESSAGE_OVERHEAD_TOKENS = 4;\n\n/**\n * OpenAI reply priming overhead in tokens.\n *\n * Rationale: Every OpenAI assistant reply is primed with the tokens:\n * <im_start>assistant\\n\n *\n * This adds 2 tokens to the total input token count before the actual\n * response generation begins. This is part of OpenAI's message formatting\n * and must be accounted for in accurate token counting.\n *\n * Reference: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n */\nexport const OPENAI_REPLY_PRIMING_TOKENS = 2;\n\n/**\n * OpenAI name field overhead in tokens.\n *\n * Rationale: When a message includes a \"name\" field (for identifying the\n * speaker in multi-party conversations), OpenAI's format adds 1 extra\n * token beyond the name's actual token count.\n *\n * This accounts for the separator between the role and name fields.\n *\n * Reference: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n */\nexport const OPENAI_NAME_FIELD_OVERHEAD_TOKENS = 1;\n","/**\n * Common utility functions shared across provider implementations\n */\n\n/**\n * Safely read an environment variable\n * @param key - The environment variable key to read\n * @returns The value if found and valid, undefined otherwise\n */\nexport function readEnvVar(key: string): string | undefined {\n if (typeof process === \"undefined\" || typeof process.env === \"undefined\") {\n return undefined;\n }\n const value = process.env[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\n/**\n * Check if a value is a non-empty string\n * @param value - The value to check\n * @returns true if the value is a non-empty string, false otherwise\n */\nexport function isNonEmpty(value: string | undefined): value is string {\n return typeof value === \"string\" && value.trim().length > 0;\n}\n\n/**\n * Generic factory function for creating provider instances from environment variables\n * @param envVarName - Name of the environment variable containing the API key\n * @param ClientClass - Constructor for the SDK client\n * @param ProviderClass - Constructor for the provider adapter\n * @param clientOptions - Optional additional options to pass to the client constructor\n * @returns Provider instance or null if API key is not set\n */\nexport function createProviderFromEnv<TClient, TProvider>(\n envVarName: string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ClientClass: new (config: any) => TClient,\n ProviderClass: new (client: TClient) => TProvider,\n clientOptions?: Record<string, unknown>,\n): TProvider | null {\n const apiKey = readEnvVar(envVarName);\n if (!isNonEmpty(apiKey)) {\n return null;\n }\n\n // Create client with API key and optional config\n const client = new ClientClass({ apiKey: apiKey.trim(), ...clientOptions });\n\n return new ProviderClass(client);\n}\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n MessageCreateParamsStreaming,\n MessageStreamEvent,\n} from \"@anthropic-ai/sdk/resources/messages\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport { ANTHROPIC_MODELS } from \"./anthropic-models.js\";\nimport { BaseProviderAdapter } from \"./base-provider.js\";\nimport { ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS, FALLBACK_CHARS_PER_TOKEN } from \"./constants.js\";\nimport { createProviderFromEnv } from \"./utils.js\";\n\nexport class AnthropicMessagesProvider extends BaseProviderAdapter {\n readonly providerId = \"anthropic\" as const;\n\n supports(descriptor: ModelDescriptor): boolean {\n return descriptor.provider === this.providerId;\n }\n\n getModelSpecs() {\n return ANTHROPIC_MODELS;\n }\n\n protected buildRequestPayload(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n spec: ModelSpec | undefined,\n messages: LLMMessage[],\n ): MessageCreateParamsStreaming {\n const systemMessages = messages.filter((message) => message.role === \"system\");\n\n // System message as array of text blocks with cache_control on last block\n // This enables Anthropic's prompt caching for the system prompt\n const system =\n systemMessages.length > 0\n ? systemMessages.map((m, index) => ({\n type: \"text\" as const,\n text: m.content,\n // Add cache_control to the LAST system message block\n ...(index === systemMessages.length - 1\n ? { cache_control: { type: \"ephemeral\" as const } }\n : {}),\n }))\n : undefined;\n\n const nonSystemMessages = messages.filter(\n (message): message is LLMMessage & { role: \"user\" | \"assistant\" } =>\n message.role !== \"system\",\n );\n\n // Find index of last user message for cache breakpoint\n const lastUserIndex = nonSystemMessages.reduce(\n (lastIdx, msg, idx) => (msg.role === \"user\" ? idx : lastIdx),\n -1,\n );\n\n // Build conversation with cache_control on the last user message\n // This caches the conversation history prefix for multi-turn efficiency\n const conversation = nonSystemMessages.map((message, index) => ({\n role: message.role,\n content: [\n {\n type: \"text\" as const,\n text: message.content,\n // Add cache_control to the LAST user message\n ...(message.role === \"user\" && index === lastUserIndex\n ? { cache_control: { type: \"ephemeral\" as const } }\n : {}),\n },\n ],\n }));\n\n // Anthropic requires max_tokens, so use a smart default if not specified\n // Use model's max from the passed spec, or fall back to the default constant\n const defaultMaxTokens = spec?.maxOutputTokens ?? ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS;\n\n const payload: MessageCreateParamsStreaming = {\n model: descriptor.name,\n system,\n messages: conversation,\n max_tokens: options.maxTokens ?? defaultMaxTokens,\n temperature: options.temperature,\n top_p: options.topP,\n stop_sequences: options.stopSequences,\n stream: true,\n ...options.extra,\n };\n\n return payload;\n }\n\n protected async executeStreamRequest(\n payload: MessageCreateParamsStreaming,\n ): Promise<AsyncIterable<MessageStreamEvent>> {\n const client = this.client as Anthropic;\n const stream = await client.messages.create(payload);\n return stream as unknown as AsyncIterable<MessageStreamEvent>;\n }\n\n protected async *wrapStream(iterable: AsyncIterable<unknown>): LLMStream {\n const stream = iterable as AsyncIterable<MessageStreamEvent>;\n let inputTokens = 0;\n let cachedInputTokens = 0;\n let cacheCreationInputTokens = 0;\n\n for await (const event of stream) {\n // Track and yield input tokens from message_start event\n // Anthropic returns cache_read_input_tokens and cache_creation_input_tokens\n if (event.type === \"message_start\") {\n const usage = event.message.usage as {\n input_tokens: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n // Total input tokens includes uncached + cached reads + cache writes\n cachedInputTokens = usage.cache_read_input_tokens ?? 0;\n cacheCreationInputTokens = usage.cache_creation_input_tokens ?? 0;\n inputTokens = usage.input_tokens + cachedInputTokens + cacheCreationInputTokens;\n // Yield early so hooks can access input tokens before text streams\n yield {\n text: \"\",\n usage: {\n inputTokens,\n outputTokens: 0,\n totalTokens: inputTokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n },\n rawEvent: event,\n };\n continue;\n }\n\n if (event.type === \"content_block_delta\" && event.delta.type === \"text_delta\") {\n yield { text: event.delta.text ?? \"\", rawEvent: event };\n continue;\n }\n\n if (event.type === \"message_delta\") {\n const usage = event.usage\n ? {\n inputTokens,\n outputTokens: event.usage.output_tokens,\n totalTokens: inputTokens + event.usage.output_tokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n }\n : undefined;\n\n if (event.delta.stop_reason || usage) {\n yield {\n text: \"\",\n finishReason: event.delta.stop_reason ?? undefined,\n usage,\n rawEvent: event,\n };\n }\n continue;\n }\n\n if (event.type === \"message_stop\") {\n yield { text: \"\", finishReason: \"stop\", rawEvent: event };\n }\n }\n }\n\n /**\n * Count tokens in messages using Anthropic's native token counting API.\n *\n * This method provides accurate token estimation for Anthropic models by:\n * - Using the native messages.countTokens() API\n * - Properly handling system messages and conversation structure\n * - Transforming messages to Anthropic's expected format\n *\n * @param messages - The messages to count tokens for\n * @param descriptor - Model descriptor containing the model name\n * @param _spec - Optional model specification (currently unused)\n * @returns Promise resolving to the estimated input token count\n *\n * @throws Never throws - falls back to character-based estimation (4 chars/token) on error\n *\n * @example\n * ```typescript\n * const count = await provider.countTokens(\n * [{ role: \"user\", content: \"Hello!\" }],\n * { provider: \"anthropic\", name: \"claude-3-5-sonnet-20241022\" }\n * );\n * ```\n */\n async countTokens(\n messages: LLMMessage[],\n descriptor: ModelDescriptor,\n _spec?: ModelSpec,\n ): Promise<number> {\n const client = this.client as Anthropic;\n\n // Extract system messages and conversation messages\n const systemMessages = messages.filter((message) => message.role === \"system\");\n const system =\n systemMessages.length > 0 ? systemMessages.map((m) => m.content).join(\"\\n\\n\") : undefined;\n\n const conversation = messages\n .filter(\n (message): message is LLMMessage & { role: \"user\" | \"assistant\" } =>\n message.role !== \"system\",\n )\n .map((message) => ({\n role: message.role,\n content: [\n {\n type: \"text\" as const,\n text: message.content,\n },\n ],\n }));\n\n try {\n // Use the native token counting API\n const response = await client.messages.countTokens({\n model: descriptor.name,\n messages: conversation,\n ...(system ? { system } : {}),\n });\n\n return response.input_tokens;\n } catch (error) {\n // Log the error for debugging\n console.warn(\n `Token counting failed for ${descriptor.name}, using fallback estimation:`,\n error,\n );\n // Fallback to rough estimation if API fails\n const totalChars = messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0);\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN);\n }\n }\n}\n\nexport function createAnthropicProviderFromEnv(): AnthropicMessagesProvider | null {\n return createProviderFromEnv(\"ANTHROPIC_API_KEY\", Anthropic, AnthropicMessagesProvider);\n}\n","/**\n * Google Gemini Model Specifications\n *\n * Model data for Google Gemini models including 3.0, 2.5 and 2.0 series\n * with their specifications, pricing (Standard Paid tier), and capabilities.\n *\n * Pricing source: https://ai.google.dev/gemini-api/docs/pricing\n * Last updated: 2025-11-29\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const GEMINI_MODELS: ModelSpec[] = [\n // Gemini 3 Pro (Preview)\n {\n provider: \"gemini\",\n modelId: \"gemini-3-pro-preview\",\n displayName: \"Gemini 3 Pro (Preview)\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n pricing: {\n input: 2.0, // $2.00 for prompts <= 200k, $4.00 for > 200k (using lower tier)\n output: 12.0, // $12.00 for prompts <= 200k, $18.00 for > 200k\n cachedInput: 0.2, // $0.20 for prompts <= 200k\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 3\",\n releaseDate: \"2025-11-18\",\n notes:\n \"Best model for multimodal understanding, agentic and vibe-coding. Deep Think mode available.\",\n },\n },\n\n // Gemini 2.5 Pro\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-pro\",\n displayName: \"Gemini 2.5 Pro\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n pricing: {\n input: 1.25, // $1.25 for prompts <= 200k, $2.50 for > 200k\n output: 10.0, // $10.00 for prompts <= 200k, $15.00 for > 200k\n cachedInput: 0.125, // $0.125 for prompts <= 200k\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 2.5\",\n releaseDate: \"2025-06\",\n notes: \"State-of-the-art multipurpose model. Excels at coding and complex reasoning.\",\n },\n },\n\n // Gemini 2.5 Flash\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-flash\",\n displayName: \"Gemini 2.5 Flash\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n pricing: {\n input: 0.3, // $0.30 for text/image/video, $1.00 for audio\n output: 2.5,\n cachedInput: 0.03, // $0.03 for text/image/video\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 2.5\",\n releaseDate: \"2025-06\",\n notes: \"First hybrid reasoning model with 1M context and thinking budgets.\",\n },\n },\n\n // Gemini 2.5 Flash-Lite\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-flash-lite\",\n displayName: \"Gemini 2.5 Flash-Lite\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n pricing: {\n input: 0.1, // $0.10 for text/image/video, $0.30 for audio\n output: 0.4,\n cachedInput: 0.01, // $0.01 for text/image/video\n },\n knowledgeCutoff: \"2025-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 2.5\",\n releaseDate: \"2025-06\",\n notes: \"Smallest and most cost effective model, built for at scale usage.\",\n },\n },\n\n // Gemini 2.0 Flash\n {\n provider: \"gemini\",\n modelId: \"gemini-2.0-flash\",\n displayName: \"Gemini 2.0 Flash\",\n contextWindow: 1_048_576,\n maxOutputTokens: 8_192,\n pricing: {\n input: 0.1, // $0.10 for text/image/video, $0.70 for audio\n output: 0.4,\n cachedInput: 0.025, // $0.025 for text/image/video\n },\n knowledgeCutoff: \"2024-08\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 2.0\",\n notes: \"Balanced multimodal model with 1M context, built for the era of Agents.\",\n },\n },\n\n // Gemini 2.0 Flash-Lite\n {\n provider: \"gemini\",\n modelId: \"gemini-2.0-flash-lite\",\n displayName: \"Gemini 2.0 Flash-Lite\",\n contextWindow: 1_048_576,\n maxOutputTokens: 8_192,\n pricing: {\n input: 0.075,\n output: 0.3,\n // No context caching available for 2.0-flash-lite\n },\n knowledgeCutoff: \"2024-08\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"Gemini 2.0\",\n notes: \"Smallest and most cost effective 2.0 model for at scale usage.\",\n },\n },\n];\n","import { FunctionCallingConfigMode, GoogleGenAI } from \"@google/genai\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport { BaseProviderAdapter } from \"./base-provider.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"./constants.js\";\nimport { GEMINI_MODELS } from \"./gemini-models.js\";\nimport { createProviderFromEnv } from \"./utils.js\";\n\ntype GeminiContent = {\n role: string;\n parts: Array<{ text: string }>;\n};\n\ntype GeminiChunk = {\n text?: () => string;\n candidates?: Array<{\n content?: {\n parts?: Array<{ text?: string }>;\n };\n finishReason?: string;\n }>;\n usageMetadata?: {\n promptTokenCount?: number;\n candidatesTokenCount?: number;\n totalTokenCount?: number;\n cachedContentTokenCount?: number;\n };\n};\n\nconst GEMINI_ROLE_MAP: Record<LLMMessage[\"role\"], \"user\" | \"model\"> = {\n system: \"user\",\n user: \"user\",\n assistant: \"model\",\n};\n\nexport class GeminiGenerativeProvider extends BaseProviderAdapter {\n readonly providerId = \"gemini\" as const;\n\n supports(descriptor: ModelDescriptor): boolean {\n return descriptor.provider === this.providerId;\n }\n\n getModelSpecs() {\n return GEMINI_MODELS;\n }\n\n protected buildRequestPayload(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n _spec: ModelSpec | undefined,\n messages: LLMMessage[],\n ): {\n model: string;\n contents: Array<{ role: string; parts: Array<{ text: string }> }>;\n config: Record<string, unknown>;\n } {\n // Convert messages to Gemini format (system messages become user+model exchanges)\n const contents = this.convertMessagesToContents(messages);\n const generationConfig = this.buildGenerationConfig(options);\n\n // Build the config object for the new SDK\n const config: Record<string, unknown> = {\n // Note: systemInstruction removed - it doesn't work with countTokens()\n // System messages are now included in contents as user+model exchanges\n ...(generationConfig ? { ...generationConfig } : {}),\n // Explicitly disable function calling to prevent UNEXPECTED_TOOL_CALL errors\n toolConfig: {\n functionCallingConfig: {\n mode: FunctionCallingConfigMode.NONE,\n },\n },\n ...options.extra,\n };\n\n return {\n model: descriptor.name,\n contents: this.convertContentsForNewSDK(contents),\n config,\n };\n }\n\n protected async executeStreamRequest(payload: {\n model: string;\n contents: Array<{ role: string; parts: Array<{ text: string }> }>;\n config: Record<string, unknown>;\n }): Promise<AsyncIterable<GeminiChunk>> {\n const client = this.client as GoogleGenAI;\n const streamResponse = await client.models.generateContentStream(payload);\n return streamResponse as unknown as AsyncIterable<GeminiChunk>;\n }\n\n /**\n * Convert LLM messages to Gemini contents format.\n *\n * For Gemini, we convert system messages to user+model exchanges instead of\n * using systemInstruction, because:\n * 1. systemInstruction doesn't work with countTokens() API\n * 2. This approach gives perfect token counting accuracy (0% error)\n * 3. The model receives and follows system instructions identically\n *\n * System message: \"You are a helpful assistant\"\n * Becomes:\n * - User: \"You are a helpful assistant\"\n * - Model: \"Understood.\"\n */\n private convertMessagesToContents(messages: LLMMessage[]): GeminiContent[] {\n const expandedMessages: LLMMessage[] = [];\n\n for (const message of messages) {\n if (message.role === \"system\") {\n // Convert system message to user+model exchange\n expandedMessages.push({\n role: \"user\",\n content: message.content,\n });\n expandedMessages.push({\n role: \"assistant\",\n content: \"Understood.\",\n });\n } else {\n expandedMessages.push(message);\n }\n }\n\n return this.mergeConsecutiveMessages(expandedMessages);\n }\n\n private mergeConsecutiveMessages(messages: LLMMessage[]): GeminiContent[] {\n if (messages.length === 0) {\n return [];\n }\n\n const result: GeminiContent[] = [];\n let currentGroup: GeminiContent | null = null;\n\n for (const message of messages) {\n const geminiRole = GEMINI_ROLE_MAP[message.role];\n\n if (currentGroup && currentGroup.role === geminiRole) {\n // Merge into current group\n currentGroup.parts.push({ text: message.content });\n } else {\n // Start new group\n if (currentGroup) {\n result.push(currentGroup);\n }\n currentGroup = {\n role: geminiRole,\n parts: [{ text: message.content }],\n };\n }\n }\n\n // Push the last group\n if (currentGroup) {\n result.push(currentGroup);\n }\n\n return result;\n }\n\n private convertContentsForNewSDK(\n contents: GeminiContent[],\n ): Array<{ role: string; parts: Array<{ text: string }> }> {\n // The new SDK expects a simpler format for contents\n return contents.map((content) => ({\n role: content.role,\n parts: content.parts.map((part) => ({ text: part.text })),\n }));\n }\n\n private buildGenerationConfig(options: LLMGenerationOptions) {\n const config: Record<string, unknown> = {};\n\n // Only set maxOutputTokens if explicitly provided\n // Otherwise let Gemini use \"as much as fits\" in the context window\n if (typeof options.maxTokens === \"number\") {\n config.maxOutputTokens = options.maxTokens;\n }\n\n if (typeof options.temperature === \"number\") {\n config.temperature = options.temperature;\n }\n if (typeof options.topP === \"number\") {\n config.topP = options.topP;\n }\n if (options.stopSequences?.length) {\n config.stopSequences = options.stopSequences;\n }\n\n return Object.keys(config).length > 0 ? config : null;\n }\n\n protected async *wrapStream(iterable: AsyncIterable<unknown>): LLMStream {\n const stream = iterable as AsyncIterable<GeminiChunk>;\n for await (const chunk of stream) {\n const text = this.extractText(chunk);\n if (text) {\n yield { text, rawEvent: chunk };\n }\n\n const finishReason = this.extractFinishReason(chunk);\n const usage = this.extractUsage(chunk);\n\n if (finishReason || usage) {\n yield { text: \"\", finishReason, usage, rawEvent: chunk };\n }\n }\n }\n\n private extractText(chunk: GeminiChunk): string {\n if (!chunk?.candidates) {\n return \"\";\n }\n\n return chunk.candidates\n .flatMap((candidate) => candidate.content?.parts ?? [])\n .map((part) => part.text ?? \"\")\n .join(\"\");\n }\n\n private extractFinishReason(chunk: GeminiChunk): string | null {\n const candidate = chunk?.candidates?.find((item) => item.finishReason);\n return candidate?.finishReason ?? null;\n }\n\n private extractUsage(\n chunk: GeminiChunk,\n ):\n | { inputTokens: number; outputTokens: number; totalTokens: number; cachedInputTokens?: number }\n | undefined {\n const usageMetadata = chunk?.usageMetadata;\n if (!usageMetadata) {\n return undefined;\n }\n\n return {\n inputTokens: usageMetadata.promptTokenCount ?? 0,\n outputTokens: usageMetadata.candidatesTokenCount ?? 0,\n totalTokens: usageMetadata.totalTokenCount ?? 0,\n // Gemini returns cached token count in cachedContentTokenCount\n cachedInputTokens: usageMetadata.cachedContentTokenCount ?? 0,\n };\n }\n\n /**\n * Count tokens in messages using Gemini's native token counting API.\n *\n * This method provides accurate token estimation for Gemini models by:\n * - Using the SDK's countTokens() method\n * - Converting system messages to user+model exchanges (same as in generation)\n * - This gives perfect token counting accuracy (0% error vs actual usage)\n *\n * @param messages - The messages to count tokens for\n * @param descriptor - Model descriptor containing the model name\n * @param _spec - Optional model specification (currently unused)\n * @returns Promise resolving to the estimated input token count\n *\n * @throws Never throws - falls back to character-based estimation (4 chars/token) on error\n *\n * @example\n * ```typescript\n * const count = await provider.countTokens(\n * [{ role: \"user\", content: \"Hello!\" }],\n * { provider: \"gemini\", name: \"gemini-1.5-pro\" }\n * );\n * ```\n */\n async countTokens(\n messages: LLMMessage[],\n descriptor: ModelDescriptor,\n _spec?: ModelSpec,\n ): Promise<number> {\n const client = this.client as GoogleGenAI;\n\n // Convert messages to Gemini format (same as buildRequestPayload)\n const contents = this.convertMessagesToContents(messages);\n\n try {\n // Use Gemini's count_tokens method\n const response = await client.models.countTokens({\n model: descriptor.name,\n contents: this.convertContentsForNewSDK(contents),\n // Note: systemInstruction not used - it's not supported by countTokens()\n // and would cause a 2100% token counting error\n });\n return response.totalTokens ?? 0;\n } catch (error) {\n // Log the error for debugging\n console.warn(\n `Token counting failed for ${descriptor.name}, using fallback estimation:`,\n error,\n );\n // Fallback to rough estimation if API fails\n const totalChars = messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0);\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN);\n }\n }\n}\n\nexport function createGeminiProviderFromEnv(): GeminiGenerativeProvider | null {\n return createProviderFromEnv(\"GEMINI_API_KEY\", GoogleGenAI, GeminiGenerativeProvider);\n}\n","/**\n * OpenAI Model Specifications\n *\n * Model data for OpenAI models including GPT-5, GPT-4.1, GPT-4o, and o-series\n * with their specifications, pricing (Standard tier), and capabilities.\n *\n * Pricing source: https://openai.com/api/pricing (Standard tier)\n * Last updated: 2025-11-29\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const OPENAI_MODELS: ModelSpec[] = [\n // GPT-5 Family\n {\n provider: \"openai\",\n modelId: \"gpt-5.1\",\n displayName: \"GPT-5.1\",\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 1.25,\n output: 10.0,\n cachedInput: 0.125,\n },\n knowledgeCutoff: \"2024-09-30\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-5\",\n releaseDate: \"2025-11-12\",\n notes: \"Latest GPT-5 with improved instruction following. 2-3x faster than GPT-5.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5\",\n displayName: \"GPT-5\",\n contextWindow: 272_000,\n maxOutputTokens: 128_000,\n pricing: {\n input: 1.25,\n output: 10.0,\n cachedInput: 0.125,\n },\n knowledgeCutoff: \"2024-09-30\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-5\",\n releaseDate: \"2025-08-07\",\n notes: \"Best model for coding and agentic tasks. Adaptive reasoning with 90% caching discount.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5-mini\",\n displayName: \"GPT-5 Mini\",\n contextWindow: 272_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 0.25,\n output: 2.0,\n cachedInput: 0.025,\n },\n knowledgeCutoff: \"2024-06-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-5\",\n notes: \"Fast and cost-efficient with adaptive reasoning\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5-nano\",\n displayName: \"GPT-5 Nano\",\n contextWindow: 272_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 0.05,\n output: 0.4,\n cachedInput: 0.005,\n },\n knowledgeCutoff: \"2024-05-31\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-5\",\n notes: \"Fastest, most cost-efficient version for well-defined tasks\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5-pro\",\n displayName: \"GPT-5 Pro\",\n contextWindow: 272_000,\n maxOutputTokens: 128_000,\n pricing: {\n input: 15.0,\n output: 120.0,\n // No cached input pricing for gpt-5-pro\n },\n knowledgeCutoff: \"2024-09-30\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"GPT-5\",\n notes: \"Premium tier with enhanced capabilities. Does not support prompt caching.\",\n supportsTemperature: false,\n },\n },\n\n // GPT-4.1 Family\n {\n provider: \"openai\",\n modelId: \"gpt-4.1\",\n displayName: \"GPT-4.1\",\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 2.0,\n output: 8.0,\n cachedInput: 0.5,\n },\n knowledgeCutoff: \"2024-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-4.1\",\n notes: \"Improved GPT-4 with better instruction following\",\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-4.1-mini\",\n displayName: \"GPT-4.1 Mini\",\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 0.4,\n output: 1.6,\n cachedInput: 0.1,\n },\n knowledgeCutoff: \"2024-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-4.1\",\n notes: \"Cost-efficient GPT-4.1 variant\",\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-4.1-nano\",\n displayName: \"GPT-4.1 Nano\",\n contextWindow: 128_000,\n maxOutputTokens: 32_768,\n pricing: {\n input: 0.1,\n output: 0.4,\n cachedInput: 0.025,\n },\n knowledgeCutoff: \"2024-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-4.1\",\n notes: \"Fastest GPT-4.1 variant for simple tasks\",\n },\n },\n\n // GPT-4o Family\n {\n provider: \"openai\",\n modelId: \"gpt-4o\",\n displayName: \"GPT-4o\",\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n pricing: {\n input: 2.5,\n output: 10.0,\n cachedInput: 1.25,\n },\n knowledgeCutoff: \"2024-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-4o\",\n notes: \"Multimodal model optimized for speed\",\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-4o-mini\",\n displayName: \"GPT-4o Mini\",\n contextWindow: 128_000,\n maxOutputTokens: 16_384,\n pricing: {\n input: 0.15,\n output: 0.6,\n cachedInput: 0.075,\n },\n knowledgeCutoff: \"2024-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"GPT-4o\",\n notes: \"Fast and affordable multimodal model\",\n },\n },\n\n // o-series (Reasoning models)\n {\n provider: \"openai\",\n modelId: \"o1\",\n displayName: \"o1\",\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n pricing: {\n input: 15.0,\n output: 60.0,\n cachedInput: 7.5,\n },\n knowledgeCutoff: \"2024-12-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"o-series\",\n notes: \"Advanced reasoning model with chain-of-thought\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"o3\",\n displayName: \"o3\",\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n pricing: {\n input: 2.0,\n output: 8.0,\n cachedInput: 0.5,\n },\n knowledgeCutoff: \"2025-01-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"o-series\",\n notes: \"Next-gen reasoning model, more efficient than o1\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"o4-mini\",\n displayName: \"o4 Mini\",\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n pricing: {\n input: 1.1,\n output: 4.4,\n cachedInput: 0.275,\n },\n knowledgeCutoff: \"2025-04-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n fineTuning: true,\n },\n metadata: {\n family: \"o-series\",\n notes: \"Cost-efficient reasoning model\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"o3-mini\",\n displayName: \"o3 Mini\",\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n pricing: {\n input: 1.1,\n output: 4.4,\n cachedInput: 0.55,\n },\n knowledgeCutoff: \"2025-01-01\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"o-series\",\n notes: \"Compact reasoning model for cost-sensitive applications\",\n supportsTemperature: false,\n },\n },\n];\n","import OpenAI from \"openai\";\nimport type { ChatCompletionChunk } from \"openai/resources/chat/completions\";\nimport { encoding_for_model, type TiktokenModel } from \"tiktoken\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport { BaseProviderAdapter } from \"./base-provider.js\";\nimport {\n FALLBACK_CHARS_PER_TOKEN,\n OPENAI_MESSAGE_OVERHEAD_TOKENS,\n OPENAI_NAME_FIELD_OVERHEAD_TOKENS,\n OPENAI_REPLY_PRIMING_TOKENS,\n} from \"./constants.js\";\nimport { OPENAI_MODELS } from \"./openai-models.js\";\nimport { createProviderFromEnv } from \"./utils.js\";\n\nconst ROLE_MAP: Record<LLMMessage[\"role\"], \"system\" | \"user\" | \"assistant\"> = {\n system: \"system\",\n user: \"user\",\n assistant: \"assistant\",\n};\n\n// Note: Temperature support is now determined from the ModelSpec passed to stream()\n// instead of being hardcoded at module level\n\nfunction sanitizeExtra(\n extra: Record<string, unknown> | undefined,\n allowTemperature: boolean,\n): Record<string, unknown> | undefined {\n if (!extra) {\n return undefined;\n }\n\n if (allowTemperature || !Object.hasOwn(extra, \"temperature\")) {\n return extra;\n }\n\n return Object.fromEntries(Object.entries(extra).filter(([key]) => key !== \"temperature\"));\n}\n\nexport class OpenAIChatProvider extends BaseProviderAdapter {\n readonly providerId = \"openai\" as const;\n\n supports(descriptor: ModelDescriptor): boolean {\n return descriptor.provider === this.providerId;\n }\n\n getModelSpecs() {\n return OPENAI_MODELS;\n }\n\n protected buildRequestPayload(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n spec: ModelSpec | undefined,\n messages: LLMMessage[],\n ): Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0] {\n const { maxTokens, temperature, topP, stopSequences, extra } = options;\n\n // Use spec metadata to determine temperature support, defaulting to true if spec is unavailable\n const supportsTemperature = spec?.metadata?.supportsTemperature !== false;\n const shouldIncludeTemperature = typeof temperature === \"number\" && supportsTemperature;\n const sanitizedExtra = sanitizeExtra(extra, shouldIncludeTemperature);\n\n return {\n model: descriptor.name,\n messages: messages.map((message) => ({\n role: ROLE_MAP[message.role],\n content: message.content,\n name: message.name,\n })),\n // Only set max_completion_tokens if explicitly provided\n // Otherwise let the API use \"as much as fits\" in the context window\n ...(maxTokens !== undefined ? { max_completion_tokens: maxTokens } : {}),\n top_p: topP,\n stop: stopSequences,\n stream: true,\n stream_options: { include_usage: true },\n ...(sanitizedExtra ?? {}),\n ...(shouldIncludeTemperature ? { temperature } : {}),\n };\n }\n\n protected async executeStreamRequest(\n payload: Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0],\n ): Promise<AsyncIterable<ChatCompletionChunk>> {\n const client = this.client as OpenAI;\n const stream = await client.chat.completions.create(payload);\n return stream as unknown as AsyncIterable<ChatCompletionChunk>;\n }\n\n protected async *wrapStream(iterable: AsyncIterable<unknown>): LLMStream {\n const stream = iterable as AsyncIterable<ChatCompletionChunk>;\n for await (const chunk of stream) {\n const text = chunk.choices.map((choice) => choice.delta?.content ?? \"\").join(\"\");\n if (text) {\n yield { text, rawEvent: chunk };\n }\n\n const finishReason = chunk.choices.find((choice) => choice.finish_reason)?.finish_reason;\n\n // Extract token usage if available (typically in the final chunk)\n // OpenAI returns cached token count in prompt_tokens_details.cached_tokens\n const usage = chunk.usage\n ? {\n inputTokens: chunk.usage.prompt_tokens,\n outputTokens: chunk.usage.completion_tokens,\n totalTokens: chunk.usage.total_tokens,\n cachedInputTokens:\n (chunk.usage as { prompt_tokens_details?: { cached_tokens?: number } })\n .prompt_tokens_details?.cached_tokens ?? 0,\n }\n : undefined;\n\n if (finishReason || usage) {\n yield { text: \"\", finishReason, usage, rawEvent: chunk };\n }\n }\n }\n\n /**\n * Count tokens in messages using OpenAI's tiktoken library.\n *\n * This method provides accurate token estimation for OpenAI models by:\n * - Using the model-specific tokenizer encoding\n * - Accounting for message formatting overhead\n * - Falling back to gpt-4o encoding for unknown models\n *\n * @param messages - The messages to count tokens for\n * @param descriptor - Model descriptor containing the model name\n * @param _spec - Optional model specification (currently unused)\n * @returns Promise resolving to the estimated input token count\n *\n * @throws Never throws - falls back to character-based estimation (4 chars/token) on error\n *\n * @example\n * ```typescript\n * const count = await provider.countTokens(\n * [{ role: \"user\", content: \"Hello!\" }],\n * { provider: \"openai\", name: \"gpt-4\" }\n * );\n * ```\n */\n async countTokens(\n messages: LLMMessage[],\n descriptor: ModelDescriptor,\n _spec?: ModelSpec,\n ): Promise<number> {\n try {\n // Map model names to tiktoken models\n // For models not directly supported, use a reasonable default\n const modelName = descriptor.name as TiktokenModel;\n let encoding;\n\n try {\n encoding = encoding_for_model(modelName);\n } catch {\n // If the specific model isn't supported, fall back to gpt-4o which uses cl100k_base\n encoding = encoding_for_model(\"gpt-4o\");\n }\n\n try {\n let tokenCount = 0;\n\n // Count tokens per message with proper formatting\n // OpenAI's format adds tokens for message boundaries and roles\n // Token overhead based on OpenAI's message formatting\n // See: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n for (const message of messages) {\n // Every message follows <im_start>{role/name}\\n{content}<im_end>\\n\n tokenCount += OPENAI_MESSAGE_OVERHEAD_TOKENS;\n\n const roleText = ROLE_MAP[message.role];\n tokenCount += encoding.encode(roleText).length;\n tokenCount += encoding.encode(message.content ?? \"\").length;\n\n if (message.name) {\n tokenCount += encoding.encode(message.name).length;\n tokenCount += OPENAI_NAME_FIELD_OVERHEAD_TOKENS;\n }\n }\n\n tokenCount += OPENAI_REPLY_PRIMING_TOKENS;\n\n return tokenCount;\n } finally {\n // Always free the encoding to prevent memory leaks\n encoding.free();\n }\n } catch (error) {\n // Log the error for debugging\n console.warn(\n `Token counting failed for ${descriptor.name}, using fallback estimation:`,\n error,\n );\n // If tiktoken fails, provide a rough estimate\n const totalChars = messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0);\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN);\n }\n }\n}\n\nexport function createOpenAIProviderFromEnv(): OpenAIChatProvider | null {\n return createProviderFromEnv(\"OPENAI_API_KEY\", OpenAI, OpenAIChatProvider);\n}\n","import { createAnthropicProviderFromEnv } from \"./anthropic.js\";\nimport { createGeminiProviderFromEnv } from \"./gemini.js\";\nimport { createOpenAIProviderFromEnv } from \"./openai.js\";\nimport type { ProviderAdapter } from \"./provider.js\";\n\nexport type ProviderDiscoverer = () => ProviderAdapter | null | undefined;\n\nconst DISCOVERERS: ProviderDiscoverer[] = [\n createOpenAIProviderFromEnv,\n createAnthropicProviderFromEnv,\n createGeminiProviderFromEnv,\n];\n\nexport function discoverProviderAdapters(): ProviderAdapter[] {\n const adapters: ProviderAdapter[] = [];\n\n for (const discover of DISCOVERERS) {\n const adapter = discover();\n if (adapter) {\n adapters.push(adapter);\n }\n }\n\n return adapters;\n}\n","/**\n * Model Registry\n *\n * Centralized registry for querying LLM model specifications,\n * validating configurations, and estimating costs.\n *\n * Model data is provided by ProviderAdapter implementations and\n * automatically populated when providers are registered.\n */\n\nimport type { ProviderAdapter } from \"../providers/provider.js\";\nimport type { CostEstimate, ModelLimits, ModelSpec } from \"./model-catalog.js\";\n\nexport class ModelRegistry {\n private modelSpecs: ModelSpec[] = [];\n private providerMap = new Map<string, ModelSpec[]>();\n\n /**\n * Register a provider and collect its model specifications\n */\n registerProvider(provider: ProviderAdapter): void {\n const specs = provider.getModelSpecs?.() ?? [];\n\n if (specs.length > 0) {\n this.modelSpecs.push(...specs);\n this.providerMap.set(provider.providerId, specs);\n }\n }\n\n /**\n * Register a custom model specification at runtime\n *\n * Use this to add models that aren't in the built-in catalog, such as:\n * - Fine-tuned models with custom pricing\n * - New models not yet supported by llmist\n * - Custom deployments with different configurations\n *\n * @param spec - Complete model specification\n * @throws {Error} If spec is missing required fields\n *\n * @example\n * ```ts\n * client.modelRegistry.registerModel({\n * provider: \"openai\",\n * modelId: \"ft:gpt-4o-2024-08-06:my-org:custom:abc123\",\n * displayName: \"My Fine-tuned GPT-4o\",\n * contextWindow: 128_000,\n * maxOutputTokens: 16_384,\n * pricing: { input: 7.5, output: 30.0 },\n * knowledgeCutoff: \"2024-08\",\n * features: { streaming: true, functionCalling: true, vision: true }\n * });\n * ```\n */\n registerModel(spec: ModelSpec): void {\n // Validate required fields\n if (!spec.modelId || !spec.provider) {\n throw new Error(\"ModelSpec must have modelId and provider\");\n }\n\n // Check for duplicates\n const existing = this.getModelSpec(spec.modelId);\n if (existing) {\n console.warn(\n `[llmist] Overwriting existing model spec for \"${spec.modelId}\". ` +\n `Previous: ${existing.displayName}, New: ${spec.displayName}`,\n );\n // Remove old spec from arrays\n const index = this.modelSpecs.findIndex((m) => m.modelId === spec.modelId);\n if (index !== -1) {\n this.modelSpecs.splice(index, 1);\n }\n // Remove from provider map\n const providerSpecs = this.providerMap.get(spec.provider);\n if (providerSpecs) {\n const providerIndex = providerSpecs.findIndex((m) => m.modelId === spec.modelId);\n if (providerIndex !== -1) {\n providerSpecs.splice(providerIndex, 1);\n }\n }\n }\n\n // Add to registry\n this.modelSpecs.push(spec);\n\n // Update provider map\n const providerSpecs = this.providerMap.get(spec.provider) ?? [];\n providerSpecs.push(spec);\n this.providerMap.set(spec.provider, providerSpecs);\n }\n\n /**\n * Register multiple custom model specifications at once\n *\n * @param specs - Array of complete model specifications\n *\n * @example\n * ```ts\n * client.modelRegistry.registerModels([\n * { provider: \"openai\", modelId: \"gpt-5\", ... },\n * { provider: \"openai\", modelId: \"gpt-5-mini\", ... }\n * ]);\n * ```\n */\n registerModels(specs: ModelSpec[]): void {\n for (const spec of specs) {\n this.registerModel(spec);\n }\n }\n\n /**\n * Get model specification by model ID\n * @param modelId - Full model identifier (e.g., 'gpt-5', 'claude-sonnet-4-5-20250929')\n * @returns ModelSpec if found, undefined otherwise\n */\n getModelSpec(modelId: string): ModelSpec | undefined {\n return this.modelSpecs.find((model) => model.modelId === modelId);\n }\n\n /**\n * List all models, optionally filtered by provider\n * @param providerId - Optional provider ID to filter by (e.g., 'openai', 'anthropic')\n * @returns Array of ModelSpec objects\n */\n listModels(providerId?: string): ModelSpec[] {\n if (!providerId) {\n return [...this.modelSpecs];\n }\n\n return this.providerMap.get(providerId) ?? [];\n }\n\n /**\n * Get context window and output limits for a model\n * @param modelId - Full model identifier\n * @returns ModelLimits if model found, undefined otherwise\n */\n getModelLimits(modelId: string): ModelLimits | undefined {\n const spec = this.getModelSpec(modelId);\n if (!spec) return undefined;\n\n return {\n contextWindow: spec.contextWindow,\n maxOutputTokens: spec.maxOutputTokens,\n };\n }\n\n /**\n * Estimate API cost for a given model and token usage\n * @param modelId - Full model identifier\n * @param inputTokens - Number of input tokens (total, including cached and cache creation)\n * @param outputTokens - Number of output tokens\n * @param cachedInputTokens - Number of cached input tokens (subset of inputTokens)\n * @param cacheCreationInputTokens - Number of cache creation tokens (subset of inputTokens, Anthropic only)\n * @returns CostEstimate if model found, undefined otherwise\n */\n estimateCost(\n modelId: string,\n inputTokens: number,\n outputTokens: number,\n cachedInputTokens = 0,\n cacheCreationInputTokens = 0,\n ): CostEstimate | undefined {\n const spec = this.getModelSpec(modelId);\n if (!spec) return undefined;\n\n // Pricing is per 1M tokens, so convert to actual cost\n // Cached tokens are charged at a lower rate (or same rate if no cached pricing)\n // Cache creation tokens are charged at a higher rate (Anthropic: 1.25x input)\n const cachedRate = spec.pricing.cachedInput ?? spec.pricing.input;\n const cacheWriteRate = spec.pricing.cacheWriteInput ?? spec.pricing.input;\n const uncachedInputTokens = inputTokens - cachedInputTokens - cacheCreationInputTokens;\n\n const uncachedInputCost = (uncachedInputTokens / 1_000_000) * spec.pricing.input;\n const cachedInputCost = (cachedInputTokens / 1_000_000) * cachedRate;\n const cacheCreationCost = (cacheCreationInputTokens / 1_000_000) * cacheWriteRate;\n const inputCost = uncachedInputCost + cachedInputCost + cacheCreationCost;\n const outputCost = (outputTokens / 1_000_000) * spec.pricing.output;\n const totalCost = inputCost + outputCost;\n\n return {\n inputCost,\n cachedInputCost,\n cacheCreationCost,\n outputCost,\n totalCost,\n currency: \"USD\",\n };\n }\n\n /**\n * Validate that requested token count fits within model limits\n * @param modelId - Full model identifier\n * @param requestedTokens - Total tokens requested (input + output)\n * @returns true if valid, false if model not found or exceeds limits\n */\n validateModelConfig(modelId: string, requestedTokens: number): boolean {\n const limits = this.getModelLimits(modelId);\n if (!limits) return false;\n\n return requestedTokens <= limits.contextWindow;\n }\n\n /**\n * Check if a model supports a specific feature\n * @param modelId - Full model identifier\n * @param feature - Feature to check ('streaming', 'functionCalling', 'vision', etc.)\n * @returns true if model supports feature, false otherwise\n */\n supportsFeature(modelId: string, feature: keyof ModelSpec[\"features\"]): boolean {\n const spec = this.getModelSpec(modelId);\n if (!spec) return false;\n\n return spec.features[feature] === true;\n }\n\n /**\n * Get all models that support a specific feature\n * @param feature - Feature to filter by\n * @param providerId - Optional provider ID to filter by\n * @returns Array of ModelSpec objects that support the feature\n */\n getModelsByFeature(feature: keyof ModelSpec[\"features\"], providerId?: string): ModelSpec[] {\n const models = this.listModels(providerId);\n return models.filter((model) => model.features[feature] === true);\n }\n\n /**\n * Get the most cost-effective model for a given provider and token budget\n * @param inputTokens - Expected input tokens\n * @param outputTokens - Expected output tokens\n * @param providerId - Optional provider ID to filter by\n * @returns ModelSpec with lowest total cost, or undefined if no models found\n */\n getCheapestModel(\n inputTokens: number,\n outputTokens: number,\n providerId?: string,\n ): ModelSpec | undefined {\n const models = this.listModels(providerId);\n if (models.length === 0) return undefined;\n\n let cheapest: { model: ModelSpec; cost: number } | undefined;\n\n for (const model of models) {\n const estimate = this.estimateCost(model.modelId, inputTokens, outputTokens);\n if (!estimate) continue;\n\n if (!cheapest || estimate.totalCost < cheapest.cost) {\n cheapest = { model, cost: estimate.totalCost };\n }\n }\n\n return cheapest?.model;\n }\n}\n","import type { LLMMessage } from \"./messages.js\";\n\nexport interface LLMGenerationOptions {\n model: string;\n messages: LLMMessage[];\n maxTokens?: number;\n temperature?: number;\n topP?: number;\n stopSequences?: string[];\n responseFormat?: \"text\";\n metadata?: Record<string, unknown>;\n extra?: Record<string, unknown>;\n}\n\nexport interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n /** Number of input tokens served from cache (subset of inputTokens) */\n cachedInputTokens?: number;\n /** Number of input tokens written to cache (subset of inputTokens, Anthropic only) */\n cacheCreationInputTokens?: number;\n}\n\nexport interface LLMStreamChunk {\n text: string;\n /**\n * Indicates that the provider has finished producing output and includes the reason if available.\n */\n finishReason?: string | null;\n /**\n * Token usage information, typically available in the final chunk when the stream completes.\n */\n usage?: TokenUsage;\n /**\n * Provider specific payload emitted at the same time as the text chunk. This is useful for debugging and tests.\n */\n rawEvent?: unknown;\n}\n\nexport interface LLMStream extends AsyncIterable<LLMStreamChunk> {}\n\nexport type ProviderIdentifier = string;\n\nexport interface ModelDescriptor {\n provider: string;\n name: string;\n}\n\nexport class ModelIdentifierParser {\n constructor(private readonly defaultProvider: string = \"openai\") {}\n\n parse(identifier: string): ModelDescriptor {\n const trimmed = identifier.trim();\n if (!trimmed) {\n throw new Error(\"Model identifier cannot be empty\");\n }\n\n const [maybeProvider, ...rest] = trimmed.split(\":\");\n if (rest.length === 0) {\n return { provider: this.defaultProvider, name: maybeProvider };\n }\n\n const provider = maybeProvider;\n const name = rest.join(\":\");\n if (!name) {\n throw new Error(\"Model name cannot be empty\");\n }\n\n return { provider, name };\n }\n}\n","/**\n * Quick execution methods for simple use cases.\n *\n * These methods provide convenient shortcuts for common operations\n * without requiring full agent setup.\n *\n * @example\n * ```typescript\n * // Quick completion\n * const answer = await llmist.complete(\"What is 2+2?\");\n *\n * // Quick streaming\n * for await (const chunk of llmist.stream(\"Tell me a story\")) {\n * process.stdout.write(chunk);\n * }\n * ```\n */\n\nimport type { LLMist } from \"./client.js\";\nimport { LLMMessageBuilder } from \"./messages.js\";\nimport { resolveModel } from \"./model-shortcuts.js\";\n\n/**\n * Options for quick execution methods.\n */\nexport interface QuickOptions {\n /** Model to use (supports aliases like \"gpt4\", \"sonnet\", \"flash\") */\n model?: string;\n\n /** Temperature (0-1) */\n temperature?: number;\n\n /** System prompt */\n systemPrompt?: string;\n\n /** Max tokens to generate */\n maxTokens?: number;\n}\n\n/**\n * Quick completion - returns final text response.\n *\n * @param client - LLMist client instance\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Complete text response\n *\n * @example\n * ```typescript\n * const client = new LLMist();\n * const answer = await complete(client, \"What is 2+2?\");\n * console.log(answer); // \"4\" or \"2+2 equals 4\"\n * ```\n */\nexport async function complete(\n client: LLMist,\n prompt: string,\n options: QuickOptions = {},\n): Promise<string> {\n const model = resolveModel(options.model ?? \"gpt-5-nano\");\n\n const builder = new LLMMessageBuilder();\n if (options.systemPrompt) {\n builder.addSystem(options.systemPrompt);\n }\n builder.addUser(prompt);\n\n let fullResponse = \"\";\n for await (const chunk of client.stream({\n model,\n messages: builder.build(),\n temperature: options.temperature,\n maxTokens: options.maxTokens,\n })) {\n fullResponse += chunk.text;\n }\n\n return fullResponse.trim();\n}\n\n/**\n * Quick streaming - returns async generator of text chunks.\n *\n * @param client - LLMist client instance\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Async generator yielding text chunks\n *\n * @example\n * ```typescript\n * const client = new LLMist();\n *\n * for await (const chunk of stream(client, \"Tell me a story\")) {\n * process.stdout.write(chunk);\n * }\n * ```\n */\nexport async function* stream(\n client: LLMist,\n prompt: string,\n options: QuickOptions = {},\n): AsyncGenerator<string> {\n const model = resolveModel(options.model ?? \"gpt-5-nano\");\n\n const builder = new LLMMessageBuilder();\n if (options.systemPrompt) {\n builder.addSystem(options.systemPrompt);\n }\n builder.addUser(prompt);\n\n for await (const chunk of client.stream({\n model,\n messages: builder.build(),\n temperature: options.temperature,\n maxTokens: options.maxTokens,\n })) {\n yield chunk.text;\n }\n}\n","import { AgentBuilder } from \"../agent/builder.js\";\nimport { discoverProviderAdapters } from \"../providers/discovery.js\";\nimport type { ProviderAdapter } from \"../providers/provider.js\";\nimport type { LLMMessage } from \"./messages.js\";\nimport type { ModelSpec } from \"./model-catalog.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"./options.js\";\nimport { ModelIdentifierParser } from \"./options.js\";\nimport {\n complete as completeHelper,\n type QuickOptions,\n stream as streamHelper,\n} from \"./quick-methods.js\";\n\nexport interface LLMistOptions {\n /**\n * Provider adapters to register manually.\n */\n adapters?: ProviderAdapter[];\n /**\n * Default provider prefix applied when a model identifier omits it.\n */\n defaultProvider?: string;\n /**\n * Automatically discover built-in providers based on environment configuration.\n * Enabled by default.\n */\n autoDiscoverProviders?: boolean;\n /**\n * Custom model specifications to register at initialization.\n * Use this to define models not in the built-in catalog, such as:\n * - Fine-tuned models with custom pricing\n * - New models not yet supported by llmist\n * - Custom deployments with different configurations\n *\n * @example\n * ```ts\n * new LLMist({\n * customModels: [{\n * provider: \"openai\",\n * modelId: \"ft:gpt-4o-2024-08-06:my-org:custom:abc123\",\n * displayName: \"My Fine-tuned GPT-4o\",\n * contextWindow: 128_000,\n * maxOutputTokens: 16_384,\n * pricing: { input: 7.5, output: 30.0 },\n * knowledgeCutoff: \"2024-08\",\n * features: { streaming: true, functionCalling: true, vision: true }\n * }]\n * });\n * ```\n */\n customModels?: ModelSpec[];\n}\n\nexport class LLMist {\n private readonly parser: ModelIdentifierParser;\n readonly modelRegistry: ModelRegistry;\n private readonly adapters: ProviderAdapter[];\n\n constructor();\n constructor(adapters: ProviderAdapter[]);\n constructor(adapters: ProviderAdapter[], defaultProvider: string);\n constructor(options: LLMistOptions);\n constructor(...args: [] | [ProviderAdapter[]] | [ProviderAdapter[], string] | [LLMistOptions]) {\n let adapters: ProviderAdapter[] = [];\n let defaultProvider: string | undefined;\n let autoDiscoverProviders = true;\n let customModels: ModelSpec[] = [];\n\n if (args.length === 0) {\n // Use defaults\n } else if (Array.isArray(args[0])) {\n adapters = args[0];\n if (args.length > 1) {\n defaultProvider = args[1];\n }\n } else if (typeof args[0] === \"object\" && args[0] !== null) {\n const options = args[0];\n adapters = options.adapters ?? [];\n defaultProvider = options.defaultProvider;\n customModels = options.customModels ?? [];\n if (typeof options.autoDiscoverProviders === \"boolean\") {\n autoDiscoverProviders = options.autoDiscoverProviders;\n }\n }\n\n const discoveredAdapters = autoDiscoverProviders ? discoverProviderAdapters() : [];\n const combinedAdapters: ProviderAdapter[] = [...adapters];\n for (const adapter of discoveredAdapters) {\n if (!combinedAdapters.some((existing) => existing.providerId === adapter.providerId)) {\n combinedAdapters.push(adapter);\n }\n }\n\n if (combinedAdapters.length === 0) {\n throw new Error(\n \"No LLM providers available. Provide adapters explicitly or set provider API keys in the environment.\",\n );\n }\n\n const resolvedDefaultProvider = defaultProvider ?? combinedAdapters[0]?.providerId ?? \"openai\";\n\n // Sort by priority (descending: higher priority first)\n // Use stable sort to preserve order for equal priorities\n this.adapters = [...combinedAdapters].sort((a, b) => {\n const priorityA = a.priority ?? 0;\n const priorityB = b.priority ?? 0;\n return priorityB - priorityA;\n });\n this.parser = new ModelIdentifierParser(resolvedDefaultProvider);\n this.modelRegistry = new ModelRegistry();\n\n // Register all providers with the model registry\n for (const adapter of this.adapters) {\n this.modelRegistry.registerProvider(adapter);\n }\n\n // Register custom models if provided\n if (customModels.length > 0) {\n this.modelRegistry.registerModels(customModels);\n }\n }\n\n stream(options: LLMGenerationOptions): LLMStream {\n const descriptor = this.parser.parse(options.model);\n const spec = this.modelRegistry.getModelSpec(descriptor.name);\n const adapter = this.resolveAdapter(descriptor);\n return adapter.stream(options, descriptor, spec);\n }\n\n /**\n * Count tokens in messages for a given model.\n *\n * Uses provider-specific token counting methods for accurate estimation:\n * - OpenAI: tiktoken library with model-specific encodings\n * - Anthropic: Native messages.countTokens() API\n * - Gemini: SDK's countTokens() method\n *\n * Falls back to character-based estimation (4 chars/token) if the provider\n * doesn't support native token counting or if counting fails.\n *\n * This is useful for:\n * - Pre-request cost estimation\n * - Context window management\n * - Request batching optimization\n *\n * @param model - Model identifier (e.g., \"openai:gpt-4\", \"anthropic:claude-3-5-sonnet-20241022\")\n * @param messages - Array of messages to count tokens for\n * @returns Promise resolving to the estimated input token count\n *\n * @example\n * ```typescript\n * const client = new LLMist();\n * const messages = [\n * { role: 'system', content: 'You are a helpful assistant.' },\n * { role: 'user', content: 'Hello!' }\n * ];\n *\n * const tokenCount = await client.countTokens('openai:gpt-4', messages);\n * console.log(`Estimated tokens: ${tokenCount}`);\n * ```\n */\n async countTokens(model: string, messages: LLMMessage[]): Promise<number> {\n const descriptor = this.parser.parse(model);\n const spec = this.modelRegistry.getModelSpec(descriptor.name);\n const adapter = this.resolveAdapter(descriptor);\n\n // Check if the provider supports token counting\n if (adapter.countTokens) {\n return adapter.countTokens(messages, descriptor, spec);\n }\n\n // Fallback: rough character-based estimation (4 chars per token)\n const totalChars = messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0);\n return Math.ceil(totalChars / 4);\n }\n\n private resolveAdapter(descriptor: ModelDescriptor): ProviderAdapter {\n const adapter = this.adapters.find((item) => item.supports(descriptor));\n if (!adapter) {\n throw new Error(`No adapter registered for provider ${descriptor.provider}`);\n }\n\n return adapter;\n }\n\n /**\n * Quick completion - returns final text response.\n * Convenient for simple queries without needing agent setup.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Complete text response\n *\n * @example\n * ```typescript\n * const answer = await LLMist.complete(\"What is 2+2?\");\n * console.log(answer); // \"4\" or \"2+2 equals 4\"\n *\n * const answer = await LLMist.complete(\"Tell me a joke\", {\n * model: \"sonnet\",\n * temperature: 0.9\n * });\n * ```\n */\n static async complete(prompt: string, options?: QuickOptions): Promise<string> {\n const client = new LLMist();\n return completeHelper(client, prompt, options);\n }\n\n /**\n * Quick streaming - returns async generator of text chunks.\n * Convenient for streaming responses without needing agent setup.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Async generator yielding text chunks\n *\n * @example\n * ```typescript\n * for await (const chunk of LLMist.stream(\"Tell me a story\")) {\n * process.stdout.write(chunk);\n * }\n *\n * // With options\n * for await (const chunk of LLMist.stream(\"Generate code\", {\n * model: \"gpt4\",\n * systemPrompt: \"You are a coding assistant\"\n * })) {\n * process.stdout.write(chunk);\n * }\n * ```\n */\n static stream(prompt: string, options?: QuickOptions): AsyncGenerator<string> {\n const client = new LLMist();\n return streamHelper(client, prompt, options);\n }\n\n /**\n * Instance method: Quick completion using this client instance.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Complete text response\n */\n async complete(prompt: string, options?: QuickOptions): Promise<string> {\n return completeHelper(this, prompt, options);\n }\n\n /**\n * Instance method: Quick streaming using this client instance.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Async generator yielding text chunks\n */\n streamText(prompt: string, options?: QuickOptions): AsyncGenerator<string> {\n return streamHelper(this, prompt, options);\n }\n\n /**\n * Create a fluent agent builder.\n * Provides a chainable API for configuring and creating agents.\n *\n * @returns AgentBuilder instance for chaining\n *\n * @example\n * ```typescript\n * const agent = LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withSystem(\"You are a helpful assistant\")\n * .withGadgets(Calculator, Weather)\n * .ask(\"What's the weather in Paris?\");\n *\n * for await (const event of agent.run()) {\n * // handle events\n * }\n * ```\n *\n * @example\n * ```typescript\n * // Quick one-liner for simple queries\n * const answer = await LLMist.createAgent()\n * .withModel(\"gpt4-mini\")\n * .askAndCollect(\"What is 2+2?\");\n * ```\n */\n static createAgent(): AgentBuilder {\n return new AgentBuilder();\n }\n\n /**\n * Create agent builder with this client instance.\n * Useful when you want to reuse a configured client.\n *\n * @returns AgentBuilder instance using this client\n *\n * @example\n * ```typescript\n * const client = new LLMist({ ... });\n *\n * const agent = client.createAgent()\n * .withModel(\"sonnet\")\n * .ask(\"Hello\");\n * ```\n */\n createAgent(): AgentBuilder {\n return new AgentBuilder(this);\n }\n}\n","/**\n * Fluent builder for creating agents with delightful DX.\n *\n * @example\n * ```typescript\n * const agent = await LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withSystem(\"You are a helpful assistant\")\n * .withGadgets(Calculator, Weather)\n * .withMaxIterations(10)\n * .ask(\"What's the weather in Paris?\");\n *\n * for await (const event of agent.run()) {\n * // process events\n * }\n * ```\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { PromptConfig } from \"../core/prompt-config.js\";\nimport type { GadgetOrClass } from \"../gadgets/registry.js\";\nimport { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { TextOnlyHandler } from \"../gadgets/types.js\";\nimport { Agent, type AgentOptions } from \"./agent.js\";\nimport { AGENT_INTERNAL_KEY } from \"./agent-internal-key.js\";\nimport type { CompactionConfig } from \"./compaction/config.js\";\nimport { collectText, type EventHandlers } from \"./event-handlers.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n/**\n * Message for conversation history.\n */\nexport type HistoryMessage = { user: string } | { assistant: string } | { system: string };\n\n/**\n * Fluent builder for creating agents.\n *\n * Provides a chainable API for configuring and creating agents,\n * making the code more expressive and easier to read.\n */\nexport class AgentBuilder {\n private client?: LLMist;\n private model?: string;\n private systemPrompt?: string;\n private temperature?: number;\n private maxIterations?: number;\n private logger?: Logger<ILogObj>;\n private hooks?: AgentHooks;\n private promptConfig?: PromptConfig;\n private gadgets: GadgetOrClass[] = [];\n private initialMessages: Array<{\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n }> = [];\n private onHumanInputRequired?: (question: string) => Promise<string>;\n private gadgetStartPrefix?: string;\n private gadgetEndPrefix?: string;\n private gadgetArgPrefix?: string;\n private textOnlyHandler?: TextOnlyHandler;\n private textWithGadgetsHandler?: {\n gadgetName: string;\n parameterMapping: (text: string) => Record<string, unknown>;\n resultMapping?: (text: string) => string;\n };\n private stopOnGadgetError?: boolean;\n private shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n private defaultGadgetTimeoutMs?: number;\n private gadgetOutputLimit?: boolean;\n private gadgetOutputLimitPercent?: number;\n private compactionConfig?: CompactionConfig;\n\n constructor(client?: LLMist) {\n this.client = client;\n }\n\n /**\n * Set the model to use.\n * Supports aliases like \"gpt4\", \"sonnet\", \"flash\".\n *\n * @param model - Model name or alias\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withModel(\"sonnet\") // Alias\n * .withModel(\"gpt-5-nano\") // Auto-detects provider\n * .withModel(\"openai:gpt-5\") // Explicit provider\n * ```\n */\n withModel(model: string): this {\n this.model = resolveModel(model);\n return this;\n }\n\n /**\n * Set the system prompt.\n *\n * @param prompt - System prompt\n * @returns This builder for chaining\n */\n withSystem(prompt: string): this {\n this.systemPrompt = prompt;\n return this;\n }\n\n /**\n * Set the temperature (0-1).\n *\n * @param temperature - Temperature value\n * @returns This builder for chaining\n */\n withTemperature(temperature: number): this {\n this.temperature = temperature;\n return this;\n }\n\n /**\n * Set maximum iterations.\n *\n * @param max - Maximum number of iterations\n * @returns This builder for chaining\n */\n withMaxIterations(max: number): this {\n this.maxIterations = max;\n return this;\n }\n\n /**\n * Set logger instance.\n *\n * @param logger - Logger instance\n * @returns This builder for chaining\n */\n withLogger(logger: Logger<ILogObj>): this {\n this.logger = logger;\n return this;\n }\n\n /**\n * Add hooks for agent lifecycle events.\n *\n * @param hooks - Agent hooks configuration\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * import { HookPresets } from 'llmist/hooks';\n *\n * .withHooks(HookPresets.logging())\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing()\n * ))\n * ```\n */\n withHooks(hooks: AgentHooks): this {\n this.hooks = hooks;\n return this;\n }\n\n /**\n * Configure custom prompts for gadget system messages.\n *\n * @param config - Prompt configuration object\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withPromptConfig({\n * mainInstruction: \"Use the gadget markers below:\",\n * rules: [\"Always use markers\", \"Never use function calling\"]\n * })\n * ```\n */\n withPromptConfig(config: PromptConfig): this {\n this.promptConfig = config;\n return this;\n }\n\n /**\n * Add gadgets (classes or instances).\n * Can be called multiple times to add more gadgets.\n *\n * @param gadgets - Gadget classes or instances\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgets(Calculator, Weather, Email)\n * .withGadgets(new Calculator(), new Weather())\n * .withGadgets(createGadget({ ... }))\n * ```\n */\n withGadgets(...gadgets: GadgetOrClass[]): this {\n this.gadgets.push(...gadgets);\n return this;\n }\n\n /**\n * Add conversation history messages.\n * Useful for continuing previous conversations.\n *\n * @param messages - Array of history messages\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withHistory([\n * { user: \"Hello\" },\n * { assistant: \"Hi there!\" },\n * { user: \"How are you?\" },\n * { assistant: \"I'm doing well, thanks!\" }\n * ])\n * ```\n */\n withHistory(messages: HistoryMessage[]): this {\n for (const msg of messages) {\n if (\"user\" in msg) {\n this.initialMessages.push({ role: \"user\", content: msg.user });\n } else if (\"assistant\" in msg) {\n this.initialMessages.push({ role: \"assistant\", content: msg.assistant });\n } else if (\"system\" in msg) {\n this.initialMessages.push({ role: \"system\", content: msg.system });\n }\n }\n return this;\n }\n\n /**\n * Add a single message to the conversation history.\n *\n * @param message - Single history message\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .addMessage({ user: \"Hello\" })\n * .addMessage({ assistant: \"Hi there!\" })\n * ```\n */\n addMessage(message: HistoryMessage): this {\n return this.withHistory([message]);\n }\n\n /**\n * Set the human input handler for interactive conversations.\n *\n * @param handler - Function to handle human input requests\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .onHumanInput(async (question) => {\n * return await promptUser(question);\n * })\n * ```\n */\n onHumanInput(handler: (question: string) => Promise<string>): this {\n this.onHumanInputRequired = handler;\n return this;\n }\n\n /**\n * Set custom gadget marker prefix.\n *\n * @param prefix - Custom start prefix for gadget markers\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetStartPrefix(\"<<GADGET_START>>\")\n * ```\n */\n withGadgetStartPrefix(prefix: string): this {\n this.gadgetStartPrefix = prefix;\n return this;\n }\n\n /**\n * Set custom gadget marker suffix.\n *\n * @param suffix - Custom end suffix for gadget markers\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetEndPrefix(\"<<GADGET_END>>\")\n * ```\n */\n withGadgetEndPrefix(suffix: string): this {\n this.gadgetEndPrefix = suffix;\n return this;\n }\n\n /**\n * Set custom argument prefix for block format parameters.\n *\n * @param prefix - Custom prefix for argument markers (default: \"!!!ARG:\")\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetArgPrefix(\"<<ARG>>\")\n * ```\n */\n withGadgetArgPrefix(prefix: string): this {\n this.gadgetArgPrefix = prefix;\n return this;\n }\n\n /**\n * Set the text-only handler strategy.\n *\n * Controls what happens when the LLM returns text without calling any gadgets:\n * - \"terminate\": End the agent loop (default)\n * - \"acknowledge\": Continue the loop for another iteration\n * - \"wait_for_input\": Wait for human input\n * - Custom handler: Provide a function for dynamic behavior\n *\n * @param handler - Text-only handler strategy or custom handler\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Simple strategy\n * .withTextOnlyHandler(\"acknowledge\")\n *\n * // Custom handler\n * .withTextOnlyHandler({\n * type: \"custom\",\n * handler: async (context) => {\n * if (context.text.includes(\"?\")) {\n * return { action: \"wait_for_input\", question: context.text };\n * }\n * return { action: \"continue\" };\n * }\n * })\n * ```\n */\n withTextOnlyHandler(handler: TextOnlyHandler): this {\n this.textOnlyHandler = handler;\n return this;\n }\n\n /**\n * Set the handler for text content that appears alongside gadget calls.\n *\n * When set, text accompanying gadget responses will be wrapped as a\n * synthetic gadget call before the actual gadget results in the\n * conversation history.\n *\n * @param handler - Configuration for wrapping text\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Wrap text as TellUser gadget\n * .withTextWithGadgetsHandler({\n * gadgetName: \"TellUser\",\n * parameterMapping: (text) => ({ message: text, done: false, type: \"info\" }),\n * resultMapping: (text) => `ℹ️ ${text}`,\n * })\n * ```\n */\n withTextWithGadgetsHandler(handler: {\n gadgetName: string;\n parameterMapping: (text: string) => Record<string, unknown>;\n resultMapping?: (text: string) => string;\n }): this {\n this.textWithGadgetsHandler = handler;\n return this;\n }\n\n /**\n * Set whether to stop gadget execution on first error.\n *\n * When true (default), if a gadget fails:\n * - Subsequent gadgets in the same response are skipped\n * - LLM stream is cancelled to save costs\n * - Agent loop continues with error in context\n *\n * When false:\n * - All gadgets in the response still execute\n * - LLM stream continues to completion\n *\n * @param stop - Whether to stop on gadget error\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withStopOnGadgetError(false)\n * ```\n */\n withStopOnGadgetError(stop: boolean): this {\n this.stopOnGadgetError = stop;\n return this;\n }\n\n /**\n * Set custom error handling logic.\n *\n * Provides fine-grained control over whether to continue after different types of errors.\n * Overrides `stopOnGadgetError` when provided.\n *\n * **Note:** This builder method configures the underlying `shouldContinueAfterError` option\n * in `AgentOptions`. The method is named `withErrorHandler` for better developer experience,\n * but maps to the `shouldContinueAfterError` property internally.\n *\n * @param handler - Function that decides whether to continue after an error.\n * Return `true` to continue execution, `false` to stop.\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withErrorHandler((context) => {\n * // Stop on parse errors, continue on validation/execution errors\n * if (context.errorType === \"parse\") {\n * return false;\n * }\n * if (context.error.includes(\"CRITICAL\")) {\n * return false;\n * }\n * return true;\n * })\n * ```\n */\n withErrorHandler(\n handler: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>,\n ): this {\n this.shouldContinueAfterError = handler;\n return this;\n }\n\n /**\n * Set default timeout for gadget execution.\n *\n * @param timeoutMs - Timeout in milliseconds (must be non-negative)\n * @returns This builder for chaining\n * @throws {Error} If timeout is negative\n *\n * @example\n * ```typescript\n * .withDefaultGadgetTimeout(5000) // 5 second timeout\n * ```\n */\n withDefaultGadgetTimeout(timeoutMs: number): this {\n if (timeoutMs < 0) {\n throw new Error(\"Timeout must be a non-negative number\");\n }\n this.defaultGadgetTimeoutMs = timeoutMs;\n return this;\n }\n\n /**\n * Enable or disable gadget output limiting.\n *\n * When enabled, gadget outputs exceeding the configured limit are stored\n * and can be browsed using the GadgetOutputViewer gadget.\n *\n * @param enabled - Whether to enable output limiting (default: true)\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetOutputLimit(false) // Disable output limiting\n * ```\n */\n withGadgetOutputLimit(enabled: boolean): this {\n this.gadgetOutputLimit = enabled;\n return this;\n }\n\n /**\n * Set the maximum gadget output as a percentage of the model's context window.\n *\n * Outputs exceeding this limit are stored for later browsing with GadgetOutputViewer.\n *\n * @param percent - Percentage of context window (1-100, default: 15)\n * @returns This builder for chaining\n * @throws {Error} If percent is not between 1 and 100\n *\n * @example\n * ```typescript\n * .withGadgetOutputLimitPercent(25) // 25% of context window\n * ```\n */\n withGadgetOutputLimitPercent(percent: number): this {\n if (percent < 1 || percent > 100) {\n throw new Error(\"Output limit percent must be between 1 and 100\");\n }\n this.gadgetOutputLimitPercent = percent;\n return this;\n }\n\n /**\n * Configure context compaction.\n *\n * Context compaction automatically manages conversation history to prevent\n * context window overflow in long-running agent conversations.\n *\n * @param config - Compaction configuration options\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Custom thresholds\n * .withCompaction({\n * triggerThresholdPercent: 70,\n * targetPercent: 40,\n * preserveRecentTurns: 10,\n * })\n *\n * // Different strategy\n * .withCompaction({\n * strategy: 'sliding-window',\n * })\n *\n * // With callback\n * .withCompaction({\n * onCompaction: (event) => {\n * console.log(`Saved ${event.tokensBefore - event.tokensAfter} tokens`);\n * }\n * })\n * ```\n */\n withCompaction(config: CompactionConfig): this {\n this.compactionConfig = { ...config, enabled: config.enabled ?? true };\n return this;\n }\n\n /**\n * Disable context compaction.\n *\n * By default, compaction is enabled. Use this method to explicitly disable it.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withoutCompaction() // Disable automatic compaction\n * ```\n */\n withoutCompaction(): this {\n this.compactionConfig = { enabled: false };\n return this;\n }\n\n /**\n * Add a synthetic gadget call to the conversation history.\n *\n * This is useful for in-context learning - showing the LLM what \"past self\"\n * did correctly so it mimics the pattern. The call is formatted with proper\n * markers and parameter format.\n *\n * @param gadgetName - Name of the gadget\n * @param parameters - Parameters passed to the gadget\n * @param result - Result returned by the gadget\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withSyntheticGadgetCall(\n * 'TellUser',\n * {\n * message: '👋 Hello!\\n\\nHere\\'s what I can do:\\n- Analyze code\\n- Run commands',\n * done: false,\n * type: 'info'\n * },\n * 'ℹ️ 👋 Hello!\\n\\nHere\\'s what I can do:\\n- Analyze code\\n- Run commands'\n * )\n * ```\n */\n withSyntheticGadgetCall(\n gadgetName: string,\n parameters: Record<string, unknown>,\n result: string,\n ): this {\n const startPrefix = this.gadgetStartPrefix ?? GADGET_START_PREFIX;\n const endPrefix = this.gadgetEndPrefix ?? GADGET_END_PREFIX;\n\n const paramStr = this.formatBlockParameters(parameters, \"\");\n\n // Assistant message with gadget call\n this.initialMessages.push({\n role: \"assistant\",\n content: `${startPrefix}${gadgetName}\\n${paramStr}\\n${endPrefix}`,\n });\n\n // User message with result\n this.initialMessages.push({\n role: \"user\",\n content: `Result: ${result}`,\n });\n\n return this;\n }\n\n /**\n * Format parameters as block format with JSON Pointer paths.\n */\n private formatBlockParameters(params: Record<string, unknown>, prefix: string): string {\n const lines: string[] = [];\n const argPrefix = this.gadgetArgPrefix ?? GADGET_ARG_PREFIX;\n\n for (const [key, value] of Object.entries(params)) {\n const fullPath = prefix ? `${prefix}/${key}` : key;\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n const itemPath = `${fullPath}/${index}`;\n if (typeof item === \"object\" && item !== null) {\n lines.push(this.formatBlockParameters(item as Record<string, unknown>, itemPath));\n } else {\n lines.push(`${argPrefix}${itemPath}`);\n lines.push(String(item));\n }\n });\n } else if (typeof value === \"object\" && value !== null) {\n lines.push(this.formatBlockParameters(value as Record<string, unknown>, fullPath));\n } else {\n lines.push(`${argPrefix}${fullPath}`);\n lines.push(String(value));\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n /**\n * Build and create the agent with the given user prompt.\n * Returns the Agent instance ready to run.\n *\n * @param userPrompt - User's question or request\n * @returns Configured Agent instance\n *\n * @example\n * ```typescript\n * const agent = await LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator)\n * .ask(\"What is 2+2?\");\n *\n * for await (const event of agent.run()) {\n * // handle events\n * }\n * ```\n */\n ask(userPrompt: string): Agent {\n // Lazy import to avoid circular dependency\n if (!this.client) {\n const { LLMist: LLMistClass } =\n require(\"../core/client.js\") as typeof import(\"../core/client.js\");\n this.client = new LLMistClass();\n }\n const registry = GadgetRegistry.from(this.gadgets);\n\n const options: AgentOptions = {\n client: this.client,\n model: this.model ?? \"openai:gpt-5-nano\",\n systemPrompt: this.systemPrompt,\n userPrompt,\n registry,\n maxIterations: this.maxIterations,\n temperature: this.temperature,\n logger: this.logger,\n hooks: this.hooks,\n promptConfig: this.promptConfig,\n initialMessages: this.initialMessages,\n onHumanInputRequired: this.onHumanInputRequired,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n textOnlyHandler: this.textOnlyHandler,\n textWithGadgetsHandler: this.textWithGadgetsHandler,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinueAfterError: this.shouldContinueAfterError,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n gadgetOutputLimit: this.gadgetOutputLimit,\n gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,\n compactionConfig: this.compactionConfig,\n };\n\n return new Agent(AGENT_INTERNAL_KEY, options);\n }\n\n /**\n * Build, run, and collect only the text response.\n * Convenient for simple queries where you just want the final answer.\n *\n * @param userPrompt - User's question or request\n * @returns Promise resolving to the complete text response\n *\n * @example\n * ```typescript\n * const answer = await LLMist.createAgent()\n * .withModel(\"gpt4-mini\")\n * .withGadgets(Calculator)\n * .askAndCollect(\"What is 42 * 7?\");\n *\n * console.log(answer); // \"294\"\n * ```\n */\n async askAndCollect(userPrompt: string): Promise<string> {\n const agent = this.ask(userPrompt);\n return collectText(agent.run());\n }\n\n /**\n * Build and run with event handlers.\n * Combines agent creation and event handling in one call.\n *\n * @param userPrompt - User's question or request\n * @param handlers - Event handlers\n *\n * @example\n * ```typescript\n * await LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator)\n * .askWith(\"What is 2+2?\", {\n * onText: (text) => console.log(\"LLM:\", text),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\n async askWith(userPrompt: string, handlers: EventHandlers): Promise<void> {\n const agent = this.ask(userPrompt);\n await agent.runWith(handlers);\n }\n\n /**\n * Build the agent without a user prompt.\n *\n * Returns an Agent instance that can be inspected (e.g., check registered gadgets)\n * but cannot be run without first calling .ask(prompt).\n *\n * This is useful for:\n * - Testing: Inspect the registry, configuration, etc.\n * - Advanced use cases: Build agent configuration separately from execution\n *\n * @returns Configured Agent instance (without user prompt)\n *\n * @example\n * ```typescript\n * // Build agent for inspection\n * const agent = new AgentBuilder()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator, Weather)\n * .build();\n *\n * // Inspect registered gadgets\n * console.log(agent.getRegistry().getNames()); // ['Calculator', 'Weather']\n *\n * // Note: Calling agent.run() will throw an error\n * // Use .ask(prompt) instead if you want to run the agent\n * ```\n */\n build(): Agent {\n // Lazy import to avoid circular dependency\n if (!this.client) {\n const { LLMist: LLMistClass } =\n require(\"../core/client.js\") as typeof import(\"../core/client.js\");\n this.client = new LLMistClass();\n }\n const registry = GadgetRegistry.from(this.gadgets);\n\n const options: AgentOptions = {\n client: this.client,\n model: this.model ?? \"openai:gpt-5-nano\",\n systemPrompt: this.systemPrompt,\n // No userPrompt - agent.run() will throw if called directly\n registry,\n maxIterations: this.maxIterations,\n temperature: this.temperature,\n logger: this.logger,\n hooks: this.hooks,\n promptConfig: this.promptConfig,\n initialMessages: this.initialMessages,\n onHumanInputRequired: this.onHumanInputRequired,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n textOnlyHandler: this.textOnlyHandler,\n textWithGadgetsHandler: this.textWithGadgetsHandler,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinueAfterError: this.shouldContinueAfterError,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n gadgetOutputLimit: this.gadgetOutputLimit,\n gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,\n compactionConfig: this.compactionConfig,\n };\n\n return new Agent(AGENT_INTERNAL_KEY, options);\n }\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 gadget: \"gadget\",\n} as const;\n\n/** Valid log level names */\nexport const LOG_LEVELS = [\"silly\", \"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"] as const;\nexport type LogLevelName = (typeof LOG_LEVELS)[number];\n\n/** Default model used when --model is not specified */\nexport const DEFAULT_MODEL = \"openai:gpt-5-nano\";\n\n/** Command-line option flags */\nexport const OPTION_FLAGS = {\n model: \"-m, --model <identifier>\",\n systemPrompt: \"-s, --system <prompt>\",\n temperature: \"-t, --temperature <value>\",\n maxTokens: \"--max-tokens <count>\",\n maxIterations: \"-i, --max-iterations <count>\",\n gadgetModule: \"-g, --gadget <module>\",\n logLevel: \"--log-level <level>\",\n logFile: \"--log-file <path>\",\n logReset: \"--log-reset\",\n logLlmRequests: \"--log-llm-requests [dir]\",\n logLlmResponses: \"--log-llm-responses [dir]\",\n noBuiltins: \"--no-builtins\",\n noBuiltinInteraction: \"--no-builtin-interaction\",\n quiet: \"-q, --quiet\",\n} as const;\n\n/** Human-readable descriptions for command-line options */\nexport const OPTION_DESCRIPTIONS = {\n model: \"Model identifier, e.g. openai:gpt-5-nano or anthropic:claude-sonnet-4-5.\",\n systemPrompt: \"Optional system prompt prepended to the conversation.\",\n temperature: \"Sampling temperature between 0 and 2.\",\n maxTokens: \"Maximum number of output tokens requested from the model.\",\n maxIterations: \"Maximum number of agent loop iterations before exiting.\",\n gadgetModule:\n \"Path or module specifier for a gadget export. Repeat to register multiple gadgets.\",\n logLevel: \"Log level: silly, trace, debug, info, warn, error, fatal.\",\n logFile: \"Path to log file. When set, logs are written to file instead of stderr.\",\n logReset: \"Reset (truncate) the log file at session start instead of appending.\",\n logLlmRequests: \"Save raw LLM requests as plain text. Optional dir, defaults to ~/.llmist/logs/requests/\",\n logLlmResponses: \"Save raw LLM responses as plain text. Optional dir, defaults to ~/.llmist/logs/responses/\",\n noBuiltins: \"Disable built-in gadgets (AskUser, TellUser).\",\n noBuiltinInteraction: \"Disable interactive gadgets (AskUser) while keeping TellUser.\",\n quiet: \"Suppress all output except content (text and TellUser messages).\",\n} as const;\n\n/** Prefix for summary output written to stderr */\nexport const SUMMARY_PREFIX = \"[llmist]\";\n","import { Command, InvalidArgumentError } from \"commander\";\n\nimport packageJson from \"../../package.json\";\n\nimport { registerAgentCommand } from \"./agent-command.js\";\nimport { registerCompleteCommand } from \"./complete-command.js\";\nimport {\n type CLIConfig,\n type CustomCommandConfig,\n getCustomCommandNames,\n loadConfig,\n} from \"./config.js\";\nimport { registerGadgetCommand } from \"./gadget-command.js\";\nimport { registerModelsCommand } from \"./models-command.js\";\nimport { registerCustomCommand } from \"./custom-command.js\";\nimport {\n CLI_DESCRIPTION,\n CLI_NAME,\n LOG_LEVELS,\n type LogLevelName,\n OPTION_DESCRIPTIONS,\n OPTION_FLAGS,\n} from \"./constants.js\";\nimport type { CLIEnvironment, CLILoggerConfig } from \"./environment.js\";\nimport { createDefaultEnvironment } from \"./environment.js\";\n\n/**\n * Parses and validates the log level option value.\n */\nfunction parseLogLevel(value: string): LogLevelName {\n const normalized = value.toLowerCase() as LogLevelName;\n if (!LOG_LEVELS.includes(normalized)) {\n throw new InvalidArgumentError(`Log level must be one of: ${LOG_LEVELS.join(\", \")}`);\n }\n return normalized;\n}\n\n/**\n * Global CLI options that apply to all commands.\n */\ninterface GlobalOptions {\n logLevel?: LogLevelName;\n logFile?: string;\n logReset?: boolean;\n}\n\n/**\n * Creates and configures the CLI program with complete and agent commands.\n *\n * @param env - CLI environment configuration for I/O and dependencies\n * @param config - Optional CLI configuration loaded from config file\n * @returns Configured Commander program ready for parsing\n */\nexport function createProgram(env: CLIEnvironment, config?: CLIConfig): Command {\n const program = new Command();\n\n program\n .name(CLI_NAME)\n .description(CLI_DESCRIPTION)\n .version(packageJson.version)\n .option(OPTION_FLAGS.logLevel, OPTION_DESCRIPTIONS.logLevel, parseLogLevel)\n .option(OPTION_FLAGS.logFile, OPTION_DESCRIPTIONS.logFile)\n .option(OPTION_FLAGS.logReset, OPTION_DESCRIPTIONS.logReset)\n .configureOutput({\n writeOut: (str) => env.stdout.write(str),\n writeErr: (str) => env.stderr.write(str),\n });\n\n // Register built-in commands with config defaults\n registerCompleteCommand(program, env, config?.complete);\n registerAgentCommand(program, env, config?.agent);\n registerModelsCommand(program, env);\n registerGadgetCommand(program, env);\n\n // Register custom commands from config\n if (config) {\n const customNames = getCustomCommandNames(config);\n for (const name of customNames) {\n const cmdConfig = config[name] as CustomCommandConfig;\n registerCustomCommand(program, name, cmdConfig, env);\n }\n }\n\n return program;\n}\n\n/**\n * Options for runCLI function.\n */\nexport interface RunCLIOptions {\n /** Environment overrides for testing or customization */\n env?: Partial<CLIEnvironment>;\n /** Config override - if provided, skips loading from file. Use {} to disable config. */\n config?: CLIConfig;\n}\n\n/**\n * Main entry point for running the CLI.\n * Creates environment, parses arguments, and executes the appropriate command.\n *\n * @param overrides - Optional environment overrides or options object\n */\nexport async function runCLI(\n overrides: Partial<CLIEnvironment> | RunCLIOptions = {},\n): Promise<void> {\n // Handle both old signature (Partial<CLIEnvironment>) and new signature (RunCLIOptions)\n const opts: RunCLIOptions =\n \"env\" in overrides || \"config\" in overrides\n ? (overrides as RunCLIOptions)\n : { env: overrides as Partial<CLIEnvironment> };\n\n // Load config early (before program creation) - errors here should fail fast\n // If config is provided in options, use it instead of loading from file\n const config = opts.config !== undefined ? opts.config : loadConfig();\n const envOverrides = opts.env ?? {};\n\n // First pass: parse global options only (skip if help requested)\n const preParser = new Command();\n preParser\n .option(OPTION_FLAGS.logLevel, OPTION_DESCRIPTIONS.logLevel, parseLogLevel)\n .option(OPTION_FLAGS.logFile, OPTION_DESCRIPTIONS.logFile)\n .option(OPTION_FLAGS.logReset, OPTION_DESCRIPTIONS.logReset)\n .allowUnknownOption()\n .allowExcessArguments()\n .helpOption(false); // Don't intercept --help\n\n preParser.parse(process.argv);\n const globalOpts = preParser.opts<GlobalOptions>();\n\n // Create environment with logger config from global options\n // Priority: CLI flags > config file > defaults\n const loggerConfig: CLILoggerConfig = {\n logLevel: globalOpts.logLevel ?? config.global?.[\"log-level\"],\n logFile: globalOpts.logFile ?? config.global?.[\"log-file\"],\n logReset: globalOpts.logReset ?? config.global?.[\"log-reset\"],\n };\n\n const defaultEnv = createDefaultEnvironment(loggerConfig);\n const env: CLIEnvironment = { ...defaultEnv, ...envOverrides };\n const program = createProgram(env, config);\n await program.parseAsync(env.argv);\n}\n","{\n \"name\": \"llmist\",\n \"version\": \"1.3.0\",\n \"description\": \"Universal TypeScript LLM client with streaming-first agent framework. Works with any model - no structured outputs or native tool calling required. Implements its own flexible grammar for function calling.\",\n \"type\": \"module\",\n \"main\": \"dist/index.cjs\",\n \"module\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./testing\": {\n \"import\": {\n \"types\": \"./dist/testing/index.d.ts\",\n \"default\": \"./dist/testing/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/testing/index.d.cts\",\n \"default\": \"./dist/testing/index.cjs\"\n }\n }\n },\n \"scripts\": {\n \"cli\": \"bun run scripts/cli-runner.ts\",\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"lint\": \"biome lint .\",\n \"format\": \"biome format --write .\",\n \"check\": \"biome check --write .\",\n \"test\": \"bun test\",\n \"test:unit\": \"bun test src/agent src/core src/gadgets src/providers src/testing\",\n \"test:watch\": \"bun test --watch\",\n \"test:e2e\": \"bun test src/e2e --timeout 60000 --bail 1\",\n \"test:e2e:watch\": \"bun test src/e2e --watch --timeout 60000\",\n \"test:all\": \"bun run test && bun run test:e2e\",\n \"clean\": \"rimraf dist\",\n \"prepare\": \"node scripts/install-hooks.js || true\",\n \"release:dry\": \"bunx semantic-release --dry-run\"\n },\n \"bin\": {\n \"llmist\": \"dist/cli.js\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/zbigniewsobiecki/llmist.git\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"files\": [\n \"dist\"\n ],\n \"keywords\": [\n \"llm\",\n \"ai\",\n \"agent\",\n \"agents\",\n \"openai\",\n \"anthropic\",\n \"claude\",\n \"gemini\",\n \"gpt\",\n \"streaming\",\n \"function-calling\",\n \"tool-calling\",\n \"typescript\",\n \"universal-client\",\n \"multi-provider\",\n \"hooks\",\n \"gadgets\"\n ],\n \"author\": \"\",\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@anthropic-ai/sdk\": \"^0.69.0\",\n \"@google/genai\": \"^1.27.0\",\n \"chalk\": \"^5.6.2\",\n \"commander\": \"^12.1.0\",\n \"eta\": \"^4.4.1\",\n \"js-toml\": \"^1.0.2\",\n \"js-yaml\": \"^4.1.0\",\n \"marked\": \"^15.0.12\",\n \"marked-terminal\": \"^7.3.0\",\n \"openai\": \"^6.0.0\",\n \"tiktoken\": \"^1.0.22\",\n \"tslog\": \"^4.10.2\",\n \"zod\": \"^4.1.12\"\n },\n \"devDependencies\": {\n \"@biomejs/biome\": \"^2.3.2\",\n \"@commitlint/cli\": \"^20.1.0\",\n \"@commitlint/config-conventional\": \"^20.0.0\",\n \"@semantic-release/changelog\": \"^6.0.3\",\n \"@semantic-release/git\": \"^10.0.1\",\n \"@types/js-yaml\": \"^4.0.9\",\n \"@types/marked-terminal\": \"^6.1.1\",\n \"@types/node\": \"^20.12.7\",\n \"bun-types\": \"^1.3.2\",\n \"dotenv\": \"^17.2.3\",\n \"rimraf\": \"^5.0.5\",\n \"semantic-release\": \"^25.0.2\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^5.4.5\"\n }\n}\n","import { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport type { Command } from \"commander\";\nimport { AgentBuilder } from \"../agent/builder.js\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { TokenUsage } from \"../core/options.js\";\nimport { GadgetRegistry } from \"../gadgets/registry.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"../providers/constants.js\";\nimport { builtinGadgets } from \"./builtin-gadgets.js\";\nimport type { AgentConfig } from \"./config.js\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { loadGadgets } from \"./gadgets.js\";\nimport { formatLlmRequest, resolveLogDir, writeLogFile } from \"./llm-logging.js\";\nimport { addAgentOptions, type AgentCommandOptions } from \"./option-helpers.js\";\nimport {\n executeAction,\n isInteractive,\n renderSummary,\n resolvePrompt,\n StreamPrinter,\n StreamProgress,\n} from \"./utils.js\";\nimport {\n formatGadgetSummary,\n renderMarkdownWithSeparators,\n renderOverallSummary,\n} from \"./ui/formatters.js\";\n\n/**\n * Prompts the user for approval with optional rejection feedback.\n * Used by the gating controller to approve dangerous gadget executions.\n *\n * SHOWCASE: This demonstrates how to build approval workflows using llmist's\n * controller hooks. The CLI gates RunCommand executions, but the pattern\n * can be applied to any gadget that needs user approval.\n *\n * @param env - CLI environment for I/O operations\n * @param prompt - The prompt to display to the user\n * @returns The user's input (empty string or \"y\" = approved, anything else = rejection reason)\n */\nasync function promptApproval(env: CLIEnvironment, prompt: string): Promise<string> {\n const rl = createInterface({ input: env.stdin, output: env.stderr });\n try {\n const answer = await rl.question(prompt);\n return answer.trim();\n } finally {\n rl.close();\n }\n}\n\n/**\n * Creates a human input handler for interactive mode.\n * Only returns a handler if stdin is a TTY (terminal), not a pipe.\n *\n * @param env - CLI environment\n * @param progress - Progress indicator to pause during input\n * @returns Human input handler function or undefined if not interactive\n */\nfunction createHumanInputHandler(\n env: CLIEnvironment,\n progress: StreamProgress,\n): ((question: string) => Promise<string>) | undefined {\n const stdout = env.stdout as NodeJS.WriteStream;\n if (!isInteractive(env.stdin) || typeof stdout.isTTY !== \"boolean\" || !stdout.isTTY) {\n return undefined;\n }\n\n return async (question: string): Promise<string> => {\n progress.pause(); // Pause progress indicator during human input\n const rl = createInterface({ input: env.stdin, output: env.stdout });\n try {\n // Display question on first prompt only (with markdown rendering and separators)\n const questionLine = question.trim() ? `\\n${renderMarkdownWithSeparators(question.trim())}` : \"\";\n let isFirst = true;\n\n // Loop until non-empty input (like a REPL)\n while (true) {\n const statsPrompt = progress.formatPrompt();\n const prompt = isFirst ? `${questionLine}\\n${statsPrompt}` : statsPrompt;\n isFirst = false;\n\n const answer = await rl.question(prompt);\n const trimmed = answer.trim();\n if (trimmed) {\n return trimmed;\n }\n // Empty input - show prompt again (no question repeat)\n }\n } finally {\n rl.close();\n }\n };\n}\n\n// formatGadgetSummary is now imported from ./ui/formatters.js\n// This demonstrates clean code organization and reusability\n\n/**\n * Executes the agent command.\n *\n * SHOWCASE: This function demonstrates how to build a production-grade CLI\n * on top of llmist's core capabilities:\n *\n * 1. **Dynamic gadget loading** - GadgetRegistry for plugin-like extensibility\n * 2. **Observer hooks** - Custom progress tracking and real-time UI updates\n * 3. **Event-driven execution** - React to agent events (text, gadget results)\n * 4. **ModelRegistry integration** - Automatic cost estimation and tracking\n * 5. **Streaming support** - Display LLM output as it's generated\n * 6. **Human-in-the-loop** - Interactive prompts during agent execution\n * 7. **Clean separation** - stdout for content, stderr for metrics/progress\n *\n * The implementation showcases llmist's flexibility: from simple scripts to\n * polished CLIs with spinners, cost tracking, and real-time feedback.\n *\n * @param promptArg - User prompt from command line argument (optional if using stdin)\n * @param options - Agent command options (model, gadgets, max iterations, etc.)\n * @param env - CLI environment for I/O operations\n */\nexport async function executeAgent(\n promptArg: string | undefined,\n options: AgentCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const prompt = await resolvePrompt(promptArg, env);\n const client = env.createClient();\n\n // SHOWCASE: llmist's GadgetRegistry for dynamic tool loading\n // This demonstrates how to build extensible CLIs with plugin-like functionality\n const registry = new GadgetRegistry();\n\n // Register built-in gadgets for basic agent interaction\n // SHOWCASE: Built-in gadgets enable conversation without any custom tools\n //\n // AskUser: Prompts user for input during agent execution\n // TellUser: Displays formatted messages and optionally ends the loop\n //\n // Flags control built-in behavior:\n // --no-builtins: Exclude all built-in gadgets\n // --no-builtin-interaction: Exclude only AskUser (keeps TellUser for output)\n //\n // AskUser is also auto-excluded when stdin is not interactive (piped input)\n const stdinIsInteractive = isInteractive(env.stdin);\n if (options.builtins !== false) {\n for (const gadget of builtinGadgets) {\n // Skip AskUser if:\n // 1. --no-builtin-interaction is set, OR\n // 2. stdin is not interactive (piped input) - AskUser can't work anyway\n if (gadget.name === \"AskUser\" && (options.builtinInteraction === false || !stdinIsInteractive)) {\n continue;\n }\n registry.registerByClass(gadget);\n }\n }\n\n // Load user-provided gadgets from file paths\n // SHOWCASE: Dynamic gadget loading enables custom tools without recompiling\n // Users can provide gadgets via -g/--gadget flag, supporting any TypeScript class\n const gadgetSpecifiers = options.gadget ?? [];\n if (gadgetSpecifiers.length > 0) {\n const gadgets = await loadGadgets(gadgetSpecifiers, process.cwd());\n for (const gadget of gadgets) {\n // Later registrations can override earlier ones\n // This allows users to customize built-in behavior\n registry.registerByClass(gadget);\n }\n }\n\n const printer = new StreamPrinter(env.stdout);\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n const progress = new StreamProgress(env.stderr, stderrTTY, client.modelRegistry);\n\n let usage: TokenUsage | undefined;\n let iterations = 0;\n\n // Resolve LLM debug log directories (if enabled)\n const llmRequestsDir = resolveLogDir(options.logLlmRequests, \"requests\");\n const llmResponsesDir = resolveLogDir(options.logLlmResponses, \"responses\");\n let llmCallCounter = 0;\n\n // Count tokens accurately using provider-specific methods\n const countMessagesTokens = async (model: string, messages: LLMMessage[]): Promise<number> => {\n try {\n return await client.countTokens(model, messages);\n } catch {\n // Fallback to character-based estimation if counting fails\n const totalChars = messages.reduce((sum, m) => sum + (m.content?.length ?? 0), 0);\n return Math.round(totalChars / FALLBACK_CHARS_PER_TOKEN);\n }\n };\n\n // Count tokens for gadget output text\n const countGadgetOutputTokens = async (output: string | undefined): Promise<number | undefined> => {\n if (!output) return undefined;\n try {\n // Wrap gadget output as assistant message for accurate token counting\n const messages: LLMMessage[] = [{ role: \"assistant\", content: output }];\n return await client.countTokens(options.model, messages);\n } catch {\n // Fallback: return undefined to trigger byte count fallback in formatter\n return undefined;\n }\n };\n\n // Build the agent with hooks for progress tracking\n // SHOWCASE: This demonstrates llmist's observer pattern for building custom UIs\n //\n // For simpler use cases, use HookPresets.progressTracking() instead:\n // .withHooks(HookPresets.progressTracking({\n // modelRegistry: client.modelRegistry,\n // onProgress: (stats) => { /* update your UI */ }\n // }))\n //\n // The CLI uses custom hooks for fine-grained control over the spinner animation\n // and real-time updates, showcasing llmist's flexibility for building polished UIs.\n const builder = new AgentBuilder(client)\n .withModel(options.model)\n .withLogger(env.createLogger(\"llmist:cli:agent\"))\n .withHooks({\n observers: {\n // onLLMCallStart: Start progress indicator for each LLM call\n // This showcases how to react to agent lifecycle events\n onLLMCallStart: async (context) => {\n llmCallCounter++;\n\n // Count input tokens accurately using provider-specific methods\n // This ensures we never show ~ for input tokens\n const inputTokens = await countMessagesTokens(\n context.options.model,\n context.options.messages,\n );\n progress.startCall(context.options.model, inputTokens);\n // Mark input tokens as accurate (not estimated)\n progress.setInputTokens(inputTokens, false);\n\n // Write LLM request to debug log if enabled\n if (llmRequestsDir) {\n const filename = `${Date.now()}_call_${llmCallCounter}.request.txt`;\n const content = formatLlmRequest(context.options.messages);\n await writeLogFile(llmRequestsDir, filename, content);\n }\n },\n // onStreamChunk: Real-time updates as LLM generates tokens\n // This enables responsive UIs that show progress during generation\n onStreamChunk: async (context) => {\n // Update estimated output tokens from accumulated text length\n progress.update(context.accumulatedText.length);\n\n // Use exact token counts when available from streaming response\n // SHOWCASE: Provider responses include token usage for accurate tracking\n if (context.usage) {\n if (context.usage.inputTokens) {\n progress.setInputTokens(context.usage.inputTokens, false);\n }\n if (context.usage.outputTokens) {\n progress.setOutputTokens(context.usage.outputTokens, false);\n }\n // Update cached token counts for live cost estimation\n progress.setCachedTokens(\n context.usage.cachedInputTokens ?? 0,\n context.usage.cacheCreationInputTokens ?? 0,\n );\n }\n },\n\n // onLLMCallComplete: Finalize metrics after each LLM call\n // This is where you'd typically log metrics or update dashboards\n onLLMCallComplete: async (context) => {\n // Capture completion metadata for final summary\n usage = context.usage;\n iterations = Math.max(iterations, context.iteration + 1);\n\n // Update with final exact token counts from provider\n // SHOWCASE: llmist normalizes token usage across all providers\n if (context.usage) {\n if (context.usage.inputTokens) {\n progress.setInputTokens(context.usage.inputTokens, false);\n }\n if (context.usage.outputTokens) {\n progress.setOutputTokens(context.usage.outputTokens, false);\n }\n }\n\n // Calculate per-call cost for the summary (accounting for cached tokens)\n // Use context.options.model (resolved) instead of options.model (raw CLI input)\n // This ensures aliases like \"sonnet\" are resolved to \"claude-sonnet-4-5\"\n let callCost: number | undefined;\n if (context.usage && client.modelRegistry) {\n try {\n const modelName = context.options.model.includes(\":\")\n ? context.options.model.split(\":\")[1]\n : context.options.model;\n const costResult = client.modelRegistry.estimateCost(\n modelName,\n context.usage.inputTokens,\n context.usage.outputTokens,\n context.usage.cachedInputTokens ?? 0,\n context.usage.cacheCreationInputTokens ?? 0,\n );\n if (costResult) callCost = costResult.totalCost;\n } catch {\n // Ignore cost calculation errors\n }\n }\n\n // Get per-call elapsed time before endCall resets it\n const callElapsed = progress.getCallElapsedSeconds();\n\n // End this call's progress tracking and switch to cumulative mode\n progress.endCall(context.usage);\n\n // SHOWCASE: Print per-call summary after each LLM call\n // This gives users visibility into each iteration's metrics\n // Skip summaries in quiet mode\n if (!options.quiet) {\n const summary = renderSummary({\n iterations: context.iteration + 1,\n model: options.model,\n usage: context.usage,\n elapsedSeconds: callElapsed,\n cost: callCost,\n finishReason: context.finishReason,\n });\n if (summary) {\n env.stderr.write(`${summary}\\n`);\n }\n }\n\n // Write LLM response to debug log if enabled\n if (llmResponsesDir) {\n const filename = `${Date.now()}_call_${llmCallCounter}.response.txt`;\n await writeLogFile(llmResponsesDir, filename, context.rawResponse);\n }\n },\n },\n\n // SHOWCASE: Controller-based approval gating for dangerous gadgets\n //\n // This demonstrates how to add safety layers WITHOUT modifying gadgets.\n // The RunCommand gadget is simple - it just executes commands. The CLI\n // adds the approval flow externally via beforeGadgetExecution controller.\n //\n // This pattern is composable: you can apply the same gating logic to\n // any gadget (DeleteFile, SendEmail, etc.) without changing the gadgets.\n controllers: {\n beforeGadgetExecution: async (ctx) => {\n // Only gate RunCommand - let other gadgets through\n if (ctx.gadgetName !== \"RunCommand\") {\n return { action: \"proceed\" };\n }\n\n // Only prompt for approval in interactive mode\n const stdinTTY = isInteractive(env.stdin);\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n if (!stdinTTY || !stderrTTY) {\n // Non-interactive mode: deny by default for safety\n return {\n action: \"skip\",\n syntheticResult:\n \"status=denied\\n\\nRunCommand requires interactive approval. Run in a terminal to approve commands.\",\n };\n }\n\n const command = ctx.parameters.command as string;\n\n // Pause progress indicator and prompt for approval\n progress.pause();\n env.stderr.write(`\\n🔒 Execute: ${chalk.cyan(command)}\\n`);\n\n const response = await promptApproval(env, \" ⏎ approve, or type to reject: \");\n\n // Empty input or \"y\"/\"Y\" = approved\n const isApproved = response === \"\" || response.toLowerCase() === \"y\";\n\n if (!isApproved) {\n env.stderr.write(` ${chalk.red(\"✗ Denied\")}\\n\\n`);\n return {\n action: \"skip\",\n syntheticResult: `status=denied\\n\\nCommand rejected by user with message: \"${response}\"`,\n };\n }\n\n env.stderr.write(` ${chalk.green(\"✓ Approved\")}\\n`);\n return { action: \"proceed\" };\n },\n },\n });\n\n // Add optional configurations\n if (options.system) {\n builder.withSystem(options.system);\n }\n if (options.maxIterations !== undefined) {\n builder.withMaxIterations(options.maxIterations);\n }\n if (options.temperature !== undefined) {\n builder.withTemperature(options.temperature);\n }\n\n const humanInputHandler = createHumanInputHandler(env, progress);\n if (humanInputHandler) {\n builder.onHumanInput(humanInputHandler);\n }\n\n // Add gadgets from the registry\n const gadgets = registry.getAll();\n if (gadgets.length > 0) {\n builder.withGadgets(...gadgets);\n }\n\n // Set custom gadget markers if configured, otherwise use library defaults\n if (options.gadgetStartPrefix) {\n builder.withGadgetStartPrefix(options.gadgetStartPrefix);\n }\n if (options.gadgetEndPrefix) {\n builder.withGadgetEndPrefix(options.gadgetEndPrefix);\n }\n if (options.gadgetArgPrefix) {\n builder.withGadgetArgPrefix(options.gadgetArgPrefix);\n }\n\n // Inject synthetic heredoc example for in-context learning\n // This teaches the LLM to use heredoc syntax (<<<EOF...EOF) for multiline strings\n // by showing what \"past self\" did correctly. LLMs mimic patterns in conversation history.\n builder.withSyntheticGadgetCall(\n \"TellUser\",\n {\n message:\n \"👋 Hello! I'm ready to help.\\n\\nHere's what I can do:\\n- Analyze your codebase\\n- Execute commands\\n- Answer questions\\n\\nWhat would you like me to work on?\",\n done: false,\n type: \"info\",\n },\n \"ℹ️ 👋 Hello! I'm ready to help.\\n\\nHere's what I can do:\\n- Analyze your codebase\\n- Execute commands\\n- Answer questions\\n\\nWhat would you like me to work on?\",\n );\n\n // Continue looping when LLM responds with just text (no gadget calls)\n // This allows multi-turn conversations where the LLM may explain before acting\n builder.withTextOnlyHandler(\"acknowledge\");\n\n // Wrap text that accompanies gadget calls as TellUser gadget calls\n // This keeps conversation history consistent and gadget-oriented\n builder.withTextWithGadgetsHandler({\n gadgetName: \"TellUser\",\n parameterMapping: (text) => ({ message: text, done: false, type: \"info\" }),\n resultMapping: (text) => `ℹ️ ${text}`,\n });\n\n // Build and start the agent\n const agent = builder.ask(prompt);\n\n // SHOWCASE: llmist's event-driven agent execution\n // The agent emits events as it runs, enabling reactive UIs\n //\n // Event types:\n // - \"text\": LLM-generated text chunks (streaming or complete)\n // - \"gadget_result\": Results from gadget/tool executions\n // - \"human_input_required\": Agent needs user input (handled via callback)\n //\n // This pattern allows building:\n // - Real-time streaming UIs\n // - Progress indicators during tool execution\n // - Separation of business logic (agent) from presentation (UI)\n\n // Buffer for accumulating text chunks - markdown rendering requires complete content\n let textBuffer = \"\";\n const flushTextBuffer = () => {\n if (textBuffer) {\n // Use separators in normal mode, plain text in quiet mode\n const output = options.quiet ? textBuffer : renderMarkdownWithSeparators(textBuffer);\n printer.write(output);\n textBuffer = \"\";\n }\n };\n\n for await (const event of agent.run()) {\n if (event.type === \"text\") {\n // Accumulate text chunks - we'll render markdown when complete\n progress.pause();\n textBuffer += event.content;\n } else if (event.type === \"gadget_result\") {\n // Flush any accumulated text before showing gadget result\n flushTextBuffer();\n // Show gadget execution feedback on stderr\n progress.pause();\n\n if (options.quiet) {\n // In quiet mode, only output TellUser messages (to stdout, plain unrendered text)\n if (event.result.gadgetName === \"TellUser\" && event.result.parameters?.message) {\n const message = String(event.result.parameters.message);\n env.stdout.write(`${message}\\n`);\n }\n } else {\n // Normal mode: show full gadget summary on stderr\n const tokenCount = await countGadgetOutputTokens(event.result.result);\n env.stderr.write(`${formatGadgetSummary({ ...event.result, tokenCount })}\\n`);\n }\n // Progress automatically resumes on next LLM call (via onLLMCallStart hook)\n }\n // Note: human_input_required handled by callback (see createHumanInputHandler)\n }\n\n // Flush any remaining buffered text with markdown rendering\n flushTextBuffer();\n\n progress.complete();\n printer.ensureNewline();\n\n // SHOWCASE: Show overall summary only if there were multiple iterations\n // Single-iteration runs already showed per-call summary, no need to repeat\n // Skip summaries in quiet mode\n if (!options.quiet && iterations > 1) {\n // Separator line to distinguish from per-call summaries\n env.stderr.write(`${chalk.dim(\"─\".repeat(40))}\\n`);\n\n const summary = renderOverallSummary({\n totalTokens: usage?.totalTokens,\n iterations,\n elapsedSeconds: progress.getTotalElapsedSeconds(),\n cost: progress.getTotalCost(),\n });\n if (summary) {\n env.stderr.write(`${summary}\\n`);\n }\n }\n}\n\n/**\n * Registers the agent command with the CLI program.\n * Configures options for model, gadgets, max iterations, temperature, and parameter format.\n *\n * @param program - Commander program to register the command with\n * @param env - CLI environment for dependencies and I/O\n * @param config - Optional configuration defaults from config file\n */\nexport function registerAgentCommand(\n program: Command,\n env: CLIEnvironment,\n config?: AgentConfig,\n): void {\n const cmd = program\n .command(COMMANDS.agent)\n .description(\"Run the llmist agent loop with optional gadgets.\")\n .argument(\"[prompt]\", \"Prompt for the agent loop. Falls back to stdin when available.\");\n\n addAgentOptions(cmd, config);\n\n cmd.action((prompt, options) =>\n executeAction(() => executeAgent(prompt, options as AgentCommandOptions, env), env),\n );\n}\n","/**\n * Built-in gadgets for CLI agent command.\n * These gadgets provide basic communication capabilities out-of-the-box.\n */\nimport { z } from \"zod\";\n\nimport { createGadget } from \"../gadgets/create-gadget.js\";\nimport {\n BreakLoopException,\n HumanInputException,\n} from \"../gadgets/exceptions.js\";\n\n/**\n * AskUser gadget - Asks the user a question and waits for their response.\n *\n * Use this when you need more information or clarification from the user.\n */\nexport const askUser = createGadget({\n name: \"AskUser\",\n description:\n \"Ask the user a question when you need more information or clarification. The user's response will be provided back to you.\",\n schema: z.object({\n question: z\n .string()\n .describe(\"The question to ask the user in plain-text or Markdown\"),\n }),\n examples: [\n {\n comment: \"Ask for clarification about the task\",\n params: { question: \"Which file would you like me to modify?\" },\n },\n {\n comment: \"Ask user to choose between options\",\n params: {\n question:\n \"I found multiple matches. Which one should I use?\\n- src/utils/helper.ts\\n- src/lib/helper.ts\",\n },\n },\n ],\n execute: ({ question }) => {\n throw new HumanInputException(question);\n },\n});\n\n/**\n * TellUser gadget - Outputs a message to the user.\n *\n * Use this for key results, warnings, or structured output that should stand out\n * from regular streamed text.\n */\nexport const tellUser = createGadget({\n name: \"TellUser\",\n description: \"Tell the user something important.\",\n schema: z.object({\n message: z\n .string()\n .optional()\n .describe(\"The message to display to the user in Markdown\"),\n type: z\n .enum([\"info\", \"success\", \"warning\", \"error\"])\n .default(\"info\")\n .describe(\"Message type: info, success, warning, or error\"),\n }),\n examples: [\n {\n comment: \"Warn the user about something\",\n params: {\n message: \"Found 3 files with potential issues. Continuing analysis...\",\n type: \"warning\",\n },\n },\n {\n comment: \"Share detailed analysis with bullet points (use heredoc for multiline)\",\n params: {\n message:\n \"Here's what I found in the codebase:\\n\\n1. **Main entry point**: `src/index.ts` exports all public APIs\\n2. **Core logic**: Located in `src/core/` with 5 modules\\n3. **Tests**: Good coverage in `src/__tests__/`\\n\\nI'll continue exploring the core modules.\",\n type: \"info\",\n },\n },\n ],\n execute: ({ message, type }) => {\n // Handle empty or missing message gracefully\n // This happens when LLM sends malformed parameters that fail to parse the message field\n if (!message || message.trim() === \"\") {\n return \"⚠️ TellUser was called without a message. Please provide content in the 'message' field.\";\n }\n\n // Format message for display, but return plain text for LLM context\n // This prevents ANSI color codes from polluting the conversation\n const prefixes = {\n info: \"ℹ️ \",\n success: \"✅ \",\n warning: \"⚠️ \",\n error: \"❌ \",\n };\n return prefixes[type] + message;\n },\n});\n\n/**\n * Finish gadget - Signals that the task is complete.\n *\n * Use this when you have completed all requested work and want to end the conversation.\n */\nexport const finish = createGadget({\n name: \"Finish\",\n description:\n \"Signal that you have completed your task. Call this when your work is done.\",\n schema: z.object({}),\n examples: [\n {\n comment: \"Signal task completion\",\n params: {},\n },\n ],\n execute: () => {\n throw new BreakLoopException(\"Task completed\");\n },\n});\n\n/**\n * All built-in gadgets as an array for easy registration.\n */\nexport const builtinGadgets = [askUser, tellUser, finish];\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { BaseGadget } from \"../gadgets/gadget.js\";\n\n/**\n * Function type for importing modules dynamically.\n */\nexport type GadgetImportFunction = (specifier: string) => Promise<unknown>;\n\nconst PATH_PREFIXES = [\".\", \"/\", \"~\"];\n\n/**\n * Duck-type check if a value looks like a Gadget instance.\n * This avoids instanceof issues when gadgets are loaded from external files\n * that import from the 'llmist' npm package (different class instance).\n */\nfunction isGadgetLike(value: unknown): value is BaseGadget {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n const obj = value as Record<string, unknown>;\n return (\n typeof obj.execute === \"function\" &&\n typeof obj.description === \"string\" &&\n (\"parameterSchema\" in obj || \"schema\" in obj)\n );\n}\n\n/**\n * Type guard to check if a value is a Gadget constructor.\n *\n * @param value - Value to check\n * @returns True if value is a Gadget constructor\n */\nfunction isGadgetConstructor(value: unknown): value is new () => BaseGadget {\n if (typeof value !== \"function\") {\n return false;\n }\n\n const prototype = value.prototype as unknown;\n // Use duck typing for prototype check too\n return Boolean(prototype) && (prototype instanceof BaseGadget || isGadgetLike(prototype));\n}\n\n/**\n * Expands ~ to the user's home directory.\n *\n * @param input - Path that may start with ~\n * @returns Expanded path with HOME directory\n */\nfunction expandHomePath(input: string): string {\n if (!input.startsWith(\"~\")) {\n return input;\n }\n\n const home = process.env.HOME;\n if (!home) {\n return input;\n }\n\n return path.join(home, input.slice(1));\n}\n\n/**\n * Determines if a specifier is a file path vs npm module name.\n * File paths start with ., /, ~ or contain path separators.\n *\n * @param specifier - Module specifier to check\n * @returns True if specifier represents a file path\n */\nfunction isFileLikeSpecifier(specifier: string): boolean {\n return (\n PATH_PREFIXES.some((prefix) => specifier.startsWith(prefix)) || specifier.includes(path.sep)\n );\n}\n\n/**\n * Resolves a gadget specifier to either a file URL or npm module name.\n * File paths are resolved relative to cwd and converted to file:// URLs.\n *\n * @param specifier - Original gadget specifier (file path or module name)\n * @param cwd - Current working directory for resolving relative paths\n * @returns Resolved specifier (file:// URL for files, module name for packages)\n * @throws Error if file path doesn't exist\n */\nexport function resolveGadgetSpecifier(specifier: string, cwd: string): string {\n if (!isFileLikeSpecifier(specifier)) {\n return specifier;\n }\n\n const expanded = expandHomePath(specifier);\n const resolvedPath = path.resolve(cwd, expanded);\n if (!fs.existsSync(resolvedPath)) {\n throw new Error(`Gadget module not found at ${resolvedPath}`);\n }\n return pathToFileURL(resolvedPath).href;\n}\n\n/**\n * Recursively extracts all Gadget instances and classes from a module's exports.\n * Searches default export, named exports, nested objects, and arrays.\n * Automatically instantiates Gadget classes.\n *\n * @param moduleExports - Module exports object to search\n * @returns Array of Gadget instances found in exports\n */\nexport function extractGadgetsFromModule(moduleExports: unknown): BaseGadget[] {\n const results: BaseGadget[] = [];\n const visited = new Set<unknown>();\n\n const visit = (value: unknown) => {\n if (value === undefined || value === null) {\n return;\n }\n\n if (visited.has(value)) {\n return;\n }\n visited.add(value);\n\n // Use duck typing to handle gadgets from external packages\n if (value instanceof BaseGadget || isGadgetLike(value)) {\n results.push(value as BaseGadget);\n return;\n }\n\n if (isGadgetConstructor(value)) {\n results.push(new value());\n return;\n }\n\n if (Array.isArray(value)) {\n for (const entry of value) {\n visit(entry);\n }\n return;\n }\n\n if (typeof value === \"object\") {\n for (const entry of Object.values(value as Record<string, unknown>)) {\n visit(entry);\n }\n }\n };\n\n visit(moduleExports);\n return results;\n}\n\n/**\n * Loads gadgets from one or more file paths or npm module names.\n * Resolves paths, imports modules, and extracts gadgets.\n *\n * @param specifiers - Array of gadget specifiers (file paths or module names)\n * @param cwd - Current working directory for resolving relative paths\n * @param importer - Function to dynamically import modules (default: native import)\n * @returns Array of loaded Gadget instances\n * @throws Error if module fails to load, contains no gadgets, or initialization fails\n */\nexport async function loadGadgets(\n specifiers: string[],\n cwd: string,\n importer: GadgetImportFunction = (specifier) => import(specifier),\n): Promise<BaseGadget[]> {\n const gadgets: BaseGadget[] = [];\n\n for (const specifier of specifiers) {\n const resolved = resolveGadgetSpecifier(specifier, cwd);\n let exports: unknown;\n try {\n exports = await importer(resolved);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to load gadget module '${specifier}': ${message}`);\n }\n\n let extracted: BaseGadget[];\n try {\n extracted = extractGadgetsFromModule(exports);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to initialize gadgets from module '${specifier}': ${message}`);\n }\n if (extracted.length === 0) {\n throw new Error(`Module '${specifier}' does not export any Gadget instances.`);\n }\n gadgets.push(...extracted);\n }\n\n return gadgets;\n}\n","import { mkdir, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport type { LLMMessage } from \"../core/messages.js\";\n\n/**\n * Default directory for LLM debug logs.\n */\nexport const DEFAULT_LLM_LOG_DIR = join(homedir(), \".llmist\", \"logs\");\n\n/**\n * Resolves the log directory from a boolean or string option.\n * - true: use default directory with subdir\n * - string: use the provided path\n * - undefined/false: disabled\n */\nexport function resolveLogDir(option: string | boolean | undefined, subdir: string): string | undefined {\n if (option === true) {\n return join(DEFAULT_LLM_LOG_DIR, subdir);\n }\n if (typeof option === \"string\") {\n return option;\n }\n return undefined;\n}\n\n/**\n * Formats LLM messages as plain text for debugging.\n */\nexport function formatLlmRequest(messages: LLMMessage[]): string {\n const lines: string[] = [];\n for (const msg of messages) {\n lines.push(`=== ${msg.role.toUpperCase()} ===`);\n lines.push(msg.content ?? \"\");\n lines.push(\"\");\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Writes a debug log file, creating the directory if needed.\n */\nexport async function writeLogFile(dir: string, filename: string, content: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n await writeFile(join(dir, filename), content, \"utf-8\");\n}\n","import chalk from \"chalk\";\nimport { InvalidArgumentError } from \"commander\";\n\nimport type { ModelRegistry } from \"../core/model-registry.js\";\nimport type { TokenUsage } from \"../core/options.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"../providers/constants.js\";\nimport type { CLIEnvironment, TTYStream } from \"./environment.js\";\n\n/**\n * Options for creating a numeric value parser.\n */\nexport interface NumericParserOptions {\n label: string;\n integer?: boolean;\n min?: number;\n max?: number;\n}\n\n/**\n * Creates a parser function for numeric command-line options with validation.\n * Validates that values are numbers, optionally integers, and within min/max bounds.\n *\n * @param options - Parser configuration (label, integer, min, max)\n * @returns Parser function that validates and returns the numeric value\n * @throws InvalidArgumentError if validation fails\n */\nexport function createNumericParser({\n label,\n integer = false,\n min,\n max,\n}: NumericParserOptions): (value: string) => number {\n return (value: string) => {\n const parsed = Number(value);\n if (Number.isNaN(parsed)) {\n throw new InvalidArgumentError(`${label} must be a number.`);\n }\n\n if (integer && !Number.isInteger(parsed)) {\n throw new InvalidArgumentError(`${label} must be an integer.`);\n }\n\n if (min !== undefined && parsed < min) {\n throw new InvalidArgumentError(`${label} must be greater than or equal to ${min}.`);\n }\n\n if (max !== undefined && parsed > max) {\n throw new InvalidArgumentError(`${label} must be less than or equal to ${max}.`);\n }\n\n return parsed;\n };\n}\n\n/**\n * Helper class for writing text to a stream while tracking newline state.\n * Ensures output ends with a newline for proper terminal formatting.\n */\nexport class StreamPrinter {\n private endedWithNewline = true;\n\n constructor(private readonly target: NodeJS.WritableStream) {}\n\n /**\n * Writes text to the target stream and tracks newline state.\n *\n * @param text - Text to write\n */\n write(text: string): void {\n if (!text) {\n return;\n }\n this.target.write(text);\n this.endedWithNewline = text.endsWith(\"\\n\");\n }\n\n /**\n * Ensures output ends with a newline by writing one if needed.\n */\n ensureNewline(): void {\n if (!this.endedWithNewline) {\n this.target.write(\"\\n\");\n this.endedWithNewline = true;\n }\n }\n}\n\n/**\n * Checks if a stream is a TTY (terminal) for interactive input.\n *\n * @param stream - Stream to check\n * @returns True if stream is a TTY\n */\nexport function isInteractive(stream: TTYStream): boolean {\n return Boolean(stream.isTTY);\n}\n\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\nconst SPINNER_DELAY_MS = 500; // Don't show spinner for fast responses\n\ntype ProgressMode = \"streaming\" | \"cumulative\";\n\n// Import formatters from centralized formatting module\n// This showcases llmist's clean code organization\nimport { formatTokens, formatCost } from \"./ui/formatters.js\";\n\n/**\n * Progress indicator shown while waiting for LLM response.\n * Two modes:\n * - streaming: Shows current LLM call stats (out/in tokens, call time)\n * - cumulative: Shows total stats across all calls (total tokens, iterations, total time)\n * Only displays on TTY (interactive terminal), silent when piped.\n */\nexport class StreamProgress {\n // Animation state\n private frameIndex = 0;\n private interval: ReturnType<typeof setInterval> | null = null;\n private delayTimeout: ReturnType<typeof setTimeout> | null = null;\n private isRunning = false;\n private hasRendered = false;\n\n // Current call stats (streaming mode)\n private mode: ProgressMode = \"cumulative\";\n private model = \"\";\n private callStartTime = Date.now();\n private callInputTokens = 0;\n private callInputTokensEstimated = true;\n private callOutputTokens = 0;\n private callOutputTokensEstimated = true;\n private callOutputChars = 0;\n private isStreaming = false;\n // Cache token tracking for live cost estimation during streaming\n private callCachedInputTokens = 0;\n private callCacheCreationInputTokens = 0;\n\n // Cumulative stats (cumulative mode)\n private totalStartTime = Date.now();\n private totalTokens = 0;\n private totalCost = 0;\n private iterations = 0;\n private currentIteration = 0;\n\n constructor(\n private readonly target: NodeJS.WritableStream,\n private readonly isTTY: boolean,\n private readonly modelRegistry?: ModelRegistry,\n ) {}\n\n /**\n * Starts a new LLM call. Switches to streaming mode.\n * @param model - Model name being used\n * @param estimatedInputTokens - Initial input token count. Should come from\n * client.countTokens() for accuracy (provider-specific counting), not\n * character-based estimation. Will be updated with provider-returned counts\n * via setInputTokens() during streaming if available.\n */\n startCall(model: string, estimatedInputTokens?: number): void {\n this.mode = \"streaming\";\n this.model = model;\n this.callStartTime = Date.now();\n this.currentIteration++;\n this.callInputTokens = estimatedInputTokens ?? 0;\n this.callInputTokensEstimated = true;\n this.callOutputTokens = 0;\n this.callOutputTokensEstimated = true;\n this.callOutputChars = 0;\n this.isStreaming = false;\n // Reset cache tracking for new call\n this.callCachedInputTokens = 0;\n this.callCacheCreationInputTokens = 0;\n this.start();\n }\n\n /**\n * Ends the current LLM call. Updates cumulative stats and switches to cumulative mode.\n * @param usage - Final token usage from the call (including cached tokens if available)\n */\n endCall(usage?: TokenUsage): void {\n this.iterations++;\n if (usage) {\n this.totalTokens += usage.totalTokens;\n\n // Calculate and accumulate cost if model registry is available\n if (this.modelRegistry && this.model) {\n try {\n // Strip provider prefix if present (e.g., \"openai:gpt-5-nano\" -> \"gpt-5-nano\")\n const modelName = this.model.includes(\":\")\n ? this.model.split(\":\")[1]\n : this.model;\n\n const cost = this.modelRegistry.estimateCost(\n modelName,\n usage.inputTokens,\n usage.outputTokens,\n usage.cachedInputTokens ?? 0,\n usage.cacheCreationInputTokens ?? 0,\n );\n if (cost) {\n this.totalCost += cost.totalCost;\n }\n } catch {\n // Ignore errors (e.g., unknown model) - just don't add to cost\n }\n }\n }\n this.pause();\n this.mode = \"cumulative\";\n }\n\n /**\n * Sets the input token count for current call (from stream metadata).\n * @param tokens - Token count from provider or client.countTokens()\n * @param estimated - If true, this is a fallback estimate (character-based).\n * If false, this is an accurate count from the provider API or client.countTokens().\n * Display shows ~ prefix only when estimated=true.\n */\n setInputTokens(tokens: number, estimated = false): void {\n // Don't overwrite actual count with a new estimate\n if (estimated && !this.callInputTokensEstimated) {\n return;\n }\n this.callInputTokens = tokens;\n this.callInputTokensEstimated = estimated;\n }\n\n /**\n * Sets the output token count for current call (from stream metadata).\n * @param tokens - Token count from provider streaming response\n * @param estimated - If true, this is a fallback estimate (character-based).\n * If false, this is an accurate count from the provider's streaming metadata.\n * Display shows ~ prefix only when estimated=true.\n */\n setOutputTokens(tokens: number, estimated = false): void {\n // Don't overwrite actual count with a new estimate\n if (estimated && !this.callOutputTokensEstimated) {\n return;\n }\n this.callOutputTokens = tokens;\n this.callOutputTokensEstimated = estimated;\n }\n\n /**\n * Sets cached token counts for the current call (from stream metadata).\n * Used for live cost estimation during streaming.\n * @param cachedInputTokens - Number of tokens read from cache (cheaper)\n * @param cacheCreationInputTokens - Number of tokens written to cache (more expensive)\n */\n setCachedTokens(cachedInputTokens: number, cacheCreationInputTokens: number): void {\n this.callCachedInputTokens = cachedInputTokens;\n this.callCacheCreationInputTokens = cacheCreationInputTokens;\n }\n\n /**\n * Get total elapsed time in seconds since the first call started.\n * @returns Elapsed time in seconds with 1 decimal place\n */\n getTotalElapsedSeconds(): number {\n if (this.totalStartTime === 0) return 0;\n return Number(((Date.now() - this.totalStartTime) / 1000).toFixed(1));\n }\n\n /**\n * Get elapsed time in seconds for the current call.\n * @returns Elapsed time in seconds with 1 decimal place\n */\n getCallElapsedSeconds(): number {\n return Number(((Date.now() - this.callStartTime) / 1000).toFixed(1));\n }\n\n /**\n * Starts the progress indicator animation after a brief delay.\n */\n start(): void {\n if (!this.isTTY || this.isRunning) return;\n this.isRunning = true;\n\n // Delay showing spinner to avoid flicker for fast responses\n this.delayTimeout = setTimeout(() => {\n if (this.isRunning) {\n this.interval = setInterval(() => this.render(), 80);\n this.render();\n }\n }, SPINNER_DELAY_MS);\n }\n\n /**\n * Updates output character count for current call and marks streaming as active.\n * @param totalChars - Total accumulated character count\n */\n update(totalChars: number): void {\n this.callOutputChars = totalChars;\n this.isStreaming = true;\n }\n\n private render(): void {\n const spinner = SPINNER_FRAMES[this.frameIndex++ % SPINNER_FRAMES.length];\n\n if (this.mode === \"streaming\") {\n this.renderStreamingMode(spinner);\n } else {\n this.renderCumulativeMode(spinner);\n }\n this.hasRendered = true;\n }\n\n private renderStreamingMode(spinner: string): void {\n const elapsed = ((Date.now() - this.callStartTime) / 1000).toFixed(1);\n\n // Output tokens: use actual if available, otherwise estimate from chars\n const outTokens = this.callOutputTokensEstimated\n ? Math.round(this.callOutputChars / FALLBACK_CHARS_PER_TOKEN)\n : this.callOutputTokens;\n\n // Build status parts: #N model | ↑ in │ ↓ out │ time | cost\n const parts: string[] = [];\n\n // #N model (iteration number + model name)\n const iterPart = chalk.cyan(`#${this.currentIteration}`);\n if (this.model) {\n parts.push(`${iterPart} ${chalk.magenta(this.model)}`);\n } else {\n parts.push(iterPart);\n }\n\n // Context usage percentage (color-coded by usage level)\n const usagePercent = this.getContextUsagePercent();\n if (usagePercent !== null) {\n const formatted = `${Math.round(usagePercent)}%`;\n if (usagePercent >= 80) {\n parts.push(chalk.red(formatted)); // Danger zone - compaction threshold\n } else if (usagePercent >= 50) {\n parts.push(chalk.yellow(formatted)); // Warning zone\n } else {\n parts.push(chalk.green(formatted)); // Safe zone\n }\n }\n\n // ↑ input tokens\n if (this.callInputTokens > 0) {\n const prefix = this.callInputTokensEstimated ? \"~\" : \"\";\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${prefix}${formatTokens(this.callInputTokens)}`));\n }\n\n // ↓ output tokens\n if (this.isStreaming || outTokens > 0) {\n const prefix = this.callOutputTokensEstimated ? \"~\" : \"\";\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${prefix}${formatTokens(outTokens)}`));\n }\n\n // Time\n parts.push(chalk.dim(`${elapsed}s`));\n\n // Live cost estimate for current call (updates as tokens stream in)\n const callCost = this.calculateCurrentCallCost(outTokens);\n if (callCost > 0) {\n parts.push(chalk.cyan(`$${formatCost(callCost)}`));\n }\n\n this.target.write(`\\r${parts.join(chalk.dim(\" | \"))} ${chalk.cyan(spinner)}`);\n }\n\n /**\n * Calculates live cost estimate for the current streaming call.\n * Uses current input/output tokens and cached token counts.\n */\n private calculateCurrentCallCost(outputTokens: number): number {\n if (!this.modelRegistry || !this.model) return 0;\n\n try {\n // Strip provider prefix if present (e.g., \"anthropic:claude-sonnet-4-5\" -> \"claude-sonnet-4-5\")\n const modelName = this.model.includes(\":\") ? this.model.split(\":\")[1] : this.model;\n\n const cost = this.modelRegistry.estimateCost(\n modelName,\n this.callInputTokens,\n outputTokens,\n this.callCachedInputTokens,\n this.callCacheCreationInputTokens,\n );\n\n return cost?.totalCost ?? 0;\n } catch {\n return 0;\n }\n }\n\n /**\n * Calculates context window usage percentage.\n * Returns null if model is unknown or context window unavailable.\n */\n private getContextUsagePercent(): number | null {\n if (!this.modelRegistry || !this.model || this.callInputTokens === 0) {\n return null;\n }\n\n // Strip provider prefix if present (e.g., \"anthropic:claude-sonnet-4-5\" -> \"claude-sonnet-4-5\")\n const modelName = this.model.includes(\":\") ? this.model.split(\":\")[1] : this.model;\n\n const limits = this.modelRegistry.getModelLimits(modelName);\n if (!limits?.contextWindow) {\n return null;\n }\n\n return (this.callInputTokens / limits.contextWindow) * 100;\n }\n\n private renderCumulativeMode(spinner: string): void {\n const elapsed = ((Date.now() - this.totalStartTime) / 1000).toFixed(1);\n\n // Build status parts: model, total tokens, iterations, cost, total time\n const parts: string[] = [];\n if (this.model) {\n parts.push(chalk.cyan(this.model));\n }\n if (this.totalTokens > 0) {\n parts.push(chalk.dim(\"total:\") + chalk.magenta(` ${this.totalTokens}`));\n }\n if (this.iterations > 0) {\n parts.push(chalk.dim(\"iter:\") + chalk.blue(` ${this.iterations}`));\n }\n if (this.totalCost > 0) {\n parts.push(chalk.dim(\"cost:\") + chalk.cyan(` $${formatCost(this.totalCost)}`));\n }\n parts.push(chalk.dim(`${elapsed}s`));\n\n this.target.write(`\\r${parts.join(chalk.dim(\" | \"))} ${chalk.cyan(spinner)}`);\n }\n\n /**\n * Pauses the progress indicator and clears the line.\n * Can be resumed with start().\n */\n pause(): void {\n if (!this.isTTY || !this.isRunning) return;\n\n if (this.delayTimeout) {\n clearTimeout(this.delayTimeout);\n this.delayTimeout = null;\n }\n if (this.interval) {\n clearInterval(this.interval);\n this.interval = null;\n }\n this.isRunning = false;\n\n // Only clear the line if we actually rendered something\n if (this.hasRendered) {\n // Clear spinner line and ensure cursor is at column 0\n // \\r = carriage return (go to column 0)\n // \\x1b[K = clear from cursor to end of line\n // \\x1b[0G = move cursor to column 0 (ensures we're at start even after clear)\n this.target.write(\"\\r\\x1b[K\\x1b[0G\");\n this.hasRendered = false;\n }\n }\n\n /**\n * Completes the progress indicator and clears the line.\n */\n complete(): void {\n this.pause();\n }\n\n /**\n * Returns the total accumulated cost across all calls.\n */\n getTotalCost(): number {\n return this.totalCost;\n }\n\n /**\n * Returns a formatted prompt string with stats (like bash PS1).\n * Shows current call stats during streaming, cumulative stats otherwise.\n * Format: \"out: 1.2k │ in: ~300 │ 5s > \" or \"3.6k │ i2 │ 34s > \"\n */\n formatPrompt(): string {\n const parts: string[] = [];\n\n if (this.mode === \"streaming\") {\n // During a call: show current call stats\n const elapsed = Math.round((Date.now() - this.callStartTime) / 1000);\n\n // Output tokens: use actual if available, otherwise estimate from chars\n const outTokens = this.callOutputTokensEstimated\n ? Math.round(this.callOutputChars / FALLBACK_CHARS_PER_TOKEN)\n : this.callOutputTokens;\n const outEstimated = this.callOutputTokensEstimated;\n\n if (this.callInputTokens > 0) {\n const prefix = this.callInputTokensEstimated ? \"~\" : \"\";\n parts.push(\n chalk.dim(\"↑\") + chalk.yellow(` ${prefix}${formatTokens(this.callInputTokens)}`),\n );\n }\n if (outTokens > 0) {\n const prefix = outEstimated ? \"~\" : \"\";\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${prefix}${formatTokens(outTokens)}`));\n }\n parts.push(chalk.dim(`${elapsed}s`));\n } else {\n // Between calls: show cumulative stats\n const elapsed = Math.round((Date.now() - this.totalStartTime) / 1000);\n\n if (this.totalTokens > 0) {\n parts.push(chalk.magenta(formatTokens(this.totalTokens)));\n }\n if (this.iterations > 0) {\n parts.push(chalk.blue(`i${this.iterations}`));\n }\n if (this.totalCost > 0) {\n parts.push(chalk.cyan(`$${formatCost(this.totalCost)}`));\n }\n parts.push(chalk.dim(`${elapsed}s`));\n }\n\n return `${parts.join(chalk.dim(\" | \"))} ${chalk.green(\">\")} `;\n }\n}\n\n/**\n * Reads all data from a readable stream into a string.\n *\n * @param stream - Stream to read from\n * @returns Complete stream contents as string\n */\nasync function readStream(stream: NodeJS.ReadableStream): Promise<string> {\n const chunks: string[] = [];\n for await (const chunk of stream) {\n if (typeof chunk === \"string\") {\n chunks.push(chunk);\n } else {\n chunks.push(chunk.toString(\"utf8\"));\n }\n }\n return chunks.join(\"\");\n}\n\n/**\n * Normalizes a prompt by trimming whitespace.\n *\n * @param value - Prompt to normalize\n * @returns Trimmed prompt\n */\nfunction normalizePrompt(value: string): string {\n return value.trim();\n}\n\n/**\n * Resolves the user prompt from either command-line argument or stdin.\n * Priority: 1) promptArg if provided, 2) stdin if piped, 3) error if neither.\n *\n * @param promptArg - Optional prompt from command-line argument\n * @param env - CLI environment for accessing stdin\n * @returns Resolved and normalized prompt\n * @throws Error if no prompt available or stdin is empty\n */\nexport async function resolvePrompt(\n promptArg: string | undefined,\n env: CLIEnvironment,\n): Promise<string> {\n if (promptArg?.trim()) {\n return normalizePrompt(promptArg);\n }\n\n if (isInteractive(env.stdin)) {\n throw new Error(\"Prompt is required. Provide an argument or pipe content via stdin.\");\n }\n\n const pipedInput = normalizePrompt(await readStream(env.stdin));\n if (!pipedInput) {\n throw new Error(\"Received empty stdin payload. Provide a prompt to continue.\");\n }\n\n return pipedInput;\n}\n\n// Re-export summary rendering from formatters module\n// This maintains backward compatibility while organizing code better\nexport { renderSummary, type SummaryMetadata } from \"./ui/formatters.js\";\n\n/**\n * Executes a CLI action with error handling.\n * Catches errors, writes to stderr, and sets exit code 1 on failure.\n *\n * @param action - Async action to execute\n * @param env - CLI environment for error output and exit code\n */\nexport async function executeAction(\n action: () => Promise<void>,\n env: CLIEnvironment,\n): Promise<void> {\n try {\n await action();\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n env.stderr.write(`${chalk.red.bold(\"Error:\")} ${message}\\n`);\n env.setExitCode(1);\n }\n}\n","/**\n * CLI output formatting utilities.\n *\n * This module provides formatting functions for displaying metrics, summaries,\n * and gadget results in a clean, consistent format across the llmist CLI.\n *\n * **Design principles:**\n * - Consistent formatting across all commands (agent, complete, models)\n * - Human-readable output with appropriate precision\n * - Color-coded for visual clarity (using chalk)\n * - Compact format optimized for terminal display\n *\n * **SHOWCASE:** Demonstrates how to build a polished CLI on top of llmist's core.\n */\n\nimport chalk from \"chalk\";\nimport { marked, type MarkedExtension } from \"marked\";\nimport { markedTerminal } from \"marked-terminal\";\nimport type { TokenUsage } from \"../../core/options.js\";\n\n/**\n * Lazy-initialized flag for marked-terminal configuration.\n *\n * We defer `marked.use(markedTerminal())` until first render because:\n * - markedTerminal() captures chalk's color level at call time\n * - At module import time, TTY detection may not be complete\n * - Lazy init ensures colors work in interactive terminals\n */\nlet markedConfigured = false;\n\n/**\n * Configure marked for terminal output (lazy initialization).\n *\n * Uses marked-terminal to convert markdown to ANSI-styled terminal output.\n * This enables rich formatting in TellUser messages and AskUser questions.\n *\n * We override marked-terminal's style functions with our own chalk instance\n * because marked-terminal bundles its own chalk that detects colors at module\n * load time. Bun's broken TTY detection causes that bundled chalk to detect\n * level 0 (no colors). See: https://github.com/oven-sh/bun/issues/1322\n *\n * By forcing `chalk.level = 3` on our imported chalk and passing custom style\n * functions, we ensure colors work regardless of TTY detection.\n *\n * Respects the NO_COLOR environment variable for accessibility.\n *\n * Note: Type assertion needed due to @types/marked-terminal lag behind the runtime API.\n */\nfunction ensureMarkedConfigured(): void {\n if (!markedConfigured) {\n // Respect NO_COLOR env var, otherwise force truecolor (level 3)\n chalk.level = process.env.NO_COLOR ? 0 : 3;\n\n // Override marked-terminal's style functions with our chalk instance\n // to work around Bun's broken TTY detection\n marked.use(\n markedTerminal({\n // Text styling\n strong: chalk.bold,\n em: chalk.italic,\n del: chalk.dim.gray.strikethrough,\n\n // Code styling\n code: chalk.yellow,\n codespan: chalk.yellow,\n\n // Headings\n heading: chalk.green.bold,\n firstHeading: chalk.magenta.underline.bold,\n\n // Links\n link: chalk.blue,\n href: chalk.blue.underline,\n\n // Block elements\n blockquote: chalk.gray.italic,\n\n // List formatting - reduce indentation and add bullet styling\n tab: 2, // Reduce from default 4 to 2 spaces\n listitem: chalk.reset, // Keep items readable (no dim)\n }) as unknown as MarkedExtension,\n );\n markedConfigured = true;\n }\n}\n\n/**\n * Renders markdown text as styled terminal output.\n *\n * Converts markdown syntax to ANSI escape codes for terminal display:\n * - **bold** and *italic* text\n * - `inline code` and code blocks\n * - Lists (bulleted and numbered)\n * - Headers\n * - Links (clickable in supported terminals)\n *\n * @param text - Markdown text to render\n * @returns ANSI-styled string for terminal output\n *\n * @example\n * ```typescript\n * renderMarkdown(\"**Important:** Check the `config.json` file\");\n * // Returns styled text with bold \"Important:\" and code-styled \"config.json\"\n * ```\n */\nexport function renderMarkdown(text: string): string {\n ensureMarkedConfigured();\n let rendered = marked.parse(text) as string;\n\n // Workaround for marked-terminal bug: inline markdown in list items\n // is not processed. Post-process to handle **bold** and *italic*.\n // See: https://github.com/mikaelbr/marked-terminal/issues\n rendered = rendered\n .replace(/\\*\\*(.+?)\\*\\*/g, (_, content) => chalk.bold(content))\n // Italic: require non-space after * to avoid matching bullet points ( * )\n .replace(/(?<!\\*)\\*(\\S[^*]*)\\*(?!\\*)/g, (_, content) => chalk.italic(content));\n\n // Remove trailing newlines that marked adds\n return rendered.trimEnd();\n}\n\n/**\n * Creates a rainbow-colored horizontal line for visual emphasis.\n * Cycles through colors for each character segment.\n * Uses the full terminal width for a complete visual separator.\n *\n * @returns Rainbow-colored separator string spanning the terminal width\n */\nfunction createRainbowSeparator(): string {\n const colors = [chalk.red, chalk.yellow, chalk.green, chalk.cyan, chalk.blue, chalk.magenta];\n const char = \"─\";\n // Use terminal width, fallback to 80 if not available (e.g., piped output)\n const width = process.stdout.columns || 80;\n let result = \"\";\n for (let i = 0; i < width; i++) {\n result += colors[i % colors.length](char);\n }\n return result;\n}\n\n/**\n * Renders markdown with colorful rainbow horizontal line separators above and below.\n * Use this for prominent markdown content that should stand out visually.\n *\n * @param text - Markdown text to render\n * @returns Rendered markdown with rainbow separators\n *\n * @example\n * ```typescript\n * renderMarkdownWithSeparators(\"**Hello** world!\");\n * // Returns rainbow line + styled markdown + rainbow line\n * ```\n */\nexport function renderMarkdownWithSeparators(text: string): string {\n const rendered = renderMarkdown(text);\n const separator = createRainbowSeparator();\n return `\\n${separator}\\n${rendered}\\n${separator}\\n`;\n}\n\n/**\n * Formats token count with 'k' suffix for thousands.\n *\n * Uses compact notation to save terminal space while maintaining readability.\n * Numbers below 1000 are shown as-is, larger numbers use 'k' suffix with one decimal.\n *\n * @param tokens - Number of tokens\n * @returns Formatted string (e.g., \"896\" or \"11.5k\")\n *\n * @example\n * ```typescript\n * formatTokens(896) // \"896\"\n * formatTokens(11500) // \"11.5k\"\n * formatTokens(1234) // \"1.2k\"\n * ```\n */\nexport function formatTokens(tokens: number): string {\n return tokens >= 1000 ? `${(tokens / 1000).toFixed(1)}k` : `${tokens}`;\n}\n\n/**\n * Formats cost with appropriate precision based on magnitude.\n *\n * Uses variable precision to balance readability and accuracy:\n * - Very small costs (<$0.001): 5 decimal places to show meaningful value\n * - Small costs (<$0.01): 4 decimal places for precision\n * - Medium costs (<$1): 3 decimal places for clarity\n * - Larger costs (≥$1): 2 decimal places (standard currency format)\n *\n * @param cost - Cost in USD\n * @returns Formatted cost string without currency symbol (e.g., \"0.0123\")\n *\n * @example\n * ```typescript\n * formatCost(0.00012) // \"0.00012\"\n * formatCost(0.0056) // \"0.0056\"\n * formatCost(0.123) // \"0.123\"\n * formatCost(1.5) // \"1.50\"\n * ```\n */\nexport function formatCost(cost: number): string {\n if (cost < 0.001) {\n return cost.toFixed(5);\n }\n if (cost < 0.01) {\n return cost.toFixed(4);\n }\n if (cost < 1) {\n return cost.toFixed(3);\n }\n return cost.toFixed(2);\n}\n\n/**\n * Metadata for generating execution summaries.\n *\n * Contains optional metrics collected during agent/LLM execution.\n * All fields are optional to allow partial summaries when data isn't available.\n */\nexport interface SummaryMetadata {\n /** LLM finish reason (e.g., \"stop\", \"length\", \"tool_calls\") */\n finishReason?: string | null;\n\n /** Token usage statistics from LLM provider */\n usage?: TokenUsage;\n\n /** Number of agent iterations (LLM calls) */\n iterations?: number;\n\n /** Model name/ID being used */\n model?: string;\n\n /** Total cost in USD (calculated via ModelRegistry) */\n cost?: number;\n\n /** Elapsed time in seconds */\n elapsedSeconds?: number;\n}\n\n/**\n * Renders execution metadata as a compact, color-coded summary line.\n *\n * Formats agent/LLM execution metrics in a consistent format used across CLI commands.\n * Only includes fields that have values, making the output clean and concise.\n *\n * **Format:** `#N | ↑ input │ ↓ output │ time | cost | finish`\n *\n * **Color scheme:**\n * - Cyan: Iteration number and cost (highlights key metrics)\n * - Yellow: Input tokens (shows what you sent)\n * - Green: Output tokens (shows what you received)\n * - Dim: Separators and finish reason (de-emphasize metadata)\n *\n * @param metadata - Summary metadata to format\n * @returns Formatted summary string, or null if no fields are populated\n *\n * @example\n * ```typescript\n * // Full summary with all fields (including cached tokens)\n * renderSummary({\n * iterations: 3,\n * usage: { inputTokens: 896, outputTokens: 11500, totalTokens: 12396, cachedInputTokens: 500 },\n * elapsedSeconds: 9,\n * cost: 0.0123,\n * finishReason: \"stop\"\n * });\n * // Output: \"#3 | ↑ 896 | ⟳ 500 | ↓ 11.5k | 9s | $0.0123 | stop\"\n *\n * // Partial summary (only tokens, no cache hit)\n * renderSummary({\n * usage: { inputTokens: 500, outputTokens: 200, totalTokens: 700 }\n * });\n * // Output: \"↑ 500 | ↓ 200\"\n * ```\n */\nexport function renderSummary(metadata: SummaryMetadata): string | null {\n const parts: string[] = [];\n\n // Iteration number and model (#N modelname) - shown first for context\n if (metadata.iterations !== undefined) {\n const iterPart = chalk.cyan(`#${metadata.iterations}`);\n if (metadata.model) {\n parts.push(`${iterPart} ${chalk.magenta(metadata.model)}`);\n } else {\n parts.push(iterPart);\n }\n } else if (metadata.model) {\n // Model without iteration number\n parts.push(chalk.magenta(metadata.model));\n }\n\n // Token usage (↑ input │ ⟳ cached │ ✎ cache-write │ ↓ output) - core metrics\n if (metadata.usage) {\n const { inputTokens, outputTokens, cachedInputTokens, cacheCreationInputTokens } =\n metadata.usage;\n parts.push(chalk.dim(\"↑\") + chalk.yellow(` ${formatTokens(inputTokens)}`));\n // Show cached tokens if present (indicates prompt caching hit - 0.1x cost)\n if (cachedInputTokens && cachedInputTokens > 0) {\n parts.push(chalk.dim(\"⟳\") + chalk.blue(` ${formatTokens(cachedInputTokens)}`));\n }\n // Show cache creation tokens if present (Anthropic cache writes - 1.25x cost)\n if (cacheCreationInputTokens && cacheCreationInputTokens > 0) {\n parts.push(chalk.dim(\"✎\") + chalk.magenta(` ${formatTokens(cacheCreationInputTokens)}`));\n }\n parts.push(chalk.dim(\"↓\") + chalk.green(` ${formatTokens(outputTokens)}`));\n }\n\n // Elapsed time - performance metric\n if (metadata.elapsedSeconds !== undefined && metadata.elapsedSeconds > 0) {\n parts.push(chalk.dim(`${metadata.elapsedSeconds}s`));\n }\n\n // Cost - financial tracking (showcases ModelRegistry integration)\n if (metadata.cost !== undefined && metadata.cost > 0) {\n parts.push(chalk.cyan(`$${formatCost(metadata.cost)}`));\n }\n\n // Finish reason - completion status (shown last for context)\n if (metadata.finishReason) {\n parts.push(chalk.dim(metadata.finishReason));\n }\n\n // Return null if no fields populated (cleaner than empty string)\n if (parts.length === 0) {\n return null;\n }\n\n // Join with \" | \" separator for visual clarity\n return parts.join(chalk.dim(\" | \"));\n}\n\n/**\n * Metadata for generating overall execution summaries.\n *\n * Used for the final accumulated summary at the end of agent execution.\n */\nexport interface OverallSummaryMetadata {\n /** Total tokens across all calls */\n totalTokens?: number;\n\n /** Number of agent iterations (LLM calls) */\n iterations?: number;\n\n /** Total elapsed time in seconds */\n elapsedSeconds?: number;\n\n /** Total cost in USD */\n cost?: number;\n}\n\n/**\n * Renders overall accumulated execution summary as a distinct styled line.\n *\n * This is displayed at the end of agent execution to show total metrics.\n * Uses a \"total:\" prefix to distinguish from per-call summaries.\n *\n * **Format:** `total: 3.5k | #2 | 19s | $0.0021`\n *\n * @param metadata - Overall summary metadata\n * @returns Formatted summary string, or null if no fields are populated\n *\n * @example\n * ```typescript\n * renderOverallSummary({\n * totalTokens: 3500,\n * iterations: 2,\n * elapsedSeconds: 19,\n * cost: 0.0021\n * });\n * // Output: \"total: 3.5k | #2 | 19s | $0.0021\"\n * ```\n */\nexport function renderOverallSummary(metadata: OverallSummaryMetadata): string | null {\n const parts: string[] = [];\n\n // Total tokens - primary metric for overall summary\n if (metadata.totalTokens !== undefined && metadata.totalTokens > 0) {\n parts.push(chalk.dim(\"total:\") + chalk.magenta(` ${formatTokens(metadata.totalTokens)}`));\n }\n\n // Iteration count (#N)\n if (metadata.iterations !== undefined && metadata.iterations > 0) {\n parts.push(chalk.cyan(`#${metadata.iterations}`));\n }\n\n // Total elapsed time\n if (metadata.elapsedSeconds !== undefined && metadata.elapsedSeconds > 0) {\n parts.push(chalk.dim(`${metadata.elapsedSeconds}s`));\n }\n\n // Total cost\n if (metadata.cost !== undefined && metadata.cost > 0) {\n parts.push(chalk.cyan(`$${formatCost(metadata.cost)}`));\n }\n\n if (parts.length === 0) {\n return null;\n }\n\n return parts.join(chalk.dim(\" | \"));\n}\n\n/**\n * Gadget execution result for formatting.\n *\n * Contains metadata about a single gadget invocation during agent execution.\n */\nexport interface GadgetResult {\n /** Name of the gadget that was executed */\n gadgetName: string;\n\n /** Execution time in milliseconds */\n executionTimeMs: number;\n\n /** Error message if gadget failed */\n error?: string;\n\n /** Result value from successful gadget execution */\n result?: string;\n\n /** Whether this gadget execution ended the agent loop */\n breaksLoop?: boolean;\n\n /** Parameters passed to the gadget */\n parameters?: Record<string, unknown>;\n\n /** Token count for output (calculated via provider API) */\n tokenCount?: number;\n}\n\n/**\n * Formats a gadget execution result as a compact one-liner for stderr output.\n *\n * Provides visual feedback for gadget execution during agent runs. Different\n * icons and colors indicate success, error, or completion states.\n *\n * **Format:**\n * - Success: `✓ GadgetName(param=value, ...) → 248 tokens 123ms`\n * - Error: `✗ GadgetName(param=value) error: message 123ms`\n * - Completion: `⏹ GadgetName(param=value) → 2.5k tokens 123ms`\n *\n * **Design:**\n * - All parameters shown inline (truncated if too long)\n * - Output shown as token count (via provider API) or bytes as fallback\n * - Execution time always shown at the end\n *\n * @param result - Gadget execution result with timing and output info\n * @returns Formatted one-liner string with ANSI colors\n *\n * @example\n * ```typescript\n * // Successful gadget execution with token count\n * formatGadgetSummary({\n * gadgetName: \"ListDirectory\",\n * executionTimeMs: 4,\n * parameters: { path: \".\", recursive: true },\n * result: \"Type | Name | Size...\",\n * tokenCount: 248\n * });\n * // Output: \"✓ ListDirectory(path=., recursive=true) → 248 tokens 4ms\"\n *\n * // Error case\n * formatGadgetSummary({\n * gadgetName: \"ReadFile\",\n * executionTimeMs: 2,\n * parameters: { path: \"/missing.txt\" },\n * error: \"File not found\"\n * });\n * // Output: \"✗ ReadFile(path=/missing.txt) error: File not found 2ms\"\n * ```\n */\n/**\n * Formats parameters as a compact inline string with color-coded keys and values.\n *\n * @param params - Parameter key-value pairs\n * @returns Formatted string with dim keys and cyan values, e.g., \"path=., recursive=true\"\n */\nfunction formatParametersInline(params: Record<string, unknown> | undefined): string {\n if (!params || Object.keys(params).length === 0) {\n return \"\";\n }\n\n return Object.entries(params)\n .map(([key, value]) => {\n // Format value compactly\n let formatted: string;\n if (typeof value === \"string\") {\n // Truncate long strings\n formatted = value.length > 30 ? `${value.slice(0, 30)}…` : value;\n } else if (typeof value === \"boolean\" || typeof value === \"number\") {\n formatted = String(value);\n } else {\n // For arrays/objects, show compact JSON\n const json = JSON.stringify(value);\n formatted = json.length > 30 ? `${json.slice(0, 30)}…` : json;\n }\n // Color: dim key, = sign, cyan value\n return `${chalk.dim(key)}${chalk.dim(\"=\")}${chalk.cyan(formatted)}`;\n })\n .join(chalk.dim(\", \"));\n}\n\n/**\n * Formats byte count in human-readable form.\n *\n * @param bytes - Number of bytes\n * @returns Formatted string like \"245 bytes\" or \"1.2 KB\"\n */\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) {\n return `${bytes} bytes`;\n }\n if (bytes < 1024 * 1024) {\n return `${(bytes / 1024).toFixed(1)} KB`;\n }\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\n}\n\nexport function formatGadgetSummary(result: GadgetResult): string {\n // Format gadget name and execution time\n const gadgetLabel = chalk.magenta.bold(result.gadgetName);\n const timeLabel = chalk.dim(`${Math.round(result.executionTimeMs)}ms`);\n\n // Format parameters inline (parentheses are dim, content is color-coded)\n const paramsStr = formatParametersInline(result.parameters);\n const paramsLabel = paramsStr ? `${chalk.dim(\"(\")}${paramsStr}${chalk.dim(\")\")}` : \"\";\n\n // Error case - show error message in red (one-liner)\n if (result.error) {\n const errorMsg = result.error.length > 50 ? `${result.error.slice(0, 50)}…` : result.error;\n return `${chalk.red(\"✗\")} ${gadgetLabel}${paramsLabel} ${chalk.red(\"error:\")} ${errorMsg} ${timeLabel}`;\n }\n\n // Format output size: prefer token count if available, fallback to bytes\n let outputLabel: string;\n if (result.tokenCount !== undefined && result.tokenCount > 0) {\n outputLabel = chalk.green(`${formatTokens(result.tokenCount)} tokens`);\n } else if (result.result) {\n const outputBytes = Buffer.byteLength(result.result, \"utf-8\");\n outputLabel = outputBytes > 0 ? chalk.green(formatBytes(outputBytes)) : chalk.dim(\"no output\");\n } else {\n outputLabel = chalk.dim(\"no output\");\n }\n\n // Build the summary line\n const icon = result.breaksLoop ? chalk.yellow(\"⏹\") : chalk.green(\"✓\");\n const summaryLine = `${icon} ${gadgetLabel}${paramsLabel} ${chalk.dim(\"→\")} ${outputLabel} ${timeLabel}`;\n\n // TellUser gadget: display full message content below the summary (with markdown and separators)\n if (result.gadgetName === \"TellUser\" && result.parameters?.message) {\n const message = String(result.parameters.message);\n const rendered = renderMarkdownWithSeparators(message);\n return `${summaryLine}\\n${rendered}`;\n }\n\n return summaryLine;\n}\n","import type { Command } from \"commander\";\nimport type { AgentConfig, CompleteConfig, CustomCommandConfig } from \"./config.js\";\nimport { DEFAULT_MODEL, OPTION_DESCRIPTIONS, OPTION_FLAGS } from \"./constants.js\";\nimport { createNumericParser } from \"./utils.js\";\n\n/**\n * Options for the complete command (camelCase, matching Commander output).\n */\nexport interface CompleteCommandOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxTokens?: number;\n quiet?: boolean;\n logLlmRequests?: string | boolean;\n logLlmResponses?: string | boolean;\n}\n\n/**\n * Options for the agent command (camelCase, matching Commander output).\n */\nexport interface AgentCommandOptions {\n model: string;\n system?: string;\n temperature?: number;\n maxIterations?: number;\n gadget?: string[];\n builtins: boolean;\n builtinInteraction: boolean;\n gadgetStartPrefix?: string;\n gadgetEndPrefix?: string;\n gadgetArgPrefix?: string;\n quiet?: boolean;\n logLlmRequests?: string | boolean;\n logLlmResponses?: string | boolean;\n}\n\n/**\n * Adds complete command options to a Commander command.\n *\n * @param cmd - Command to add options to\n * @param defaults - Optional defaults from config file\n * @returns The command with options added\n */\nexport function addCompleteOptions(cmd: Command, defaults?: CompleteConfig): Command {\n return cmd\n .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, defaults?.model ?? DEFAULT_MODEL)\n .option(OPTION_FLAGS.systemPrompt, OPTION_DESCRIPTIONS.systemPrompt, defaults?.system)\n .option(\n OPTION_FLAGS.temperature,\n OPTION_DESCRIPTIONS.temperature,\n createNumericParser({ label: \"Temperature\", min: 0, max: 2 }),\n defaults?.temperature,\n )\n .option(\n OPTION_FLAGS.maxTokens,\n OPTION_DESCRIPTIONS.maxTokens,\n createNumericParser({ label: \"Max tokens\", integer: true, min: 1 }),\n defaults?.[\"max-tokens\"],\n )\n .option(OPTION_FLAGS.quiet, OPTION_DESCRIPTIONS.quiet, defaults?.quiet)\n .option(OPTION_FLAGS.logLlmRequests, OPTION_DESCRIPTIONS.logLlmRequests, defaults?.[\"log-llm-requests\"])\n .option(OPTION_FLAGS.logLlmResponses, OPTION_DESCRIPTIONS.logLlmResponses, defaults?.[\"log-llm-responses\"]);\n}\n\n/**\n * Adds agent command options to a Commander command.\n *\n * @param cmd - Command to add options to\n * @param defaults - Optional defaults from config file\n * @returns The command with options added\n */\nexport function addAgentOptions(cmd: Command, defaults?: AgentConfig): Command {\n // Gadget accumulator needs special handling for defaults\n const gadgetAccumulator = (value: string, previous: string[] = []): string[] => [\n ...previous,\n value,\n ];\n const defaultGadgets = defaults?.gadget ?? [];\n\n return cmd\n .option(OPTION_FLAGS.model, OPTION_DESCRIPTIONS.model, defaults?.model ?? DEFAULT_MODEL)\n .option(OPTION_FLAGS.systemPrompt, OPTION_DESCRIPTIONS.systemPrompt, defaults?.system)\n .option(\n OPTION_FLAGS.temperature,\n OPTION_DESCRIPTIONS.temperature,\n createNumericParser({ label: \"Temperature\", min: 0, max: 2 }),\n defaults?.temperature,\n )\n .option(\n OPTION_FLAGS.maxIterations,\n OPTION_DESCRIPTIONS.maxIterations,\n createNumericParser({ label: \"Max iterations\", integer: true, min: 1 }),\n defaults?.[\"max-iterations\"],\n )\n .option(OPTION_FLAGS.gadgetModule, OPTION_DESCRIPTIONS.gadgetModule, gadgetAccumulator, [\n ...defaultGadgets,\n ])\n .option(OPTION_FLAGS.noBuiltins, OPTION_DESCRIPTIONS.noBuiltins, defaults?.builtins !== false)\n .option(\n OPTION_FLAGS.noBuiltinInteraction,\n OPTION_DESCRIPTIONS.noBuiltinInteraction,\n defaults?.[\"builtin-interaction\"] !== false,\n )\n .option(OPTION_FLAGS.quiet, OPTION_DESCRIPTIONS.quiet, defaults?.quiet)\n .option(OPTION_FLAGS.logLlmRequests, OPTION_DESCRIPTIONS.logLlmRequests, defaults?.[\"log-llm-requests\"])\n .option(OPTION_FLAGS.logLlmResponses, OPTION_DESCRIPTIONS.logLlmResponses, defaults?.[\"log-llm-responses\"]);\n}\n\n/**\n * Converts kebab-case config to camelCase command options for complete command.\n */\nexport function configToCompleteOptions(config: CustomCommandConfig): Partial<CompleteCommandOptions> {\n const result: Partial<CompleteCommandOptions> = {};\n if (config.model !== undefined) result.model = config.model;\n if (config.system !== undefined) result.system = config.system;\n if (config.temperature !== undefined) result.temperature = config.temperature;\n if (config[\"max-tokens\"] !== undefined) result.maxTokens = config[\"max-tokens\"];\n if (config.quiet !== undefined) result.quiet = config.quiet;\n if (config[\"log-llm-requests\"] !== undefined) result.logLlmRequests = config[\"log-llm-requests\"];\n if (config[\"log-llm-responses\"] !== undefined) result.logLlmResponses = config[\"log-llm-responses\"];\n return result;\n}\n\n/**\n * Converts kebab-case config to camelCase command options for agent command.\n */\nexport function configToAgentOptions(config: CustomCommandConfig): Partial<AgentCommandOptions> {\n const result: Partial<AgentCommandOptions> = {};\n if (config.model !== undefined) result.model = config.model;\n if (config.system !== undefined) result.system = config.system;\n if (config.temperature !== undefined) result.temperature = config.temperature;\n if (config[\"max-iterations\"] !== undefined) result.maxIterations = config[\"max-iterations\"];\n if (config.gadget !== undefined) result.gadget = config.gadget;\n if (config.builtins !== undefined) result.builtins = config.builtins;\n if (config[\"builtin-interaction\"] !== undefined)\n result.builtinInteraction = config[\"builtin-interaction\"];\n if (config[\"gadget-start-prefix\"] !== undefined)\n result.gadgetStartPrefix = config[\"gadget-start-prefix\"];\n if (config[\"gadget-end-prefix\"] !== undefined)\n result.gadgetEndPrefix = config[\"gadget-end-prefix\"];\n if (config[\"gadget-arg-prefix\"] !== undefined)\n result.gadgetArgPrefix = config[\"gadget-arg-prefix\"];\n if (config.quiet !== undefined) result.quiet = config.quiet;\n if (config[\"log-llm-requests\"] !== undefined) result.logLlmRequests = config[\"log-llm-requests\"];\n if (config[\"log-llm-responses\"] !== undefined) result.logLlmResponses = config[\"log-llm-responses\"];\n return result;\n}\n","import type { Command } from \"commander\";\n\nimport { LLMMessageBuilder } from \"../core/messages.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { TokenUsage } from \"../core/options.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"../providers/constants.js\";\nimport type { CompleteConfig } from \"./config.js\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { formatLlmRequest, resolveLogDir, writeLogFile } from \"./llm-logging.js\";\nimport {\n addCompleteOptions,\n type CompleteCommandOptions,\n} from \"./option-helpers.js\";\nimport {\n executeAction,\n renderSummary,\n resolvePrompt,\n StreamPrinter,\n StreamProgress,\n} from \"./utils.js\";\n\n/**\n * Executes the complete command.\n * Streams a single LLM response without agent loop or gadgets.\n *\n * @param promptArg - User prompt from command line argument (optional if using stdin)\n * @param options - Complete command options (model, system prompt, temperature, etc.)\n * @param env - CLI environment for I/O operations\n */\nexport async function executeComplete(\n promptArg: string | undefined,\n options: CompleteCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const prompt = await resolvePrompt(promptArg, env);\n const client = env.createClient();\n const model = resolveModel(options.model);\n\n const builder = new LLMMessageBuilder();\n if (options.system) {\n builder.addSystem(options.system);\n }\n builder.addUser(prompt);\n\n const messages = builder.build();\n\n // Resolve LLM debug log directories (if enabled)\n const llmRequestsDir = resolveLogDir(options.logLlmRequests, \"requests\");\n const llmResponsesDir = resolveLogDir(options.logLlmResponses, \"responses\");\n const timestamp = Date.now();\n\n // Log request before streaming\n if (llmRequestsDir) {\n const filename = `${timestamp}_complete.request.txt`;\n const content = formatLlmRequest(messages);\n await writeLogFile(llmRequestsDir, filename, content);\n }\n\n const stream = client.stream({\n model,\n messages,\n temperature: options.temperature,\n maxTokens: options.maxTokens,\n });\n\n const printer = new StreamPrinter(env.stdout);\n const stderrTTY = (env.stderr as NodeJS.WriteStream).isTTY === true;\n const progress = new StreamProgress(env.stderr, stderrTTY, client.modelRegistry);\n\n // Start call with model and estimate based on prompt length\n const estimatedInputTokens = Math.round(prompt.length / FALLBACK_CHARS_PER_TOKEN);\n progress.startCall(model, estimatedInputTokens);\n\n let finishReason: string | null | undefined;\n let usage: TokenUsage | undefined;\n let accumulatedResponse = \"\";\n\n for await (const chunk of stream) {\n // Capture actual usage from stream\n if (chunk.usage) {\n usage = chunk.usage;\n if (chunk.usage.inputTokens) {\n progress.setInputTokens(chunk.usage.inputTokens, false);\n }\n if (chunk.usage.outputTokens) {\n progress.setOutputTokens(chunk.usage.outputTokens, false);\n }\n }\n if (chunk.text) {\n progress.pause(); // Must pause to avoid stderr/stdout interleaving\n accumulatedResponse += chunk.text;\n progress.update(accumulatedResponse.length); // Update token estimate from chars\n printer.write(chunk.text);\n }\n if (chunk.finishReason !== undefined) {\n finishReason = chunk.finishReason;\n }\n }\n\n progress.endCall(usage); // Calculate cost before completing\n progress.complete();\n printer.ensureNewline();\n\n // Log response after streaming\n if (llmResponsesDir) {\n const filename = `${timestamp}_complete.response.txt`;\n await writeLogFile(llmResponsesDir, filename, accumulatedResponse);\n }\n\n // Only show summary if stderr is a TTY (not redirected) and not in quiet mode\n if (stderrTTY && !options.quiet) {\n const summary = renderSummary({ finishReason, usage, cost: progress.getTotalCost() });\n if (summary) {\n env.stderr.write(`${summary}\\n`);\n }\n }\n}\n\n/**\n * Registers the complete command with the CLI program.\n * Configures options for model, system prompt, temperature, and max tokens.\n *\n * @param program - Commander program to register the command with\n * @param env - CLI environment for dependencies and I/O\n * @param config - Optional configuration defaults from config file\n */\nexport function registerCompleteCommand(\n program: Command,\n env: CLIEnvironment,\n config?: CompleteConfig,\n): void {\n const cmd = program\n .command(COMMANDS.complete)\n .description(\"Stream a single completion from a specified model.\")\n .argument(\"[prompt]\", \"Prompt to send to the LLM. If omitted, stdin is used when available.\");\n\n addCompleteOptions(cmd, config);\n\n cmd.action((prompt, options) =>\n executeAction(() => executeComplete(prompt, options as CompleteCommandOptions, env), env),\n );\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { load as parseToml } from \"js-toml\";\nimport {\n type PromptsConfig,\n TemplateError,\n createTemplateEngine,\n hasTemplateSyntax,\n resolveTemplate,\n validateEnvVars,\n validatePrompts,\n} from \"./templates.js\";\n\n// Re-export PromptsConfig for consumers\nexport type { PromptsConfig } from \"./templates.js\";\n\n/**\n * Valid log level names.\n */\nexport type LogLevel = \"silly\" | \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"fatal\";\n\n/**\n * Global CLI options that apply to all commands.\n */\nexport interface GlobalConfig {\n \"log-level\"?: LogLevel;\n \"log-file\"?: string;\n \"log-reset\"?: boolean;\n}\n\n/**\n * Base options shared by both complete and agent command configurations.\n */\nexport interface BaseCommandConfig {\n model?: string;\n system?: string;\n temperature?: number;\n inherits?: string | string[];\n}\n\n/**\n * Configuration for the complete command.\n */\nexport interface CompleteConfig extends BaseCommandConfig {\n \"max-tokens\"?: number;\n quiet?: boolean;\n \"log-level\"?: LogLevel;\n \"log-file\"?: string;\n \"log-reset\"?: boolean;\n \"log-llm-requests\"?: string | boolean;\n \"log-llm-responses\"?: string | boolean;\n}\n\n/**\n * Configuration for the agent command.\n */\nexport interface AgentConfig extends BaseCommandConfig {\n \"max-iterations\"?: number;\n gadget?: string[];\n builtins?: boolean;\n \"builtin-interaction\"?: boolean;\n \"gadget-start-prefix\"?: string;\n \"gadget-end-prefix\"?: string;\n \"gadget-arg-prefix\"?: string;\n quiet?: boolean;\n \"log-level\"?: LogLevel;\n \"log-file\"?: string;\n \"log-reset\"?: boolean;\n \"log-llm-requests\"?: string | boolean;\n \"log-llm-responses\"?: string | boolean;\n}\n\n/**\n * Command type determines execution behavior.\n */\nexport type CommandType = \"agent\" | \"complete\";\n\n/**\n * Custom command configuration from config file.\n * Extends both agent and complete configs, with type determining behavior.\n */\nexport interface CustomCommandConfig extends AgentConfig, CompleteConfig {\n type?: CommandType;\n description?: string;\n}\n\n/**\n * Root configuration structure matching ~/.llmist/cli.toml.\n */\nexport interface CLIConfig {\n global?: GlobalConfig;\n complete?: CompleteConfig;\n agent?: AgentConfig;\n prompts?: PromptsConfig;\n [customCommand: string]:\n | CustomCommandConfig\n | CompleteConfig\n | AgentConfig\n | GlobalConfig\n | PromptsConfig\n | undefined;\n}\n\n/** Valid keys for global config */\nconst GLOBAL_CONFIG_KEYS = new Set([\"log-level\", \"log-file\", \"log-reset\"]);\n\n/** Valid log levels */\nconst VALID_LOG_LEVELS: LogLevel[] = [\"silly\", \"trace\", \"debug\", \"info\", \"warn\", \"error\", \"fatal\"];\n\n/** Valid keys for complete command config */\nconst COMPLETE_CONFIG_KEYS = new Set([\n \"model\",\n \"system\",\n \"temperature\",\n \"max-tokens\",\n \"quiet\",\n \"inherits\",\n \"log-level\",\n \"log-file\",\n \"log-reset\",\n \"log-llm-requests\",\n \"log-llm-responses\",\n \"type\", // Allowed for inheritance compatibility, ignored for built-in commands\n]);\n\n/** Valid keys for agent command config */\nconst AGENT_CONFIG_KEYS = new Set([\n \"model\",\n \"system\",\n \"temperature\",\n \"max-iterations\",\n \"gadget\",\n \"builtins\",\n \"builtin-interaction\",\n \"gadget-start-prefix\",\n \"gadget-end-prefix\",\n \"gadget-arg-prefix\",\n \"quiet\",\n \"inherits\",\n \"log-level\",\n \"log-file\",\n \"log-reset\",\n \"log-llm-requests\",\n \"log-llm-responses\",\n \"type\", // Allowed for inheritance compatibility, ignored for built-in commands\n]);\n\n/** Valid keys for custom command config (union of complete + agent + type + description) */\nconst CUSTOM_CONFIG_KEYS = new Set([\n ...COMPLETE_CONFIG_KEYS,\n ...AGENT_CONFIG_KEYS,\n \"type\",\n \"description\",\n]);\n\n/**\n * Returns the default config file path: ~/.llmist/cli.toml\n */\nexport function getConfigPath(): string {\n return join(homedir(), \".llmist\", \"cli.toml\");\n}\n\n/**\n * Configuration validation error.\n */\nexport class ConfigError extends Error {\n constructor(\n message: string,\n public readonly path?: string,\n ) {\n super(path ? `${path}: ${message}` : message);\n this.name = \"ConfigError\";\n }\n}\n\n/**\n * Validates that a value is a string.\n */\nfunction validateString(value: unknown, key: string, section: string): string {\n if (typeof value !== \"string\") {\n throw new ConfigError(`[${section}].${key} must be a string`);\n }\n return value;\n}\n\n/**\n * Validates that a value is a number within optional bounds.\n */\nfunction validateNumber(\n value: unknown,\n key: string,\n section: string,\n opts?: { min?: number; max?: number; integer?: boolean },\n): number {\n if (typeof value !== \"number\") {\n throw new ConfigError(`[${section}].${key} must be a number`);\n }\n if (opts?.integer && !Number.isInteger(value)) {\n throw new ConfigError(`[${section}].${key} must be an integer`);\n }\n if (opts?.min !== undefined && value < opts.min) {\n throw new ConfigError(`[${section}].${key} must be >= ${opts.min}`);\n }\n if (opts?.max !== undefined && value > opts.max) {\n throw new ConfigError(`[${section}].${key} must be <= ${opts.max}`);\n }\n return value;\n}\n\n/**\n * Validates that a value is a boolean.\n */\nfunction validateBoolean(value: unknown, key: string, section: string): boolean {\n if (typeof value !== \"boolean\") {\n throw new ConfigError(`[${section}].${key} must be a boolean`);\n }\n return value;\n}\n\n/**\n * Validates that a value is an array of strings.\n */\nfunction validateStringArray(value: unknown, key: string, section: string): string[] {\n if (!Array.isArray(value)) {\n throw new ConfigError(`[${section}].${key} must be an array`);\n }\n for (let i = 0; i < value.length; i++) {\n if (typeof value[i] !== \"string\") {\n throw new ConfigError(`[${section}].${key}[${i}] must be a string`);\n }\n }\n return value as string[];\n}\n\n/**\n * Validates that a value is a string or array of strings (for inherits field).\n */\nfunction validateInherits(value: unknown, section: string): string | string[] {\n if (typeof value === \"string\") {\n return value;\n }\n if (Array.isArray(value)) {\n for (let i = 0; i < value.length; i++) {\n if (typeof value[i] !== \"string\") {\n throw new ConfigError(`[${section}].inherits[${i}] must be a string`);\n }\n }\n return value as string[];\n }\n throw new ConfigError(`[${section}].inherits must be a string or array of strings`);\n}\n\n/**\n * Validates and extracts logging config fields from a raw object.\n */\nfunction validateLoggingConfig(\n raw: Record<string, unknown>,\n section: string,\n): { \"log-level\"?: LogLevel; \"log-file\"?: string; \"log-reset\"?: boolean } {\n const result: { \"log-level\"?: LogLevel; \"log-file\"?: string; \"log-reset\"?: boolean } = {};\n\n if (\"log-level\" in raw) {\n const level = validateString(raw[\"log-level\"], \"log-level\", section);\n if (!VALID_LOG_LEVELS.includes(level as LogLevel)) {\n throw new ConfigError(\n `[${section}].log-level must be one of: ${VALID_LOG_LEVELS.join(\", \")}`,\n );\n }\n result[\"log-level\"] = level as LogLevel;\n }\n if (\"log-file\" in raw) {\n result[\"log-file\"] = validateString(raw[\"log-file\"], \"log-file\", section);\n }\n if (\"log-reset\" in raw) {\n result[\"log-reset\"] = validateBoolean(raw[\"log-reset\"], \"log-reset\", section);\n }\n\n return result;\n}\n\n/**\n * Validates and extracts base command config fields.\n */\nfunction validateBaseConfig(\n raw: Record<string, unknown>,\n section: string,\n): Partial<BaseCommandConfig> {\n const result: Partial<BaseCommandConfig> = {};\n\n if (\"model\" in raw) {\n result.model = validateString(raw.model, \"model\", section);\n }\n if (\"system\" in raw) {\n result.system = validateString(raw.system, \"system\", section);\n }\n if (\"temperature\" in raw) {\n result.temperature = validateNumber(raw.temperature, \"temperature\", section, {\n min: 0,\n max: 2,\n });\n }\n if (\"inherits\" in raw) {\n result.inherits = validateInherits(raw.inherits, section);\n }\n\n return result;\n}\n\n/**\n * Validates the global config section.\n */\nfunction validateGlobalConfig(raw: unknown, section: string): GlobalConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!GLOBAL_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n return validateLoggingConfig(rawObj, section);\n}\n\n/**\n * Validates a complete command config section.\n */\nfunction validateCompleteConfig(raw: unknown, section: string): CompleteConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!COMPLETE_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n const result: CompleteConfig = {\n ...validateBaseConfig(rawObj, section),\n ...validateLoggingConfig(rawObj, section),\n };\n\n if (\"max-tokens\" in rawObj) {\n result[\"max-tokens\"] = validateNumber(rawObj[\"max-tokens\"], \"max-tokens\", section, {\n integer: true,\n min: 1,\n });\n }\n if (\"quiet\" in rawObj) {\n result.quiet = validateBoolean(rawObj.quiet, \"quiet\", section);\n }\n if (\"log-llm-requests\" in rawObj) {\n result[\"log-llm-requests\"] = validateStringOrBoolean(\n rawObj[\"log-llm-requests\"],\n \"log-llm-requests\",\n section,\n );\n }\n if (\"log-llm-responses\" in rawObj) {\n result[\"log-llm-responses\"] = validateStringOrBoolean(\n rawObj[\"log-llm-responses\"],\n \"log-llm-responses\",\n section,\n );\n }\n\n return result;\n}\n\n/**\n * Validates an agent command config section.\n */\nfunction validateAgentConfig(raw: unknown, section: string): AgentConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!AGENT_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n const result: AgentConfig = {\n ...validateBaseConfig(rawObj, section),\n ...validateLoggingConfig(rawObj, section),\n };\n\n if (\"max-iterations\" in rawObj) {\n result[\"max-iterations\"] = validateNumber(rawObj[\"max-iterations\"], \"max-iterations\", section, {\n integer: true,\n min: 1,\n });\n }\n if (\"gadget\" in rawObj) {\n result.gadget = validateStringArray(rawObj.gadget, \"gadget\", section);\n }\n if (\"builtins\" in rawObj) {\n result.builtins = validateBoolean(rawObj.builtins, \"builtins\", section);\n }\n if (\"builtin-interaction\" in rawObj) {\n result[\"builtin-interaction\"] = validateBoolean(\n rawObj[\"builtin-interaction\"],\n \"builtin-interaction\",\n section,\n );\n }\n if (\"gadget-start-prefix\" in rawObj) {\n result[\"gadget-start-prefix\"] = validateString(\n rawObj[\"gadget-start-prefix\"],\n \"gadget-start-prefix\",\n section,\n );\n }\n if (\"gadget-end-prefix\" in rawObj) {\n result[\"gadget-end-prefix\"] = validateString(\n rawObj[\"gadget-end-prefix\"],\n \"gadget-end-prefix\",\n section,\n );\n }\n if (\"gadget-arg-prefix\" in rawObj) {\n result[\"gadget-arg-prefix\"] = validateString(\n rawObj[\"gadget-arg-prefix\"],\n \"gadget-arg-prefix\",\n section,\n );\n }\n if (\"quiet\" in rawObj) {\n result.quiet = validateBoolean(rawObj.quiet, \"quiet\", section);\n }\n if (\"log-llm-requests\" in rawObj) {\n result[\"log-llm-requests\"] = validateStringOrBoolean(\n rawObj[\"log-llm-requests\"],\n \"log-llm-requests\",\n section,\n );\n }\n if (\"log-llm-responses\" in rawObj) {\n result[\"log-llm-responses\"] = validateStringOrBoolean(\n rawObj[\"log-llm-responses\"],\n \"log-llm-responses\",\n section,\n );\n }\n\n return result;\n}\n\n/**\n * Validates a value is either a string or boolean.\n */\nfunction validateStringOrBoolean(value: unknown, field: string, section: string): string | boolean {\n if (typeof value === \"string\" || typeof value === \"boolean\") {\n return value;\n }\n throw new ConfigError(`[${section}].${field} must be a string or boolean`);\n}\n\n/**\n * Validates a custom command config section.\n */\nfunction validateCustomConfig(raw: unknown, section: string): CustomCommandConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const rawObj = raw as Record<string, unknown>;\n\n // Check for unknown keys\n for (const key of Object.keys(rawObj)) {\n if (!CUSTOM_CONFIG_KEYS.has(key)) {\n throw new ConfigError(`[${section}].${key} is not a valid option`);\n }\n }\n\n // Get the type first to validate properly\n let type: CommandType = \"agent\"; // Default\n if (\"type\" in rawObj) {\n const typeValue = validateString(rawObj.type, \"type\", section);\n if (typeValue !== \"agent\" && typeValue !== \"complete\") {\n throw new ConfigError(`[${section}].type must be \"agent\" or \"complete\"`);\n }\n type = typeValue;\n }\n\n // Validate base fields + type-specific fields\n const result: CustomCommandConfig = {\n ...validateBaseConfig(rawObj, section),\n type,\n };\n\n if (\"description\" in rawObj) {\n result.description = validateString(rawObj.description, \"description\", section);\n }\n\n // Always allow agent-specific fields (they'll be ignored for complete type)\n if (\"max-iterations\" in rawObj) {\n result[\"max-iterations\"] = validateNumber(rawObj[\"max-iterations\"], \"max-iterations\", section, {\n integer: true,\n min: 1,\n });\n }\n if (\"gadget\" in rawObj) {\n result.gadget = validateStringArray(rawObj.gadget, \"gadget\", section);\n }\n if (\"builtins\" in rawObj) {\n result.builtins = validateBoolean(rawObj.builtins, \"builtins\", section);\n }\n if (\"builtin-interaction\" in rawObj) {\n result[\"builtin-interaction\"] = validateBoolean(\n rawObj[\"builtin-interaction\"],\n \"builtin-interaction\",\n section,\n );\n }\n if (\"gadget-start-prefix\" in rawObj) {\n result[\"gadget-start-prefix\"] = validateString(\n rawObj[\"gadget-start-prefix\"],\n \"gadget-start-prefix\",\n section,\n );\n }\n if (\"gadget-end-prefix\" in rawObj) {\n result[\"gadget-end-prefix\"] = validateString(\n rawObj[\"gadget-end-prefix\"],\n \"gadget-end-prefix\",\n section,\n );\n }\n if (\"gadget-arg-prefix\" in rawObj) {\n result[\"gadget-arg-prefix\"] = validateString(\n rawObj[\"gadget-arg-prefix\"],\n \"gadget-arg-prefix\",\n section,\n );\n }\n\n // Complete-specific fields\n if (\"max-tokens\" in rawObj) {\n result[\"max-tokens\"] = validateNumber(rawObj[\"max-tokens\"], \"max-tokens\", section, {\n integer: true,\n min: 1,\n });\n }\n\n // Shared fields\n if (\"quiet\" in rawObj) {\n result.quiet = validateBoolean(rawObj.quiet, \"quiet\", section);\n }\n\n // Logging options\n Object.assign(result, validateLoggingConfig(rawObj, section));\n\n return result;\n}\n\n/**\n * Validates the prompts config section.\n * Each key must be a string (prompt name) and each value must be a string (template).\n */\nfunction validatePromptsConfig(raw: unknown, section: string): PromptsConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(`[${section}] must be a table`);\n }\n\n const result: PromptsConfig = {};\n for (const [key, value] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof value !== \"string\") {\n throw new ConfigError(`[${section}].${key} must be a string`);\n }\n result[key] = value;\n }\n return result;\n}\n\n/**\n * Validates and normalizes raw TOML object to CLIConfig.\n *\n * @throws ConfigError if validation fails\n */\nexport function validateConfig(raw: unknown, configPath?: string): CLIConfig {\n if (typeof raw !== \"object\" || raw === null) {\n throw new ConfigError(\"Config must be a TOML table\", configPath);\n }\n\n const rawObj = raw as Record<string, unknown>;\n const result: CLIConfig = {};\n\n for (const [key, value] of Object.entries(rawObj)) {\n try {\n if (key === \"global\") {\n result.global = validateGlobalConfig(value, key);\n } else if (key === \"complete\") {\n result.complete = validateCompleteConfig(value, key);\n } else if (key === \"agent\") {\n result.agent = validateAgentConfig(value, key);\n } else if (key === \"prompts\") {\n result.prompts = validatePromptsConfig(value, key);\n } else {\n // Custom command section\n result[key] = validateCustomConfig(value, key);\n }\n } catch (error) {\n if (error instanceof ConfigError) {\n throw new ConfigError(error.message, configPath);\n }\n throw error;\n }\n }\n\n return result;\n}\n\n/**\n * Loads configuration from the default path (~/.llmist/cli.toml).\n * Returns empty config if file doesn't exist.\n *\n * @throws ConfigError if file exists but has invalid syntax or unknown fields\n */\nexport function loadConfig(): CLIConfig {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n return {};\n }\n\n let content: string;\n try {\n content = readFileSync(configPath, \"utf-8\");\n } catch (error) {\n throw new ConfigError(\n `Failed to read config file: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n configPath,\n );\n }\n\n let raw: unknown;\n try {\n raw = parseToml(content);\n } catch (error) {\n throw new ConfigError(\n `Invalid TOML syntax: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n configPath,\n );\n }\n\n const validated = validateConfig(raw, configPath);\n const inherited = resolveInheritance(validated, configPath);\n return resolveTemplatesInConfig(inherited, configPath);\n}\n\n/**\n * Gets list of custom command names from config (excludes built-in sections).\n */\nexport function getCustomCommandNames(config: CLIConfig): string[] {\n const reserved = new Set([\"global\", \"complete\", \"agent\", \"prompts\"]);\n return Object.keys(config).filter((key) => !reserved.has(key));\n}\n\n/**\n * Resolves Eta templates in system prompts throughout the config.\n * Templates are resolved using the [prompts] section as named partials.\n *\n * @param config - Config with inheritance already resolved\n * @param configPath - Path to config file for error messages\n * @returns Config with all templates resolved in system prompts\n * @throws ConfigError if template resolution fails\n */\nexport function resolveTemplatesInConfig(config: CLIConfig, configPath?: string): CLIConfig {\n const prompts = config.prompts ?? {};\n\n // If no prompts and no templates used, return as-is\n const hasPrompts = Object.keys(prompts).length > 0;\n\n // Check if any section uses template syntax\n let hasTemplates = false;\n for (const [sectionName, section] of Object.entries(config)) {\n if (sectionName === \"global\" || sectionName === \"prompts\") continue;\n if (!section || typeof section !== \"object\") continue;\n\n const sectionObj = section as Record<string, unknown>;\n if (typeof sectionObj.system === \"string\" && hasTemplateSyntax(sectionObj.system)) {\n hasTemplates = true;\n break;\n }\n }\n\n // Also check prompts for template syntax (they may reference each other)\n for (const template of Object.values(prompts)) {\n if (hasTemplateSyntax(template)) {\n hasTemplates = true;\n break;\n }\n }\n\n // Quick return if nothing to do\n if (!hasPrompts && !hasTemplates) {\n return config;\n }\n\n // Validate all prompts compile correctly and env vars exist\n try {\n validatePrompts(prompts, configPath);\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(error.message, configPath);\n }\n throw error;\n }\n\n // Validate environment variables in all prompts\n for (const [name, template] of Object.entries(prompts)) {\n try {\n validateEnvVars(template, name, configPath);\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(error.message, configPath);\n }\n throw error;\n }\n }\n\n // Create template engine with all prompts registered\n const eta = createTemplateEngine(prompts, configPath);\n const result = { ...config };\n\n // Resolve templates in all sections with system fields\n for (const [sectionName, section] of Object.entries(config)) {\n if (sectionName === \"global\" || sectionName === \"prompts\") continue;\n if (!section || typeof section !== \"object\") continue;\n\n const sectionObj = section as Record<string, unknown>;\n if (typeof sectionObj.system === \"string\" && hasTemplateSyntax(sectionObj.system)) {\n // Validate env vars in the system prompt itself\n try {\n validateEnvVars(sectionObj.system, undefined, configPath);\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(`[${sectionName}].system: ${error.message}`, configPath);\n }\n throw error;\n }\n\n // Resolve the template\n try {\n const resolved = resolveTemplate(eta, sectionObj.system, {}, configPath);\n result[sectionName] = {\n ...sectionObj,\n system: resolved,\n };\n } catch (error) {\n if (error instanceof TemplateError) {\n throw new ConfigError(`[${sectionName}].system: ${error.message}`, configPath);\n }\n throw error;\n }\n }\n }\n\n return result;\n}\n\n/**\n * Resolves inheritance chains for all sections in the config.\n * Each section can specify `inherits` as a string or array of strings.\n * Resolution follows these rules:\n * - For multiple parents, later parents override earlier ones (last wins)\n * - Section's own values always override inherited values\n * - Arrays are replaced, not merged\n * - Circular inheritance is detected and throws an error\n *\n * @param config - Validated config with possible unresolved inheritance\n * @param configPath - Path to config file for error messages\n * @returns Config with all inheritance resolved\n * @throws ConfigError if circular inheritance or unknown parent section\n */\nexport function resolveInheritance(config: CLIConfig, configPath?: string): CLIConfig {\n const resolved: Record<string, Record<string, unknown>> = {};\n const resolving = new Set<string>(); // For cycle detection\n\n function resolveSection(name: string): Record<string, unknown> {\n // Return cached if already resolved\n if (name in resolved) {\n return resolved[name];\n }\n\n // Cycle detection\n if (resolving.has(name)) {\n throw new ConfigError(`Circular inheritance detected: ${name}`, configPath);\n }\n\n const section = config[name];\n if (section === undefined || typeof section !== \"object\") {\n throw new ConfigError(`Cannot inherit from unknown section: ${name}`, configPath);\n }\n\n resolving.add(name);\n\n // Get inheritance list (normalize to array)\n const sectionObj = section as Record<string, unknown>;\n const inheritsRaw = sectionObj.inherits;\n const inheritsList: string[] = inheritsRaw\n ? Array.isArray(inheritsRaw)\n ? inheritsRaw\n : [inheritsRaw]\n : [];\n\n // Resolve all parents first (recursive), merge in order (last wins)\n let merged: Record<string, unknown> = {};\n for (const parent of inheritsList) {\n const parentResolved = resolveSection(parent);\n merged = { ...merged, ...parentResolved };\n }\n\n // Apply own values on top (excluding 'inherits' key - it's metadata, not a value)\n const { inherits: _inherits, ...ownValues } = sectionObj;\n merged = { ...merged, ...ownValues };\n\n resolving.delete(name);\n resolved[name] = merged;\n return merged;\n }\n\n // Resolve all sections\n for (const name of Object.keys(config)) {\n resolveSection(name);\n }\n\n return resolved as unknown as CLIConfig;\n}\n","import { Eta } from \"eta\";\n\n/**\n * Configuration for reusable prompt templates.\n * Each key is a prompt name, value is the template string.\n */\nexport interface PromptsConfig {\n [name: string]: string;\n}\n\n/**\n * Error thrown when template processing fails.\n */\nexport class TemplateError extends Error {\n constructor(\n message: string,\n public readonly promptName?: string,\n public readonly configPath?: string,\n ) {\n super(promptName ? `[prompts.${promptName}]: ${message}` : message);\n this.name = \"TemplateError\";\n }\n}\n\n/**\n * Creates an Eta instance configured with prompts as named templates.\n * Templates are registered with an @ prefix (e.g., @base-assistant).\n *\n * @param prompts - Map of prompt names to template strings\n * @param configPath - Path to config file for error messages\n * @returns Configured Eta instance\n * @throws TemplateError if a template has invalid syntax\n */\nexport function createTemplateEngine(prompts: PromptsConfig, configPath?: string): Eta {\n const eta = new Eta({\n views: \"/\", // Required but we use named templates\n autoEscape: false, // Don't escape - these are prompts, not HTML\n autoTrim: false, // Preserve whitespace in prompts\n });\n\n // Register all prompts as named templates with @ prefix\n // loadTemplate parses the template and will throw on syntax errors\n for (const [name, template] of Object.entries(prompts)) {\n try {\n eta.loadTemplate(`@${name}`, template);\n } catch (error) {\n throw new TemplateError(\n error instanceof Error ? error.message : String(error),\n name,\n configPath,\n );\n }\n }\n\n return eta;\n}\n\n/**\n * Resolves a template string using the configured Eta engine.\n * Injects environment variables into the context.\n *\n * @param eta - Configured Eta instance\n * @param template - Template string to resolve\n * @param context - Additional context variables\n * @param configPath - Path to config file for error messages\n * @returns Resolved template string\n */\nexport function resolveTemplate(\n eta: Eta,\n template: string,\n context: Record<string, unknown> = {},\n configPath?: string,\n): string {\n try {\n // Merge env vars and built-in variables into context\n const fullContext = {\n ...context,\n env: process.env,\n date: new Date().toISOString().split(\"T\")[0], // \"2025-12-01\"\n };\n return eta.renderString(template, fullContext);\n } catch (error) {\n throw new TemplateError(\n error instanceof Error ? error.message : String(error),\n undefined,\n configPath,\n );\n }\n}\n\n/**\n * Validates that all prompts can be compiled and references exist.\n * This is called at config load time to fail fast on errors.\n *\n * @param prompts - Map of prompt names to template strings\n * @param configPath - Path to config file for error messages\n * @throws TemplateError if validation fails\n */\nexport function validatePrompts(prompts: PromptsConfig, configPath?: string): void {\n // createTemplateEngine will throw TemplateError on syntax errors during loadTemplate\n const eta = createTemplateEngine(prompts, configPath);\n\n // Also try to render each template to catch missing includes\n for (const [name, template] of Object.entries(prompts)) {\n try {\n // Try to render with empty context to catch missing includes\n // (references to undefined prompts)\n eta.renderString(template, { env: {} });\n } catch (error) {\n throw new TemplateError(\n error instanceof Error ? error.message : String(error),\n name,\n configPath,\n );\n }\n }\n}\n\n/**\n * Validates that all environment variables referenced in a template are defined.\n *\n * @param template - Template string to check\n * @param promptName - Name of the prompt for error messages\n * @param configPath - Path to config file for error messages\n * @throws TemplateError if an undefined env var is referenced\n */\nexport function validateEnvVars(\n template: string,\n promptName?: string,\n configPath?: string,\n): void {\n // Match <%= it.env.VAR_NAME %> patterns\n const envVarPattern = /<%=\\s*it\\.env\\.(\\w+)\\s*%>/g;\n const matches = template.matchAll(envVarPattern);\n\n for (const match of matches) {\n const varName = match[1] as string;\n if (process.env[varName] === undefined) {\n throw new TemplateError(\n `Environment variable '${varName}' is not set`,\n promptName,\n configPath,\n );\n }\n }\n}\n\n/**\n * Checks if a string contains Eta template syntax.\n * Used to determine if a system prompt needs template resolution.\n *\n * @param str - String to check\n * @returns true if the string contains template syntax\n */\nexport function hasTemplateSyntax(str: string): boolean {\n return str.includes(\"<%\");\n}\n","/**\n * CLI command for testing and inspecting gadgets outside the agent loop.\n * Provides `gadget run`, `gadget info`, and `gadget validate` subcommands.\n *\n * @module cli/gadget-command\n */\n\nimport type { Command } from \"commander\";\nimport chalk from \"chalk\";\n\nimport type { BaseGadget } from \"../gadgets/gadget.js\";\nimport { schemaToJSONSchema } from \"../gadgets/schema-to-json.js\";\nimport { validateGadgetSchema } from \"../gadgets/schema-validator.js\";\n\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { loadGadgets } from \"./gadgets.js\";\nimport { promptForParameters, readStdinJson } from \"./gadget-prompts.js\";\nimport { executeAction } from \"./utils.js\";\n\n/**\n * Result of selecting a gadget from a file.\n */\ninterface GadgetSelection {\n gadget: BaseGadget;\n name: string;\n}\n\n/**\n * Options for the `gadget run` subcommand.\n */\ninterface GadgetRunOptions {\n name?: string;\n json?: boolean;\n raw?: boolean;\n}\n\n/**\n * Options for the `gadget info` subcommand.\n */\ninterface GadgetInfoOptions {\n name?: string;\n json?: boolean;\n}\n\n/**\n * Loads and selects a gadget from a file.\n * - Single gadget: returns it directly\n * - Multiple gadgets without --name: throws error listing available names\n * - Multiple gadgets with --name: finds matching gadget\n *\n * @param file - Path to gadget file\n * @param nameOption - Optional gadget name for selection\n * @param cwd - Current working directory\n * @returns Selected gadget with its name\n */\nasync function selectGadget(\n file: string,\n nameOption: string | undefined,\n cwd: string,\n): Promise<GadgetSelection> {\n const gadgets = await loadGadgets([file], cwd);\n\n if (gadgets.length === 0) {\n throw new Error(\n `No gadgets found in '${file}'.\\n` +\n \"Ensure the file exports a Gadget class or instance.\",\n );\n }\n\n // Single gadget - return it\n if (gadgets.length === 1) {\n const gadget = gadgets[0];\n const name = gadget.name ?? gadget.constructor.name;\n return { gadget, name };\n }\n\n // Multiple gadgets - need --name selection\n const names = gadgets.map((g) => g.name ?? g.constructor.name);\n\n if (!nameOption) {\n throw new Error(\n `File '${file}' exports ${gadgets.length} gadgets.\\n` +\n `Use --name to select one:\\n` +\n names.map((n) => ` - ${n}`).join(\"\\n\"),\n );\n }\n\n // Find by name (case-sensitive)\n const found = gadgets.find((g) => (g.name ?? g.constructor.name) === nameOption);\n\n if (!found) {\n throw new Error(\n `Gadget '${nameOption}' not found in '${file}'.\\n` +\n `Available gadgets:\\n` +\n names.map((n) => ` - ${n}`).join(\"\\n\"),\n );\n }\n\n return { gadget: found, name: nameOption };\n}\n\n/**\n * Executes the `gadget run` subcommand.\n * Loads a gadget, prompts for parameters (or reads from stdin), and executes it.\n */\nasync function executeGadgetRun(\n file: string,\n options: GadgetRunOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const cwd = process.cwd();\n const { gadget, name } = await selectGadget(file, options.name, cwd);\n\n env.stderr.write(chalk.cyan.bold(`\\n🔧 Running gadget: ${name}\\n`));\n\n // Get parameters - either interactive or from stdin\n let params: Record<string, unknown>;\n\n if (env.isTTY) {\n // Interactive mode: prompt for each parameter\n params = await promptForParameters(gadget.parameterSchema, {\n stdin: env.stdin,\n stdout: env.stderr, // Prompts go to stderr to keep stdout clean\n });\n } else {\n // Non-TTY mode: read JSON from stdin\n env.stderr.write(chalk.dim(\"Reading parameters from stdin...\\n\"));\n const stdinParams = await readStdinJson(env.stdin);\n\n // Validate through Zod if schema exists\n if (gadget.parameterSchema) {\n const result = gadget.parameterSchema.safeParse(stdinParams);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid parameters:\\n${issues}`);\n }\n params = result.data as Record<string, unknown>;\n } else {\n params = stdinParams;\n }\n }\n\n env.stderr.write(chalk.dim(\"\\nExecuting...\\n\"));\n\n // Execute with timeout if configured\n const startTime = Date.now();\n let result: string;\n\n try {\n if (gadget.timeoutMs && gadget.timeoutMs > 0) {\n result = await Promise.race([\n Promise.resolve(gadget.execute(params)),\n new Promise<never>((_, reject) =>\n setTimeout(\n () => reject(new Error(`Gadget timed out after ${gadget.timeoutMs}ms`)),\n gadget.timeoutMs,\n ),\n ),\n ]);\n } else {\n result = await Promise.resolve(gadget.execute(params));\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Execution failed: ${message}`);\n }\n\n const elapsed = Date.now() - startTime;\n env.stderr.write(chalk.green(`\\n✓ Completed in ${elapsed}ms\\n\\n`));\n\n // Output result\n formatOutput(result, options, env.stdout);\n}\n\n/**\n * Formats and writes the gadget execution result to stdout.\n */\nfunction formatOutput(\n result: string,\n options: GadgetRunOptions,\n stdout: NodeJS.WritableStream,\n): void {\n // Raw mode: output as-is\n if (options.raw) {\n stdout.write(result);\n if (!result.endsWith(\"\\n\")) stdout.write(\"\\n\");\n return;\n }\n\n // JSON mode or auto-detect JSON\n if (options.json || looksLikeJson(result)) {\n try {\n const parsed = JSON.parse(result);\n stdout.write(JSON.stringify(parsed, null, 2) + \"\\n\");\n return;\n } catch {\n // Not valid JSON, output as-is\n }\n }\n\n // Default: output as-is with trailing newline\n stdout.write(result);\n if (!result.endsWith(\"\\n\")) stdout.write(\"\\n\");\n}\n\n/**\n * Checks if a string looks like JSON (starts with { or [).\n */\nfunction looksLikeJson(str: string): boolean {\n const trimmed = str.trim();\n return (\n (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) ||\n (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\"))\n );\n}\n\n/**\n * Executes the `gadget info` subcommand.\n * Displays gadget description, schema, and examples.\n */\nasync function executeGadgetInfo(\n file: string,\n options: GadgetInfoOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const cwd = process.cwd();\n const { gadget, name } = await selectGadget(file, options.name, cwd);\n\n if (options.json) {\n // JSON output for programmatic use\n const info = buildGadgetInfo(gadget, name);\n env.stdout.write(JSON.stringify(info, null, 2) + \"\\n\");\n return;\n }\n\n // Pretty-printed output\n env.stdout.write(\"\\n\");\n env.stdout.write(chalk.cyan.bold(`${name}\\n`));\n env.stdout.write(chalk.cyan(\"═\".repeat(name.length)) + \"\\n\\n\");\n\n // Description\n env.stdout.write(chalk.bold(\"Description:\\n\"));\n env.stdout.write(` ${gadget.description}\\n\\n`);\n\n // Parameters\n if (gadget.parameterSchema) {\n env.stdout.write(chalk.bold(\"Parameters:\\n\"));\n const jsonSchema = schemaToJSONSchema(gadget.parameterSchema, { target: \"draft-7\" });\n env.stdout.write(formatSchemaAsText(jsonSchema, \" \") + \"\\n\\n\");\n } else {\n env.stdout.write(chalk.dim(\"No parameters required.\\n\\n\"));\n }\n\n // Timeout\n if (gadget.timeoutMs) {\n env.stdout.write(chalk.bold(\"Timeout:\\n\"));\n env.stdout.write(` ${gadget.timeoutMs}ms\\n\\n`);\n }\n\n // Examples\n if (gadget.examples && gadget.examples.length > 0) {\n env.stdout.write(chalk.bold(\"Examples:\\n\"));\n for (const example of gadget.examples) {\n if (example.comment) {\n env.stdout.write(chalk.dim(` # ${example.comment}\\n`));\n }\n env.stdout.write(` Input: ${chalk.cyan(JSON.stringify(example.params))}\\n`);\n if (example.output !== undefined) {\n env.stdout.write(` Output: ${chalk.green(example.output)}\\n`);\n }\n env.stdout.write(\"\\n\");\n }\n }\n}\n\n/**\n * Builds a JSON-serializable info object for a gadget.\n */\nfunction buildGadgetInfo(gadget: BaseGadget, name: string): Record<string, unknown> {\n const info: Record<string, unknown> = {\n name,\n description: gadget.description,\n };\n\n if (gadget.parameterSchema) {\n info.schema = schemaToJSONSchema(gadget.parameterSchema, { target: \"draft-7\" });\n }\n\n if (gadget.timeoutMs) {\n info.timeoutMs = gadget.timeoutMs;\n }\n\n if (gadget.examples && gadget.examples.length > 0) {\n info.examples = gadget.examples;\n }\n\n return info;\n}\n\n/**\n * Formats a JSON Schema as readable text with indentation.\n */\nfunction formatSchemaAsText(schema: Record<string, unknown>, indent = \"\"): string {\n const lines: string[] = [];\n const properties = (schema.properties || {}) as Record<string, Record<string, unknown>>;\n const required = (schema.required || []) as string[];\n\n for (const [key, prop] of Object.entries(properties)) {\n const type = prop.type as string;\n const description = prop.description as string | undefined;\n const isRequired = required.includes(key);\n const enumValues = prop.enum as string[] | undefined;\n const defaultValue = prop.default;\n\n // Build the line\n let line = `${indent}${chalk.cyan(key)}`;\n\n // Required marker\n if (isRequired) {\n line += chalk.red(\"*\");\n }\n\n // Type info\n if (type === \"array\") {\n const items = prop.items as Record<string, unknown> | undefined;\n const itemType = items?.type || \"any\";\n line += chalk.dim(` (${itemType}[])`);\n } else if (type === \"object\" && prop.properties) {\n line += chalk.dim(\" (object)\");\n } else {\n line += chalk.dim(` (${type})`);\n }\n\n // Default value\n if (defaultValue !== undefined) {\n line += chalk.dim(` [default: ${JSON.stringify(defaultValue)}]`);\n }\n\n // Description\n if (description) {\n line += `: ${description}`;\n }\n\n // Enum values\n if (enumValues) {\n line += chalk.yellow(` - one of: ${enumValues.join(\", \")}`);\n }\n\n lines.push(line);\n\n // Recurse for nested objects\n if (type === \"object\" && prop.properties) {\n lines.push(formatSchemaAsText(prop, indent + \" \"));\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Executes the `gadget validate` subcommand.\n * Checks if a file exports valid gadget(s).\n */\nasync function executeGadgetValidate(file: string, env: CLIEnvironment): Promise<void> {\n const cwd = process.cwd();\n\n try {\n const gadgets = await loadGadgets([file], cwd);\n\n if (gadgets.length === 0) {\n throw new Error(\n \"No gadgets exported from file.\\n\" +\n \"A valid gadget must have:\\n\" +\n \" - execute() method\\n\" +\n \" - description property\\n\" +\n \" - parameterSchema (optional)\",\n );\n }\n\n // Validate each gadget's structure and schema\n const issues: string[] = [];\n\n for (const gadget of gadgets) {\n const name = gadget.name ?? gadget.constructor.name;\n\n // Check required fields\n if (!gadget.description) {\n issues.push(`${name}: Missing 'description' property.`);\n }\n\n // Validate schema if present\n if (gadget.parameterSchema) {\n try {\n validateGadgetSchema(gadget.parameterSchema, name);\n } catch (schemaError) {\n const message = schemaError instanceof Error ? schemaError.message : String(schemaError);\n issues.push(`${name}: ${message}`);\n }\n }\n\n // Check execute method\n if (typeof gadget.execute !== \"function\") {\n issues.push(`${name}: Missing 'execute()' method.`);\n }\n }\n\n if (issues.length > 0) {\n throw new Error(`Validation issues:\\n${issues.map((i) => ` - ${i}`).join(\"\\n\")}`);\n }\n\n // Success output\n env.stdout.write(chalk.green.bold(\"\\n✓ Valid\\n\\n\"));\n env.stdout.write(chalk.bold(\"Gadgets found:\\n\"));\n\n for (const gadget of gadgets) {\n const name = gadget.name ?? gadget.constructor.name;\n const schemaInfo = gadget.parameterSchema\n ? chalk.cyan(\"(with schema)\")\n : chalk.dim(\"(no schema)\");\n env.stdout.write(` ${chalk.bold(name)} ${schemaInfo}\\n`);\n env.stdout.write(chalk.dim(` ${gadget.description}\\n`));\n }\n\n env.stdout.write(\"\\n\");\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n env.stdout.write(chalk.red.bold(`\\n✗ Invalid\\n\\n`));\n env.stdout.write(`${message}\\n\\n`);\n env.setExitCode(1);\n }\n}\n\n/**\n * Registers the `gadget` command group with run/info/validate subcommands.\n *\n * @param program - Commander program to register on\n * @param env - CLI environment for I/O\n */\nexport function registerGadgetCommand(program: Command, env: CLIEnvironment): void {\n const gadgetCmd = program\n .command(\"gadget\")\n .description(\"Test and inspect gadgets outside the agent loop.\");\n\n // Subcommand: run\n gadgetCmd\n .command(\"run <file>\")\n .description(\"Execute a gadget with interactive prompts or stdin JSON.\")\n .option(\"--name <gadget>\", \"Select gadget by name (required if file exports multiple)\")\n .option(\"--json\", \"Format output as pretty-printed JSON\")\n .option(\"--raw\", \"Output result as raw string without formatting\")\n .action((file: string, options: GadgetRunOptions) =>\n executeAction(() => executeGadgetRun(file, options, env), env),\n );\n\n // Subcommand: info\n gadgetCmd\n .command(\"info <file>\")\n .description(\"Display gadget description, schema, and examples.\")\n .option(\"--name <gadget>\", \"Select gadget by name (required if file exports multiple)\")\n .option(\"--json\", \"Output as JSON instead of formatted text\")\n .action((file: string, options: GadgetInfoOptions) =>\n executeAction(() => executeGadgetInfo(file, options, env), env),\n );\n\n // Subcommand: validate\n gadgetCmd\n .command(\"validate <file>\")\n .description(\"Check if file exports valid gadget(s).\")\n .action((file: string) =>\n executeAction(() => executeGadgetValidate(file, env), env),\n );\n}\n","/**\n * Interactive prompts for schema-driven gadget parameter input.\n * Converts Zod schemas to JSON Schema for introspection and prompts\n * users for each parameter with type hints, descriptions, and defaults.\n *\n * @module cli/gadget-prompts\n */\n\nimport { createInterface } from \"node:readline/promises\";\nimport chalk from \"chalk\";\nimport type { ZodTypeAny } from \"zod\";\n\nimport { schemaToJSONSchema } from \"../gadgets/schema-to-json.js\";\n\n/**\n * Context for interactive prompting.\n */\nexport interface PromptContext {\n stdin: NodeJS.ReadableStream;\n stdout: NodeJS.WritableStream;\n}\n\n/**\n * JSON Schema property representation for a single field.\n */\ninterface JsonSchemaProperty {\n type?: string;\n description?: string;\n enum?: string[];\n default?: unknown;\n items?: { type?: string; enum?: string[] };\n properties?: Record<string, JsonSchemaProperty>;\n required?: string[];\n}\n\n/**\n * Prompts user for parameter values based on Zod schema.\n * Displays type hints, descriptions, and defaults for each field.\n * Returns validated and transformed parameters.\n *\n * @param schema - Zod schema describing expected parameters\n * @param ctx - I/O context for prompts\n * @returns Object containing user-provided parameter values\n */\nexport async function promptForParameters(\n schema: ZodTypeAny | undefined,\n ctx: PromptContext,\n): Promise<Record<string, unknown>> {\n if (!schema) {\n return {}; // No parameters required\n }\n\n const jsonSchema = schemaToJSONSchema(schema, { target: \"draft-7\" }) as {\n properties?: Record<string, JsonSchemaProperty>;\n required?: string[];\n };\n\n if (!jsonSchema.properties || Object.keys(jsonSchema.properties).length === 0) {\n return {};\n }\n\n const rl = createInterface({ input: ctx.stdin, output: ctx.stdout });\n const params: Record<string, unknown> = {};\n\n try {\n for (const [key, prop] of Object.entries(jsonSchema.properties)) {\n const value = await promptForField(rl, key, prop, jsonSchema.required ?? []);\n if (value !== undefined) {\n params[key] = value;\n }\n }\n } finally {\n rl.close();\n }\n\n // Validate and apply defaults/transforms through Zod\n const result = schema.safeParse(params);\n if (!result.success) {\n const issues = result.error.issues\n .map((i) => ` ${i.path.join(\".\")}: ${i.message}`)\n .join(\"\\n\");\n throw new Error(`Invalid parameters:\\n${issues}`);\n }\n\n return result.data as Record<string, unknown>;\n}\n\n/**\n * Prompts for a single field value with type-aware formatting.\n */\nasync function promptForField(\n rl: ReturnType<typeof createInterface>,\n key: string,\n prop: JsonSchemaProperty,\n required: string[],\n): Promise<unknown> {\n const isRequired = required.includes(key);\n const typeHint = formatTypeHint(prop);\n const defaultHint =\n prop.default !== undefined ? chalk.dim(` [default: ${JSON.stringify(prop.default)}]`) : \"\";\n const requiredMarker = isRequired ? chalk.red(\"*\") : \"\";\n\n // Build prompt with description\n let prompt = `\\n${chalk.cyan.bold(key)}${requiredMarker}`;\n if (prop.description) {\n prompt += chalk.dim(` - ${prop.description}`);\n }\n prompt += `\\n ${typeHint}${defaultHint}\\n ${chalk.green(\">\")} `;\n\n const answer = await rl.question(prompt);\n const trimmed = answer.trim();\n\n // Handle empty input\n if (!trimmed) {\n if (prop.default !== undefined) {\n return undefined; // Let Zod apply default\n }\n if (!isRequired) {\n return undefined; // Optional field, skip\n }\n throw new Error(`Parameter '${key}' is required.`);\n }\n\n // Parse based on type\n return parseValue(trimmed, prop, key);\n}\n\n/**\n * Formats the type hint for display (e.g., \"(number)\", \"(add | subtract)\").\n */\nfunction formatTypeHint(prop: JsonSchemaProperty): string {\n // Enum types: show allowed values\n if (prop.enum) {\n return chalk.yellow(`(${prop.enum.join(\" | \")})`);\n }\n\n // Array types: show item type\n if (prop.type === \"array\") {\n const items = prop.items;\n if (items?.enum) {\n return chalk.yellow(`(${items.enum.join(\" | \")})[] comma-separated`);\n }\n const itemType = items?.type ?? \"any\";\n return chalk.yellow(`(${itemType}[]) comma-separated`);\n }\n\n // Object types: indicate nested structure\n if (prop.type === \"object\" && prop.properties) {\n return chalk.yellow(\"(object) enter as JSON\");\n }\n\n // Simple types\n return chalk.yellow(`(${prop.type ?? \"any\"})`);\n}\n\n/**\n * Parses a string value into the appropriate type based on schema.\n */\nfunction parseValue(input: string, prop: JsonSchemaProperty, key: string): unknown {\n const type = prop.type;\n\n // Numbers\n if (type === \"number\" || type === \"integer\") {\n const num = Number(input);\n if (Number.isNaN(num)) {\n throw new Error(`Invalid number for '${key}': ${input}`);\n }\n if (type === \"integer\" && !Number.isInteger(num)) {\n throw new Error(`Expected integer for '${key}', got: ${input}`);\n }\n return num;\n }\n\n // Booleans\n if (type === \"boolean\") {\n const lower = input.toLowerCase();\n if ([\"true\", \"yes\", \"1\", \"y\"].includes(lower)) return true;\n if ([\"false\", \"no\", \"0\", \"n\"].includes(lower)) return false;\n throw new Error(`Invalid boolean for '${key}': ${input} (use true/false, yes/no, 1/0)`);\n }\n\n // Arrays (comma-separated)\n if (type === \"array\") {\n const items = input.split(\",\").map((s) => s.trim()).filter(Boolean);\n const itemType = prop.items?.type;\n\n // Convert array items to appropriate type\n if (itemType === \"number\" || itemType === \"integer\") {\n return items.map((item) => {\n const num = Number(item);\n if (Number.isNaN(num)) throw new Error(`Invalid number in '${key}' array: ${item}`);\n return num;\n });\n }\n if (itemType === \"boolean\") {\n return items.map((item) => {\n const lower = item.toLowerCase();\n if ([\"true\", \"yes\", \"1\", \"y\"].includes(lower)) return true;\n if ([\"false\", \"no\", \"0\", \"n\"].includes(lower)) return false;\n throw new Error(`Invalid boolean in '${key}' array: ${item}`);\n });\n }\n return items; // String array\n }\n\n // Objects (parse as JSON)\n if (type === \"object\") {\n try {\n return JSON.parse(input);\n } catch {\n throw new Error(`Invalid JSON for '${key}': ${input}`);\n }\n }\n\n // String (default) - also handles enums which are validated by Zod\n return input;\n}\n\n/**\n * Reads JSON parameters from stdin (for non-TTY piped input).\n *\n * @param stdin - Readable stream to read from\n * @returns Parsed JSON object\n */\nexport async function readStdinJson(stdin: NodeJS.ReadableStream): Promise<Record<string, unknown>> {\n const chunks: string[] = [];\n\n for await (const chunk of stdin) {\n if (typeof chunk === \"string\") {\n chunks.push(chunk);\n } else {\n chunks.push(chunk.toString(\"utf8\"));\n }\n }\n\n const content = chunks.join(\"\").trim();\n\n if (!content) {\n return {}; // Empty stdin, use defaults\n }\n\n try {\n const parsed = JSON.parse(content);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(\"Stdin must contain a JSON object, not an array or primitive.\");\n }\n return parsed as Record<string, unknown>;\n } catch (error) {\n if (error instanceof SyntaxError) {\n throw new Error(`Invalid JSON from stdin: ${error.message}`);\n }\n throw error;\n }\n}\n","import { type Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { COMMANDS } from \"./constants.js\";\nimport type { CLIEnvironment } from \"./environment.js\";\nimport { executeAction } from \"./utils.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport { MODEL_ALIASES } from \"../core/model-shortcuts.js\";\n\ninterface ModelsCommandOptions {\n provider?: string;\n format?: \"table\" | \"json\";\n verbose?: boolean;\n}\n\nasync function handleModelsCommand(\n options: ModelsCommandOptions,\n env: CLIEnvironment,\n): Promise<void> {\n const client = env.createClient();\n\n // Get models, optionally filtered by provider\n const models = client.modelRegistry.listModels(options.provider);\n\n if (options.format === \"json\") {\n renderJSON(models, env.stdout);\n } else {\n renderTable(models, options.verbose || false, env.stdout);\n }\n}\n\nfunction renderTable(models: ModelSpec[], verbose: boolean, stream: NodeJS.WritableStream): void {\n // Group models by provider\n const grouped = new Map<string, ModelSpec[]>();\n for (const model of models) {\n const provider = model.provider;\n if (!grouped.has(provider)) {\n grouped.set(provider, []);\n }\n grouped.get(provider)!.push(model);\n }\n\n // Header\n stream.write(chalk.bold.cyan(\"\\nAvailable Models\\n\"));\n stream.write(chalk.cyan(\"=\".repeat(80)) + \"\\n\\n\");\n\n // Display each provider's models\n const providers = Array.from(grouped.keys()).sort();\n for (const provider of providers) {\n const providerModels = grouped.get(provider)!;\n const providerName = provider.charAt(0).toUpperCase() + provider.slice(1);\n\n stream.write(chalk.bold.yellow(`${providerName} Models\\n`));\n\n if (verbose) {\n renderVerboseTable(providerModels, stream);\n } else {\n renderCompactTable(providerModels, stream);\n }\n\n stream.write(\"\\n\");\n }\n\n // Display shortcuts\n stream.write(chalk.bold.magenta(\"Model Shortcuts\\n\"));\n stream.write(chalk.dim(\"─\".repeat(80)) + \"\\n\");\n\n const shortcuts = Object.entries(MODEL_ALIASES).sort((a, b) => a[0].localeCompare(b[0]));\n for (const [shortcut, fullName] of shortcuts) {\n stream.write(chalk.cyan(` ${shortcut.padEnd(15)}`) + chalk.dim(\" → \") + chalk.white(fullName) + \"\\n\");\n }\n stream.write(\"\\n\");\n}\n\nfunction renderCompactTable(models: ModelSpec[], stream: NodeJS.WritableStream): void {\n // Column widths\n const idWidth = 25;\n const nameWidth = 22;\n const contextWidth = 13;\n const inputWidth = 10;\n const outputWidth = 10;\n\n // Header\n stream.write(chalk.dim(\"─\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\n\");\n stream.write(\n chalk.bold(\n \"Model ID\".padEnd(idWidth) +\n \" \" + \"Display Name\".padEnd(nameWidth) +\n \" \" + \"Context\".padEnd(contextWidth) +\n \" \" + \"Input\".padEnd(inputWidth) +\n \" \" + \"Output\".padEnd(outputWidth)\n ) + \"\\n\"\n );\n stream.write(chalk.dim(\"─\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\n\");\n\n // Rows\n for (const model of models) {\n const contextFormatted = formatTokens(model.contextWindow);\n const inputPrice = `$${model.pricing.input.toFixed(2)}`;\n const outputPrice = `$${model.pricing.output.toFixed(2)}`;\n\n stream.write(\n chalk.green(model.modelId.padEnd(idWidth)) +\n \" \" + chalk.white(model.displayName.padEnd(nameWidth)) +\n \" \" + chalk.yellow(contextFormatted.padEnd(contextWidth)) +\n \" \" + chalk.cyan(inputPrice.padEnd(inputWidth)) +\n \" \" + chalk.cyan(outputPrice.padEnd(outputWidth)) +\n \"\\n\"\n );\n }\n\n stream.write(chalk.dim(\"─\".repeat(idWidth + nameWidth + contextWidth + inputWidth + outputWidth + 8)) + \"\\n\");\n stream.write(chalk.dim(` * Prices are per 1M tokens\\n`));\n}\n\nfunction renderVerboseTable(models: ModelSpec[], stream: NodeJS.WritableStream): void {\n for (const model of models) {\n stream.write(chalk.bold.green(`\\n ${model.modelId}\\n`));\n stream.write(chalk.dim(\" \" + \"─\".repeat(60)) + \"\\n\");\n stream.write(` ${chalk.dim(\"Name:\")} ${chalk.white(model.displayName)}\\n`);\n stream.write(` ${chalk.dim(\"Context:\")} ${chalk.yellow(formatTokens(model.contextWindow))}\\n`);\n stream.write(` ${chalk.dim(\"Max Output:\")} ${chalk.yellow(formatTokens(model.maxOutputTokens))}\\n`);\n stream.write(` ${chalk.dim(\"Pricing:\")} ${chalk.cyan(`$${model.pricing.input.toFixed(2)} input`)} ${chalk.dim(\"/\")} ${chalk.cyan(`$${model.pricing.output.toFixed(2)} output`)} ${chalk.dim(\"(per 1M tokens)\")}\\n`);\n\n if (model.pricing.cachedInput !== undefined) {\n stream.write(` ${chalk.dim(\"Cached Input:\")} ${chalk.cyan(`$${model.pricing.cachedInput.toFixed(2)} per 1M tokens`)}\\n`);\n }\n\n if (model.knowledgeCutoff) {\n stream.write(` ${chalk.dim(\"Knowledge:\")} ${model.knowledgeCutoff}\\n`);\n }\n\n // Features\n const features: string[] = [];\n if (model.features.streaming) features.push(\"streaming\");\n if (model.features.functionCalling) features.push(\"function-calling\");\n if (model.features.vision) features.push(\"vision\");\n if (model.features.reasoning) features.push(\"reasoning\");\n if (model.features.structuredOutputs) features.push(\"structured-outputs\");\n if (model.features.fineTuning) features.push(\"fine-tuning\");\n\n if (features.length > 0) {\n stream.write(` ${chalk.dim(\"Features:\")} ${chalk.blue(features.join(\", \"))}\\n`);\n }\n\n // Metadata\n if (model.metadata) {\n if (model.metadata.family) {\n stream.write(` ${chalk.dim(\"Family:\")} ${model.metadata.family}\\n`);\n }\n if (model.metadata.releaseDate) {\n stream.write(` ${chalk.dim(\"Released:\")} ${model.metadata.releaseDate}\\n`);\n }\n if (model.metadata.notes) {\n stream.write(` ${chalk.dim(\"Notes:\")} ${chalk.italic(model.metadata.notes)}\\n`);\n }\n }\n }\n stream.write(\"\\n\");\n}\n\nfunction renderJSON(models: ModelSpec[], stream: NodeJS.WritableStream): void {\n const output = {\n models: models.map(model => ({\n provider: model.provider,\n modelId: model.modelId,\n displayName: model.displayName,\n contextWindow: model.contextWindow,\n maxOutputTokens: model.maxOutputTokens,\n pricing: {\n input: model.pricing.input,\n output: model.pricing.output,\n cachedInput: model.pricing.cachedInput,\n currency: \"USD\",\n per: \"1M tokens\",\n },\n knowledgeCutoff: model.knowledgeCutoff,\n features: model.features,\n metadata: model.metadata,\n })),\n shortcuts: MODEL_ALIASES,\n };\n\n stream.write(JSON.stringify(output, null, 2) + \"\\n\");\n}\n\nfunction formatTokens(count: number): string {\n if (count >= 1_000_000) {\n return `${(count / 1_000_000).toFixed(1)}M tokens`;\n } else if (count >= 1_000) {\n return `${(count / 1_000).toFixed(0)}K tokens`;\n } else {\n return `${count} tokens`;\n }\n}\n\nexport function registerModelsCommand(program: Command, env: CLIEnvironment): void {\n program\n .command(COMMANDS.models)\n .description(\"List all available LLM models with pricing and capabilities.\")\n .option(\"--provider <name>\", \"Filter by provider (openai, anthropic, gemini)\")\n .option(\"--format <format>\", \"Output format: table or json\", \"table\")\n .option(\"--verbose\", \"Show detailed model information\", false)\n .action((options) =>\n executeAction(\n () => handleModelsCommand(options as ModelsCommandOptions, env),\n env,\n ),\n );\n}\n","import readline from \"node:readline\";\nimport chalk from \"chalk\";\nimport type { ILogObj, Logger } from \"tslog\";\nimport { LLMist } from \"../core/client.js\";\nimport type { LoggerOptions } from \"../logging/logger.js\";\nimport { createLogger } from \"../logging/logger.js\";\n\n/**\n * Stream type that may have TTY capabilities.\n */\nexport type TTYStream = NodeJS.ReadableStream & { isTTY?: boolean };\n\n/**\n * Logger configuration for CLI commands.\n */\nexport interface CLILoggerConfig {\n logLevel?: string;\n logFile?: string;\n logReset?: boolean;\n}\n\n/**\n * Environment abstraction for CLI dependencies and I/O.\n * Allows dependency injection for testing.\n */\nexport interface CLIEnvironment {\n argv: string[];\n stdin: TTYStream;\n stdout: NodeJS.WritableStream;\n stderr: NodeJS.WritableStream;\n createClient: () => LLMist;\n setExitCode: (code: number) => void;\n loggerConfig?: CLILoggerConfig;\n createLogger: (name: string) => Logger<ILogObj>;\n /** Whether stdin is a TTY (interactive terminal) */\n isTTY: boolean;\n /** Prompt the user for input (only works when isTTY is true) */\n prompt: (question: string) => Promise<string>;\n}\n\nconst LOG_LEVEL_MAP: Record<string, number> = {\n silly: 0,\n trace: 1,\n debug: 2,\n info: 3,\n warn: 4,\n error: 5,\n fatal: 6,\n};\n\n/**\n * Creates a logger factory based on CLI configuration.\n * Priority: CLI options > environment variables > defaults\n */\nfunction createLoggerFactory(config?: CLILoggerConfig): (name: string) => Logger<ILogObj> {\n return (name: string) => {\n const options: LoggerOptions = { name };\n\n // CLI --log-level takes priority over LLMIST_LOG_LEVEL env var\n if (config?.logLevel) {\n const level = config.logLevel.toLowerCase();\n if (level in LOG_LEVEL_MAP) {\n options.minLevel = LOG_LEVEL_MAP[level];\n }\n }\n\n // CLI --log-reset takes priority over LLMIST_LOG_RESET env var\n if (config?.logReset !== undefined) {\n options.logReset = config.logReset;\n }\n\n // CLI --log-file takes priority over LLMIST_LOG_FILE env var\n // When log file is set via CLI, we temporarily set the env var\n // so createLogger picks it up\n if (config?.logFile) {\n const originalLogFile = process.env.LLMIST_LOG_FILE;\n process.env.LLMIST_LOG_FILE = config.logFile;\n const logger = createLogger(options);\n // Restore original (or delete if it wasn't set)\n if (originalLogFile === undefined) {\n delete process.env.LLMIST_LOG_FILE;\n } else {\n process.env.LLMIST_LOG_FILE = originalLogFile;\n }\n return logger;\n }\n\n // If no log file, default to pretty output (not hidden)\n if (!process.env.LLMIST_LOG_FILE) {\n options.type = \"pretty\";\n }\n\n return createLogger(options);\n };\n}\n\n/**\n * Creates a readline-based prompt function for user input.\n */\nfunction createPromptFunction(\n stdin: NodeJS.ReadableStream,\n stdout: NodeJS.WritableStream,\n): (question: string) => Promise<string> {\n return (question: string) => {\n return new Promise((resolve) => {\n const rl = readline.createInterface({\n input: stdin,\n output: stdout,\n });\n // Display question with visual styling\n stdout.write(\"\\n\");\n stdout.write(`${chalk.cyan(\"─\".repeat(60))}\\n`);\n stdout.write(chalk.cyan.bold(\"🤖 Agent asks:\\n\"));\n stdout.write(`${question}\\n`);\n stdout.write(`${chalk.cyan(\"─\".repeat(60))}\\n`);\n rl.question(chalk.green.bold(\"You: \"), (answer) => {\n rl.close();\n resolve(answer);\n });\n });\n };\n}\n\n/**\n * Creates the default CLI environment using Node.js process globals.\n * Uses process.argv, process.stdin/stdout/stderr, and creates a new LLMist client.\n *\n * @param loggerConfig - Optional logger configuration from CLI options\n * @returns Default CLI environment\n */\nexport function createDefaultEnvironment(loggerConfig?: CLILoggerConfig): CLIEnvironment {\n const isTTY = Boolean(process.stdin.isTTY);\n\n return {\n argv: process.argv,\n stdin: process.stdin,\n stdout: process.stdout,\n stderr: process.stderr,\n createClient: () => new LLMist(),\n setExitCode: (code: number) => {\n process.exitCode = code;\n },\n loggerConfig,\n createLogger: createLoggerFactory(loggerConfig),\n isTTY,\n prompt: isTTY\n ? createPromptFunction(process.stdin, process.stdout)\n : async () => {\n throw new Error(\"Cannot prompt for input: stdin is not a TTY\");\n },\n };\n}\n","import type { Command } from \"commander\";\nimport { executeAgent } from \"./agent-command.js\";\nimport { executeComplete } from \"./complete-command.js\";\nimport type { CustomCommandConfig } from \"./config.js\";\nimport { createDefaultEnvironment, type CLIEnvironment, type CLILoggerConfig } from \"./environment.js\";\nimport {\n addAgentOptions,\n addCompleteOptions,\n type AgentCommandOptions,\n type CompleteCommandOptions,\n configToAgentOptions,\n configToCompleteOptions,\n} from \"./option-helpers.js\";\nimport { executeAction } from \"./utils.js\";\n\n/**\n * Creates an environment with per-command logging config merged in.\n * If the command has logging options, creates a new environment; otherwise returns the original.\n */\nfunction createCommandEnvironment(\n baseEnv: CLIEnvironment,\n config: CustomCommandConfig,\n): CLIEnvironment {\n // Check if command has any logging overrides\n const hasLoggingConfig =\n config[\"log-level\"] !== undefined ||\n config[\"log-file\"] !== undefined ||\n config[\"log-reset\"] !== undefined;\n\n if (!hasLoggingConfig) {\n return baseEnv;\n }\n\n // Merge per-command logging config with base environment's config\n const loggerConfig: CLILoggerConfig = {\n logLevel: config[\"log-level\"] ?? baseEnv.loggerConfig?.logLevel,\n logFile: config[\"log-file\"] ?? baseEnv.loggerConfig?.logFile,\n logReset: config[\"log-reset\"] ?? baseEnv.loggerConfig?.logReset,\n };\n\n // Create new environment with merged logging config\n return createDefaultEnvironment(loggerConfig);\n}\n\n/**\n * Registers a custom command from config file.\n *\n * Custom commands are defined in ~/.llmist/cli.toml as sections like [code-review].\n * Each section can specify `type = \"agent\"` (default) or `type = \"complete\"` to\n * determine the execution behavior.\n *\n * @param program - Commander program to register the command with\n * @param name - Command name (e.g., \"code-review\")\n * @param config - Command configuration from TOML file\n * @param env - CLI environment for I/O operations\n */\nexport function registerCustomCommand(\n program: Command,\n name: string,\n config: CustomCommandConfig,\n env: CLIEnvironment,\n): void {\n const type = config.type ?? \"agent\";\n const description = config.description ?? `Custom ${type} command`;\n\n const cmd = program\n .command(name)\n .description(description)\n .argument(\"[prompt]\", \"Prompt for the command. Falls back to stdin when available.\");\n\n if (type === \"complete\") {\n // Complete type command\n addCompleteOptions(cmd, config);\n\n cmd.action((prompt, cliOptions) => {\n // Create environment with per-command logging config\n const cmdEnv = createCommandEnvironment(env, config);\n return executeAction(async () => {\n // Config values are base, CLI options override\n const configDefaults = configToCompleteOptions(config);\n const options: CompleteCommandOptions = {\n ...configDefaults,\n ...(cliOptions as Partial<CompleteCommandOptions>),\n } as CompleteCommandOptions;\n await executeComplete(prompt, options, cmdEnv);\n }, cmdEnv);\n });\n } else {\n // Agent type command (default)\n addAgentOptions(cmd, config);\n\n cmd.action((prompt, cliOptions) => {\n // Create environment with per-command logging config\n const cmdEnv = createCommandEnvironment(env, config);\n return executeAction(async () => {\n // Config values are base, CLI options override\n const configDefaults = configToAgentOptions(config);\n const options: AgentCommandOptions = {\n ...configDefaults,\n ...(cliOptions as Partial<AgentCommandOptions>),\n } as AgentCommandOptions;\n await executeAgent(prompt, options, cmdEnv);\n }, cmdEnv);\n });\n }\n}\n","#!/usr/bin/env node\nimport { SUMMARY_PREFIX } from \"./cli/constants.js\";\nimport { runCLI } from \"./cli/program.js\";\n\nrunCLI().catch((error) => {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`${SUMMARY_PREFIX} Error: ${message}\\n`);\n process.exitCode = 1;\n});\n"],"mappings":"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","names":["path","path","z","pointer","path","stream","stream","init_constants","Anthropic","init_constants","stream","init_constants","stream","OpenAI","init_constants","stream","providerSpecs","import_commander","import_promises","import_chalk","init_constants","import_zod","import_node_fs","import_node_path","path","fs","exports","import_node_path","import_chalk","init_constants","chalk","stream","chalk","gadgets","stderrTTY","chalk","init_constants","stream","import_node_fs","import_node_os","import_node_path","path","parseToml","import_chalk","import_promises","import_chalk","chalk","chalk","result","import_chalk","stream","chalk","formatTokens","import_chalk","readline","chalk","parseLogLevel"]}
|