llmist 0.8.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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/exceptions.ts","../src/gadgets/executor.ts","../src/gadgets/parser.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/index.ts","../src/agent/hook-presets.ts","../src/agent/index.ts","../src/gadgets/typed-gadget.ts","../src/gadgets/validation.ts","../src/testing/mock-manager.ts","../src/testing/mock-stream.ts","../src/testing/mock-adapter.ts","../src/testing/mock-builder.ts","../src/testing/mock-client.ts","../src/testing/mock-gadget.ts"],"sourcesContent":["// Gadget marker constants\nexport const GADGET_START_PREFIX = \"!!!GADGET_START:\";\nexport const GADGET_END_PREFIX = \"!!!GADGET_END\";\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","import type { ParameterFormat } from \"../gadgets/parser.js\";\n\n/**\n * Context provided to prompt template functions for rendering dynamic content.\n */\nexport interface PromptContext {\n /** The parameter format being used (json or yaml) */\n parameterFormat: ParameterFormat;\n /** Custom gadget start prefix */\n startPrefix: string;\n /** Custom gadget end prefix */\n endPrefix: 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 YAML parameter format.\n * Default: \"Parameters in YAML format (one per line)\"\n */\n formatDescriptionYaml?: PromptTemplate;\n\n /**\n * Format description for JSON parameter format.\n * Default: \"Parameters in JSON format (valid JSON object)\"\n */\n formatDescriptionJson?: PromptTemplate;\n\n /**\n * Format description for TOML parameter format.\n * Default: \"Parameters in TOML format (key = value pairs, use heredoc for multiline: key = <<<EOF ... EOF)\"\n */\n formatDescriptionToml?: 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 6 rules about not using function calling.\n */\n rules?: PromptTemplate | string[] | ((context: PromptContext) => string[]);\n\n /**\n * Schema label for JSON format.\n * Default: \"\\n\\nInput Schema (JSON):\"\n */\n schemaLabelJson?: PromptTemplate;\n\n /**\n * Schema label for YAML format.\n * Default: \"\\n\\nInput Schema (YAML):\"\n */\n schemaLabelYaml?: PromptTemplate;\n\n /**\n * Schema label for TOML format.\n * Default: \"\\n\\nInput Schema (TOML):\"\n */\n schemaLabelToml?: PromptTemplate;\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 * These match the original hardcoded strings.\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 formatDescriptionYaml: \"Parameters in YAML format (one per line)\",\n\n formatDescriptionJson: \"Parameters in JSON format (valid JSON object)\",\n\n formatDescriptionToml:\n \"Parameters in TOML format (key = value pairs, use heredoc for multiline: key = <<<EOF ... EOF)\",\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 schemaLabelJson: \"\\n\\nInput Schema (JSON):\",\n\n schemaLabelYaml: \"\\n\\nInput Schema (YAML):\",\n\n schemaLabelToml: \"\\n\\nInput Schema (TOML):\",\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 type { ParameterFormat } from \"../gadgets/parser.js\";\nimport { GADGET_END_PREFIX, GADGET_START_PREFIX } from \"./constants.js\";\nimport type { PromptConfig, PromptTemplate } 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 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): this {\n this.startPrefix = startPrefix;\n this.endPrefix = endPrefix;\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 parameterFormat: ParameterFormat = \"json\",\n options?: { startPrefix?: string; endPrefix?: 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\n const context = {\n parameterFormat,\n startPrefix: this.startPrefix,\n endPrefix: this.endPrefix,\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, parameterFormat));\n parts.push(this.buildUsageSection(parameterFormat, context));\n\n this.messages.push({ role: \"system\", content: parts.join(\"\") });\n return this;\n }\n\n private buildGadgetsSection(gadgets: BaseGadget[], parameterFormat: ParameterFormat): 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(parameterFormat);\n\n // Parse instruction to separate description and schema\n const schemaMarkers: Record<ParameterFormat, string> = {\n yaml: \"\\n\\nInput Schema (YAML):\",\n json: \"\\n\\nInput Schema (JSON):\",\n toml: \"\\n\\nInput Schema (TOML):\",\n auto: \"\\n\\nInput Schema (JSON):\", // auto defaults to JSON schema display\n };\n const schemaMarker = schemaMarkers[parameterFormat];\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 (${parameterFormat.toUpperCase()}):\\n${schema}`);\n }\n parts.push(\"\\n\\n---\");\n }\n\n return parts.join(\"\");\n }\n\n private buildUsageSection(\n parameterFormat: ParameterFormat,\n context: {\n parameterFormat: ParameterFormat;\n startPrefix: string;\n endPrefix: string;\n gadgetCount: number;\n gadgetNames: string[];\n },\n ): string {\n const parts: string[] = [];\n\n // Use configurable format description\n const formatDescriptionMap: Record<\n ParameterFormat,\n { config?: PromptTemplate; defaultValue: PromptTemplate }\n > = {\n yaml: {\n config: this.promptConfig.formatDescriptionYaml,\n defaultValue: DEFAULT_PROMPTS.formatDescriptionYaml,\n },\n json: {\n config: this.promptConfig.formatDescriptionJson,\n defaultValue: DEFAULT_PROMPTS.formatDescriptionJson,\n },\n toml: {\n config: this.promptConfig.formatDescriptionToml,\n defaultValue: DEFAULT_PROMPTS.formatDescriptionToml,\n },\n auto: {\n config: this.promptConfig.formatDescriptionJson,\n defaultValue: DEFAULT_PROMPTS.formatDescriptionJson,\n },\n };\n const { config, defaultValue } = formatDescriptionMap[parameterFormat];\n const formatDescription = resolvePromptTemplate(config, defaultValue, context);\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(parameterFormat, context));\n parts.push(this.buildRulesSection(context));\n\n parts.push(\"\\n\");\n\n return parts.join(\"\");\n }\n\n private buildExamplesSection(\n parameterFormat: ParameterFormat,\n context: {\n parameterFormat: ParameterFormat;\n startPrefix: string;\n endPrefix: string;\n gadgetCount: number;\n gadgetNames: string[];\n },\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 // Format-specific single gadget examples\n const singleExamples: Record<ParameterFormat, string> = {\n yaml: `${this.startPrefix}translate\nfrom: English\nto: Polish\ncontent: \"Paris is the capital of France: a beautiful city.\"\n${this.endPrefix}`,\n json: `${this.startPrefix}translate\n{\"from\": \"English\", \"to\": \"Polish\", \"content\": \"Paris is the capital of France: a beautiful city.\"}\n${this.endPrefix}`,\n toml: `${this.startPrefix}translate\nfrom = \"English\"\nto = \"Polish\"\ncontent = \"Paris is the capital of France: a beautiful city.\"\n${this.endPrefix}`,\n auto: `${this.startPrefix}translate\n{\"from\": \"English\", \"to\": \"Polish\", \"content\": \"Paris is the capital of France: a beautiful city.\"}\n${this.endPrefix}`,\n };\n\n parts.push(`\\n\\nEXAMPLE (Single Gadget):\\n\\n${singleExamples[parameterFormat]}`);\n\n // Format-specific multiple gadget examples (with multiline content)\n const multipleExamples: Record<ParameterFormat, string> = {\n yaml: `${this.startPrefix}translate\nfrom: English\nto: Polish\ncontent: \"Paris is the capital of France: a beautiful city.\"\n${this.endPrefix}\n${this.startPrefix}analyze\ntype: economic_analysis\nmatter: \"Polish Economy\"\nquestion: <<<EOF\nAnalyze the following:\n- Polish arms exports 2025\n- Economic implications\nEOF\n${this.endPrefix}`,\n json: `${this.startPrefix}translate\n{\"from\": \"English\", \"to\": \"Polish\", \"content\": \"Paris is the capital of France: a beautiful city.\"}\n${this.endPrefix}\n${this.startPrefix}analyze\n{\"type\": \"economic_analysis\", \"matter\": \"Polish Economy\", \"question\": \"Analyze the following: Polish arms exports 2025, economic implications\"}\n${this.endPrefix}`,\n toml: `${this.startPrefix}translate\nfrom = \"English\"\nto = \"Polish\"\ncontent = \"Paris is the capital of France: a beautiful city.\"\n${this.endPrefix}\n${this.startPrefix}analyze\ntype = \"economic_analysis\"\nmatter = \"Polish Economy\"\nquestion = <<<EOF\nAnalyze the following:\n- Polish arms exports 2025\n- Economic implications\nEOF\n${this.endPrefix}`,\n auto: `${this.startPrefix}translate\n{\"from\": \"English\", \"to\": \"Polish\", \"content\": \"Paris is the capital of France: a beautiful city.\"}\n${this.endPrefix}\n${this.startPrefix}analyze\n{\"type\": \"economic_analysis\", \"matter\": \"Polish Economy\", \"question\": \"Analyze the following: Polish arms exports 2025, economic implications\"}\n${this.endPrefix}`,\n };\n\n parts.push(`\\n\\nEXAMPLE (Multiple Gadgets):\\n\\n${multipleExamples[parameterFormat]}`);\n\n // Add format-specific syntax guides\n if (parameterFormat === \"yaml\") {\n parts.push(`\n\nYAML HEREDOC SYNTAX:\nFor string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):\n\nfilePath: \"README.md\"\ncontent: <<<EOF\n# Project Title\n\nThis content can contain:\n- Markdown lists\n- Special characters: # : -\n- Multiple paragraphs\nEOF\n\nThe delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.\nNo indentation is required for the content.`);\n } else if (parameterFormat === \"toml\") {\n parts.push(`\n\nTOML HEREDOC SYNTAX:\nFor string values with multiple lines, use heredoc syntax (<<<DELIMITER...DELIMITER):\n\nfilePath = \"README.md\"\ncontent = <<<EOF\n# Project Title\n\nThis content can contain:\n- Markdown lists\n- Special characters: # : -\n- Multiple paragraphs\nEOF\n\nThe delimiter (EOF) can be any identifier. The closing delimiter must be on its own line.\nIMPORTANT: Content inside heredoc is LITERAL - do NOT escape backticks, dollar signs, or any characters.\nNEVER use TOML triple-quote strings (\"\"\"). ALWAYS use heredoc syntax (<<<EOF...EOF) for multiline content.`);\n }\n\n return parts.join(\"\");\n }\n\n private buildRulesSection(context: {\n parameterFormat: ParameterFormat;\n startPrefix: string;\n endPrefix: 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(\n gadget: string,\n parameters: Record<string, unknown>,\n result: string,\n parameterFormat: ParameterFormat = \"json\",\n ) {\n const paramStr = this.formatParameters(parameters, parameterFormat);\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 private formatParameters(parameters: Record<string, unknown>, format: ParameterFormat): string {\n if (format === \"yaml\") {\n return Object.entries(parameters)\n .map(([key, value]) => {\n if (typeof value === \"string\") {\n return `${key}: ${value}`;\n }\n return `${key}: ${JSON.stringify(value)}`;\n })\n .join(\"\\n\");\n }\n if (format === \"toml\") {\n return Object.entries(parameters)\n .map(([key, value]) => {\n if (typeof value === \"string\" && value.includes(\"\\n\")) {\n // Use heredoc syntax to avoid teaching model to use triple-quotes\n return `${key} = <<<EOF\\n${value}\\nEOF`;\n }\n return `${key} = ${JSON.stringify(value)}`;\n })\n .join(\"\\n\");\n }\n return JSON.stringify(parameters);\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 * as yaml from \"js-yaml\";\nimport type { ZodTypeAny } from \"zod\";\n\nimport type { ParameterFormat } from \"./parser.js\";\nimport { schemaToJSONSchema } from \"./schema-to-json.js\";\nimport { validateGadgetSchema } from \"./schema-validator.js\";\nimport type { GadgetExample } from \"./types.js\";\n\n/**\n * Common heredoc delimiter names, in order of preference.\n * We try these until we find one that doesn't appear in the content.\n */\nconst HEREDOC_DELIMITERS = [\n \"__GADGET_PARAM_EOF__\",\n \"__GADGET_PARAM_END__\",\n \"__GADGET_PARAM_DOC__\",\n \"__GADGET_PARAM_CONTENT__\",\n \"__GADGET_PARAM_TEXT__\",\n \"__GADGET_PARAM_HEREDOC__\",\n \"__GADGET_PARAM_DATA__\",\n \"__GADGET_PARAM_BLOCK__\",\n];\n\n/**\n * Find a safe heredoc delimiter that doesn't appear alone on a line in the content.\n */\nfunction findSafeDelimiter(content: string): string {\n const lines = content.split(\"\\n\");\n for (const delimiter of HEREDOC_DELIMITERS) {\n // Check if this delimiter appears alone on any line\n const regex = new RegExp(`^${delimiter}\\\\s*$`);\n const isUsed = lines.some((line) => regex.test(line));\n if (!isUsed) {\n return delimiter;\n }\n }\n // Fallback: generate a unique delimiter with a number suffix\n let counter = 1;\n while (counter < 1000) {\n const delimiter = `__GADGET_PARAM_${counter}__`;\n const regex = new RegExp(`^${delimiter}\\\\s*$`);\n const isUsed = lines.some((line) => regex.test(line));\n if (!isUsed) {\n return delimiter;\n }\n counter++;\n }\n // Last resort (should never happen)\n return \"HEREDOC_FALLBACK\";\n}\n\n/**\n * Format a value for YAML output, using heredoc syntax for multiline strings.\n * This teaches LLMs to use heredoc syntax which is cleaner and doesn't require indentation.\n */\nfunction formatYamlValue(value: unknown, indent: string = \"\"): string {\n if (typeof value === \"string\") {\n const lines = value.split(\"\\n\");\n if (lines.length === 1 && !value.includes(\":\") && !value.startsWith(\"-\")) {\n // Simple single-line string without special chars - can use plain style\n return value;\n }\n // Use heredoc syntax for multiline or strings with special chars\n const delimiter = findSafeDelimiter(value);\n return `<<<${delimiter}\\n${value}\\n${delimiter}`;\n }\n\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n\n if (value === null || value === undefined) {\n return \"null\";\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) return \"[]\";\n const items = value.map((item) => `${indent}- ${formatYamlValue(item, indent + \" \")}`);\n return \"\\n\" + items.join(\"\\n\");\n }\n\n if (typeof value === \"object\") {\n const entries = Object.entries(value);\n if (entries.length === 0) return \"{}\";\n const lines = entries.map(([k, v]) => {\n const formattedValue = formatYamlValue(v, indent + \" \");\n // If value starts with newline (arrays/objects), don't add space after colon\n if (formattedValue.startsWith(\"\\n\") || formattedValue.startsWith(\"|\")) {\n return `${indent}${k}: ${formattedValue}`;\n }\n return `${indent}${k}: ${formattedValue}`;\n });\n return \"\\n\" + lines.join(\"\\n\");\n }\n\n // Fallback to yaml.dump for complex types\n return yaml.dump(value).trimEnd();\n}\n\n/**\n * Format parameters object as YAML with pipe multiline syntax for all string values.\n * This ensures examples teach LLMs to use the correct pattern.\n */\nfunction formatParamsAsYaml(params: Record<string, unknown>): string {\n const lines: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n const formattedValue = formatYamlValue(value, \"\");\n if (formattedValue.startsWith(\"\\n\")) {\n // Object or array - value on next lines (no space before newline)\n lines.push(`${key}:${formattedValue}`);\n } else {\n // Simple value or pipe multiline - space before value\n lines.push(`${key}: ${formattedValue}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format a TOML inline table (object).\n * TOML uses { key = value, key2 = value2 } syntax, NOT JSON's {\"key\": value}.\n * This is critical because LLMs copy the examples we show them in the prompt.\n */\nfunction formatTomlInlineTable(obj: Record<string, unknown>): string {\n const entries = Object.entries(obj).map(([k, v]) => `${k} = ${formatTomlValue(v)}`);\n return `{ ${entries.join(\", \")} }`;\n}\n\n/**\n * Format a value for TOML output, using heredoc syntax for multiline content.\n * This teaches LLMs to use the heredoc syntax which is cleaner for multi-line strings.\n *\n * IMPORTANT: Arrays and objects must use TOML inline table syntax, NOT JSON.stringify().\n * If we use JSON.stringify(), the LLM will copy the JSON syntax and the parser will fail.\n */\nfunction formatTomlValue(value: unknown): string {\n if (typeof value === \"string\") {\n if (value.includes(\"\\n\")) {\n // Multiline: use heredoc syntax\n const delimiter = findSafeDelimiter(value);\n return `<<<${delimiter}\\n${value}\\n${delimiter}`;\n }\n // Single line: use regular quoted string\n return JSON.stringify(value);\n }\n\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n\n if (value === null || value === undefined) {\n // TOML doesn't have null, use empty string\n return '\"\"';\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) return \"[]\";\n // Format array elements with proper TOML syntax\n const items = value.map((item) => {\n if (typeof item === \"object\" && item !== null && !Array.isArray(item)) {\n // Inline table for objects in arrays\n return formatTomlInlineTable(item as Record<string, unknown>);\n }\n return formatTomlValue(item);\n });\n return `[${items.join(\", \")}]`;\n }\n\n if (typeof value === \"object\") {\n // Use proper TOML inline table syntax for objects\n return formatTomlInlineTable(value as Record<string, unknown>);\n }\n\n return JSON.stringify(value);\n}\n\n/**\n * Format parameters object as TOML.\n */\nfunction formatParamsAsToml(params: Record<string, unknown>): string {\n const lines: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n lines.push(`${key} = ${formatTomlValue(value)}`);\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(format) instead for format-specific schemas\n */\n get instruction(): string {\n return this.getInstruction(\"yaml\");\n }\n\n /**\n * Generate instruction text for the LLM with format-specific schema.\n * Combines name, description, and parameter schema into a formatted instruction.\n *\n * @param format - Format for the schema representation ('json' | 'yaml' | 'toml' | 'auto')\n * @returns Formatted instruction string\n */\n getInstruction(format: ParameterFormat = \"json\"): 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 if (format === \"json\" || format === \"auto\") {\n parts.push(\"\\n\\nInput Schema (JSON):\");\n parts.push(JSON.stringify(jsonSchema, null, 2));\n } else if (format === \"toml\") {\n // TOML uses JSON-like schema representation since TOML doesn't have a native schema format\n parts.push(\"\\n\\nInput Schema (TOML):\");\n parts.push(JSON.stringify(jsonSchema, null, 2));\n } else {\n const yamlSchema = yaml.dump(jsonSchema).trimEnd();\n parts.push(\"\\n\\nInput Schema (YAML):\");\n parts.push(yamlSchema);\n }\n }\n\n // Render examples if present\n if (this.examples && this.examples.length > 0) {\n parts.push(\"\\n\\nExamples:\");\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 the appropriate format\n parts.push(\"Input:\");\n if (format === \"json\" || format === \"auto\") {\n parts.push(JSON.stringify(example.params, null, 2));\n } else if (format === \"toml\") {\n parts.push(formatParamsAsToml(example.params as Record<string, unknown>));\n } else {\n // Use custom formatter that applies pipe multiline syntax for strings\n parts.push(formatParamsAsYaml(example.params as Record<string, unknown>));\n }\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 { ParameterFormat } from \"../gadgets/parser.js\";\nimport type { IConversationManager } from \"./interfaces.js\";\n\n/**\n * Options for ConversationManager constructor.\n */\nexport interface ConversationManagerOptions {\n parameterFormat?: ParameterFormat;\n /** Custom gadget start marker prefix */\n startPrefix?: string;\n /** Custom gadget end marker prefix */\n endPrefix?: 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 private readonly parameterFormat: ParameterFormat;\n\n constructor(\n baseMessages: LLMMessage[],\n initialMessages: LLMMessage[],\n options: ConversationManagerOptions = {},\n ) {\n this.baseMessages = baseMessages;\n this.initialMessages = initialMessages;\n this.parameterFormat = options.parameterFormat ?? \"json\";\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);\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, this.parameterFormat);\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 parametersYaml: 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 parametersYaml: event.call.parametersYaml,\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","/**\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 type { ILogObj, Logger } from \"tslog\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { BreakLoopException, HumanInputException, TimeoutException } from \"./exceptions.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\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 ) {\n this.logger = logger ?? createLogger({ name: \"llmist:executor\" });\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 return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n error: `Gadget '${call.gadgetName}' not found in registry`,\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.parametersYaml,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: {},\n error: call.parseError ?? \"Failed to parse parameters\",\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n if (gadget.parameterSchema) {\n const validationResult = gadget.parameterSchema.safeParse(rawParameters);\n if (!validationResult.success) {\n const formattedIssues = validationResult.error.issues\n .map((issue) => {\n const path = issue.path.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\"; \");\n\n const validationError = `Invalid parameters: ${formattedIssues}`;\n this.logger.error(\"Gadget parameter validation failed\", {\n gadgetName: call.gadgetName,\n error: validationError,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: rawParameters,\n error: validationError,\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n validatedParameters = validationResult.data as Record<string, unknown>;\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","import * as yaml from \"js-yaml\";\nimport { load as parseToml } from \"js-toml\";\nimport { GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { StreamEvent } from \"./types.js\";\n\nexport type ParameterFormat = \"json\" | \"yaml\" | \"toml\" | \"auto\";\n\n/**\n * Preprocess YAML to handle common LLM output issues.\n *\n * Handles three patterns:\n * 1. Single-line values with colons: `key: value with: colon` → `key: \"value with: colon\"`\n * 2. Multi-line continuations where LLM writes:\n * ```\n * key: value ending with:\n * - list item 1\n * - list item 2\n * ```\n * Converts to proper YAML multiline:\n * ```\n * key: |\n * value ending with:\n * - list item 1\n * - list item 2\n * ```\n * 3. Pipe blocks with inconsistent indentation:\n * ```\n * key: |\n * first line (4 spaces)\n * second line (2 spaces - wrong!)\n * ```\n * Normalizes to consistent indentation based on minimum indent.\n *\n * @internal Exported for testing only\n */\nexport function preprocessYaml(yamlStr: string): string {\n const lines = yamlStr.split(\"\\n\");\n const result: string[] = [];\n let i = 0;\n\n while (i < lines.length) {\n const line = lines[i];\n\n // Check for heredoc syntax: key: <<<DELIMITER\n const heredocMatch = line.match(/^(\\s*)([\\w-]+):\\s*<<<([A-Za-z_][A-Za-z0-9_]*)\\s*$/);\n if (heredocMatch) {\n const [, indent, key, delimiter] = heredocMatch;\n const bodyLines: string[] = [];\n i++; // Move past heredoc start line\n\n // Collect body until closing delimiter (lenient - allows trailing whitespace)\n const closingRegex = new RegExp(`^${delimiter}\\\\s*$`);\n while (i < lines.length && !closingRegex.test(lines[i])) {\n bodyLines.push(lines[i]);\n i++;\n }\n if (i < lines.length) {\n i++; // Move past closing delimiter\n }\n\n // Convert to YAML pipe block with proper indentation\n result.push(`${indent}${key}: |`);\n for (const bodyLine of bodyLines) {\n result.push(`${indent} ${bodyLine}`);\n }\n continue;\n }\n\n // Match lines like \"key: value\" where value isn't quoted or using pipe\n // Support keys with hyphens/underscores (e.g., my-key, my_key)\n const match = line.match(/^(\\s*)([\\w-]+):\\s+(.+)$/);\n\n if (match) {\n const [, indent, key, value] = match;\n\n // Handle pipe/block indicators - need to check for inconsistent indentation\n if (value === \"|\" || value === \">\" || value === \"|-\" || value === \">-\") {\n result.push(line);\n i++;\n\n // Collect all block content lines\n const keyIndentLen = indent.length;\n const blockLines: { content: string; originalIndent: number }[] = [];\n let minContentIndent = Infinity;\n\n while (i < lines.length) {\n const blockLine = lines[i];\n const blockIndentMatch = blockLine.match(/^(\\s*)/);\n const blockIndentLen = blockIndentMatch ? blockIndentMatch[1].length : 0;\n\n // Empty lines are part of the block\n if (blockLine.trim() === \"\") {\n blockLines.push({ content: \"\", originalIndent: 0 });\n i++;\n continue;\n }\n\n // Lines must be more indented than the key to be part of block\n if (blockIndentLen > keyIndentLen) {\n const content = blockLine.substring(blockIndentLen);\n blockLines.push({ content, originalIndent: blockIndentLen });\n if (content.trim().length > 0) {\n minContentIndent = Math.min(minContentIndent, blockIndentLen);\n }\n i++;\n } else {\n // End of block\n break;\n }\n }\n\n // Normalize indentation: use minimum indent found as the base\n const targetIndent = keyIndentLen + 2; // Standard 2-space indent from key\n for (const blockLine of blockLines) {\n if (blockLine.content === \"\") {\n result.push(\"\");\n } else {\n // All content gets the same base indentation\n result.push(\" \".repeat(targetIndent) + blockLine.content);\n }\n }\n continue;\n }\n\n // Skip if already quoted or is a boolean/number\n if (\n value.startsWith('\"') ||\n value.startsWith(\"'\") ||\n value === \"true\" ||\n value === \"false\" ||\n /^-?\\d+(\\.\\d+)?$/.test(value)\n ) {\n result.push(line);\n i++;\n continue;\n }\n\n // Check if this is a multi-line continuation pattern:\n // A value followed by more-indented lines starting with dash (list items)\n // or text that looks like continuation\n const keyIndentLen = indent.length;\n const continuationLines: string[] = [];\n let j = i + 1;\n\n // Look ahead to see if there are continuation lines\n while (j < lines.length) {\n const nextLine = lines[j];\n // Empty lines can be part of continuation\n if (nextLine.trim() === \"\") {\n continuationLines.push(nextLine);\n j++;\n continue;\n }\n\n // Check indentation - must be more indented than the key\n const nextIndentMatch = nextLine.match(/^(\\s*)/);\n const nextIndentLen = nextIndentMatch ? nextIndentMatch[1].length : 0;\n\n // If more indented and starts with dash or looks like continuation text\n if (nextIndentLen > keyIndentLen) {\n continuationLines.push(nextLine);\n j++;\n } else {\n // Not a continuation line\n break;\n }\n }\n\n // If we found continuation lines, convert to pipe multiline\n if (continuationLines.length > 0 && continuationLines.some((l) => l.trim().length > 0)) {\n result.push(`${indent}${key}: |`);\n // Add the first line value as part of multiline content\n result.push(`${indent} ${value}`);\n // Add continuation lines, adjusting indentation\n for (const contLine of continuationLines) {\n if (contLine.trim() === \"\") {\n result.push(\"\");\n } else {\n // Normalize indentation: ensure all lines have at least 2-space indent from key\n const contIndentMatch = contLine.match(/^(\\s*)/);\n const contIndent = contIndentMatch ? contIndentMatch[1] : \"\";\n const contContent = contLine.substring(contIndent.length);\n result.push(`${indent} ${contContent}`);\n }\n }\n i = j;\n continue;\n }\n\n // Single-line value: quote if it contains problematic colon patterns\n if (value.includes(\": \") || value.endsWith(\":\")) {\n const escaped = value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n result.push(`${indent}${key}: \"${escaped}\"`);\n i++;\n continue;\n }\n }\n\n result.push(line);\n i++;\n }\n\n return result.join(\"\\n\");\n}\n\n/**\n * Remove unnecessary escape sequences from heredoc content.\n * LLMs often escape characters like backticks and dollar signs even when told not to.\n * This function un-escapes common patterns to make the content valid for TOML multiline strings.\n *\n * @internal Exported for testing only\n */\nexport function unescapeHeredocContent(content: string): string {\n return content\n .replace(/\\\\`/g, \"`\") // \\` -> `\n .replace(/\\\\\\$/g, \"$\") // \\$ -> $\n .replace(/\\\\{/g, \"{\") // \\{ -> {\n .replace(/\\\\}/g, \"}\"); // \\} -> }\n}\n\n/**\n * Preprocess TOML to convert heredoc syntax to standard multiline strings.\n *\n * Supports basic heredoc: `key = <<<DELIMITER...DELIMITER`\n * - Delimiter: ASCII letters, digits, or _, starting with letter or _\n * - Closing delimiter: alone on line (trailing whitespace allowed for LLM friendliness)\n * - Escape sequences are preserved and processed by js-toml as standard basic strings\n *\n * Example:\n * ```toml\n * message = <<<EOF\n * Hello \"world\"\n * Line 2\n * EOF\n * ```\n * Transforms to:\n * ```toml\n * message = \"\"\"\n * Hello \"world\"\n * Line 2\n * \"\"\"\n * ```\n *\n * @internal Exported for testing only\n */\nexport function preprocessTomlHeredoc(tomlStr: string): string {\n const lines = tomlStr.split(\"\\n\");\n const result: string[] = [];\n let i = 0;\n\n // Regex to match heredoc start: key = <<<DELIMITER or key = <<<DELIMITER (with optional trailing content)\n // Also supports keys with hyphens/underscores\n const heredocStartRegex = /^(\\s*)([\\w-]+)\\s*=\\s*<<<([A-Za-z_][A-Za-z0-9_]*)\\s*$/;\n\n while (i < lines.length) {\n const line = lines[i];\n const match = line.match(heredocStartRegex);\n\n if (match) {\n const [, indent, key, delimiter] = match;\n\n // Start collecting heredoc body\n const bodyLines: string[] = [];\n i++; // Move past the heredoc start line\n\n // Create lenient closing delimiter regex (allows trailing whitespace)\n const closingRegex = new RegExp(`^${delimiter}\\\\s*$`);\n\n let foundClosing = false;\n while (i < lines.length) {\n const bodyLine = lines[i];\n\n // Check if this is the closing delimiter\n if (closingRegex.test(bodyLine)) {\n foundClosing = true;\n i++; // Move past the closing delimiter\n break;\n }\n\n bodyLines.push(bodyLine);\n i++;\n }\n\n // Convert to TOML literal multiline string (''')\n // Using ''' instead of \"\"\" because literal strings DON'T process escape sequences.\n // This is critical because code often contains regex like \\s, \\d, \\n which would\n // be interpreted as (invalid) TOML escape sequences in basic strings.\n if (bodyLines.length === 0) {\n // Empty heredoc\n result.push(`${indent}${key} = ''''''`);\n } else {\n // Non-empty heredoc - use triple single quotes (literal string)\n // IMPORTANT: Put closing ''' on the same line as last content to avoid trailing newline\n // Also un-escape common LLM escaping mistakes (like \\` and \\$)\n result.push(`${indent}${key} = '''`);\n for (let j = 0; j < bodyLines.length - 1; j++) {\n result.push(unescapeHeredocContent(bodyLines[j]));\n }\n // Last line includes the closing quotes\n result.push(`${unescapeHeredocContent(bodyLines[bodyLines.length - 1])}'''`);\n }\n\n if (!foundClosing) {\n // If we didn't find a closing delimiter, the TOML will be malformed\n // but let js-toml handle the error\n }\n\n continue;\n }\n\n // Not a heredoc line, pass through unchanged\n result.push(line);\n i++;\n }\n\n return result.join(\"\\n\");\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 /**\n * Format for parsing gadget parameters.\n * - 'json': Parse as JSON (more robust, recommended for complex nested data)\n * - 'yaml': Parse as YAML (backward compatible)\n * - 'auto': Try JSON first, fall back to YAML\n * @default 'json'\n */\n parameterFormat?: ParameterFormat;\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 parameterFormat: ParameterFormat;\n\n constructor(options: StreamParserOptions = {}) {\n this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;\n this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;\n this.parameterFormat = options.parameterFormat ?? \"json\";\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 * Truncate verbose parse errors to avoid context overflow.\n * Keeps first meaningful line and limits total length.\n */\n private truncateParseError(error: unknown, format: string): string {\n const message = error instanceof Error ? error.message : String(error);\n // Take first line only (most TOML errors have useful info there)\n const firstLine = message.split(\"\\n\")[0];\n // Truncate to max 200 chars\n const maxLen = 200;\n if (firstLine.length <= maxLen) {\n return firstLine;\n }\n return `${firstLine.slice(0, maxLen)}... (${message.length} chars total)`;\n }\n\n /**\n * Parse parameter string according to configured 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 if (this.parameterFormat === \"json\") {\n try {\n return { parameters: JSON.parse(cleaned) as Record<string, unknown> };\n } catch (error) {\n return { parseError: this.truncateParseError(error, \"JSON\") };\n }\n }\n\n if (this.parameterFormat === \"yaml\") {\n try {\n return { parameters: yaml.load(preprocessYaml(cleaned)) as Record<string, unknown> };\n } catch (error) {\n return { parseError: this.truncateParseError(error, \"YAML\") };\n }\n }\n\n if (this.parameterFormat === \"toml\") {\n try {\n return { parameters: parseToml(preprocessTomlHeredoc(cleaned)) as Record<string, unknown> };\n } catch (error) {\n return { parseError: this.truncateParseError(error, \"TOML\") };\n }\n }\n\n // Auto-detect: try JSON first, then TOML, then YAML\n try {\n return { parameters: JSON.parse(cleaned) as Record<string, unknown> };\n } catch {\n try {\n return { parameters: parseToml(preprocessTomlHeredoc(cleaned)) as Record<string, unknown> };\n } catch {\n try {\n return { parameters: yaml.load(preprocessYaml(cleaned)) as Record<string, unknown> };\n } catch (error) {\n return { parseError: this.truncateParseError(error, \"auto\") };\n }\n }\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 parametersYaml: parametersRaw, // Keep property name for backward compatibility\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 parametersYaml: 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","/**\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 { type ParameterFormat, 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 /** Parameter format for parsing */\n parameterFormat: ParameterFormat;\n\n /** Custom gadget start prefix */\n gadgetStartPrefix?: string;\n\n /** Custom gadget end prefix */\n gadgetEndPrefix?: 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 parameterFormat: options.parameterFormat,\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n });\n\n this.executor = new GadgetExecutor(\n options.registry,\n options.onHumanInputRequired,\n this.logger.getSubLogger({ name: \"executor\" }),\n options.defaultGadgetTimeoutMs,\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.parametersYaml,\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 { ParameterFormat } from \"../gadgets/parser.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 /** Parameter format */\n parameterFormat?: ParameterFormat;\n\n /** Custom gadget start prefix */\n gadgetStartPrefix?: string;\n\n /** Custom gadget end prefix */\n gadgetEndPrefix?: 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 parameterFormat: ParameterFormat;\n private readonly gadgetStartPrefix?: string;\n private readonly gadgetEndPrefix?: 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.parameterFormat = options.parameterFormat ?? \"json\";\n this.gadgetStartPrefix = options.gadgetStartPrefix;\n this.gadgetEndPrefix = options.gadgetEndPrefix;\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(), this.parameterFormat, {\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\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 parameterFormat: this.parameterFormat,\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\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 parameterFormat: this.parameterFormat,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\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_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 { ParameterFormat } from \"../gadgets/parser.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 parameterFormat?: ParameterFormat;\n private gadgetStartPrefix?: string;\n private gadgetEndPrefix?: 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 the parameter format for gadget calls.\n *\n * @param format - Parameter format (\"json\" or \"xml\")\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withParameterFormat(\"xml\")\n * ```\n */\n withParameterFormat(format: ParameterFormat): this {\n this.parameterFormat = format;\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 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 const format = this.parameterFormat ?? \"yaml\";\n\n const paramStr = this.formatSyntheticParameters(parameters, format);\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 for synthetic gadget calls.\n * Uses heredoc for multiline string values.\n */\n private formatSyntheticParameters(\n parameters: Record<string, unknown>,\n format: ParameterFormat,\n ): string {\n if (format === \"json\" || format === \"auto\") {\n return JSON.stringify(parameters);\n }\n\n // YAML or TOML - use heredoc for multiline strings\n return Object.entries(parameters)\n .map(([key, value]) => {\n if (typeof value === \"string\" && value.includes(\"\\n\")) {\n // Use heredoc syntax for multiline\n const separator = format === \"yaml\" ? \":\" : \" =\";\n return `${key}${separator} <<<EOF\\n${value}\\nEOF`;\n }\n // Simple values\n if (format === \"yaml\") {\n return typeof value === \"string\" ? `${key}: ${value}` : `${key}: ${JSON.stringify(value)}`;\n }\n // TOML\n return `${key} = ${JSON.stringify(value)}`;\n })\n .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 parameterFormat: this.parameterFormat,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\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 parameterFormat: this.parameterFormat,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\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","// Re-export Zod's z for schema definitions\n// Using llmist's z ensures .describe() metadata is preserved in JSON schemas\nexport { z } from \"zod\";\n// Syntactic sugar: Agent builder and event handlers\nexport type { HistoryMessage } from \"./agent/builder.js\";\nexport { AgentBuilder } from \"./agent/builder.js\";\nexport type { EventHandlers } from \"./agent/event-handlers.js\";\nexport { collectEvents, collectText, runWithHandlers } from \"./agent/event-handlers.js\";\n// Syntactic sugar: Hook presets\nexport type { LoggingOptions } from \"./agent/hook-presets.js\";\nexport { HookPresets } from \"./agent/hook-presets.js\";\n// Agent infrastructure\n// New clean hooks system\nexport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n AgentOptions,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n // Interceptor contexts\n ChunkInterceptorContext,\n Controllers,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n IConversationManager,\n Interceptors,\n // Controller contexts and actions\n LLMCallControllerContext,\n LLMErrorControllerContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetStartContext,\n // Observer contexts\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n Observers,\n StreamProcessingResult,\n StreamProcessorOptions,\n // Gadget output limiting\n StoredOutput,\n} from \"./agent/index.js\";\nexport { ConversationManager, GadgetOutputStore, StreamProcessor } from \"./agent/index.js\";\nexport type { LLMistOptions } from \"./core/client.js\";\nexport { LLMist } from \"./core/client.js\";\nexport type { LLMMessage, LLMRole } from \"./core/messages.js\";\nexport { LLMMessageBuilder } from \"./core/messages.js\";\n// Model catalog\nexport type {\n CostEstimate,\n ModelFeatures,\n ModelLimits,\n ModelPricing,\n ModelSpec,\n} from \"./core/model-catalog.js\";\nexport { ModelRegistry } from \"./core/model-registry.js\";\n\n// Syntactic sugar: Model shortcuts and quick methods\nexport {\n getModelId,\n getProvider,\n hasProviderPrefix,\n MODEL_ALIASES,\n resolveModel,\n} from \"./core/model-shortcuts.js\";\nexport type {\n LLMGenerationOptions,\n LLMStream,\n LLMStreamChunk,\n ModelDescriptor,\n ProviderIdentifier,\n TokenUsage,\n} from \"./core/options.js\";\nexport { ModelIdentifierParser } from \"./core/options.js\";\nexport type { PromptConfig, PromptContext, PromptTemplate } from \"./core/prompt-config.js\";\nexport {\n DEFAULT_PROMPTS,\n resolvePromptTemplate,\n resolveRulesTemplate,\n} from \"./core/prompt-config.js\";\nexport type { QuickOptions } from \"./core/quick-methods.js\";\nexport { complete, stream } from \"./core/quick-methods.js\";\nexport type { CreateGadgetConfig } from \"./gadgets/create-gadget.js\";\nexport { createGadget } from \"./gadgets/create-gadget.js\";\n// Gadget output viewer (for custom output store integration)\nexport { createGadgetOutputViewer } from \"./gadgets/output-viewer.js\";\n// Gadget infrastructure\nexport { BreakLoopException, HumanInputException } from \"./gadgets/exceptions.js\";\nexport { GadgetExecutor } from \"./gadgets/executor.js\";\nexport { BaseGadget } from \"./gadgets/gadget.js\";\nexport { StreamParser } from \"./gadgets/parser.js\";\nexport type { GadgetClass, GadgetOrClass } from \"./gadgets/registry.js\";\nexport { GadgetRegistry } from \"./gadgets/registry.js\";\n\n// Syntactic sugar: Typed gadgets and helpers\nexport type { GadgetConfig } from \"./gadgets/typed-gadget.js\";\nexport { Gadget } from \"./gadgets/typed-gadget.js\";\nexport type {\n GadgetExample,\n GadgetExecutionResult,\n ParsedGadgetCall,\n StreamEvent,\n TextOnlyAction,\n TextOnlyContext,\n TextOnlyCustomHandler,\n TextOnlyGadgetConfig,\n TextOnlyHandler,\n TextOnlyStrategy,\n} from \"./gadgets/types.js\";\nexport type { ValidationIssue, ValidationResult } from \"./gadgets/validation.js\";\nexport { validateAndApplyDefaults, validateGadgetParams } from \"./gadgets/validation.js\";\nexport type { LoggerOptions } from \"./logging/logger.js\";\nexport { createLogger, defaultLogger } from \"./logging/logger.js\";\nexport {\n AnthropicMessagesProvider,\n createAnthropicProviderFromEnv,\n} from \"./providers/anthropic.js\";\nexport { discoverProviderAdapters } from \"./providers/discovery.js\";\nexport { createGeminiProviderFromEnv, GeminiGenerativeProvider } from \"./providers/gemini.js\";\nexport { createOpenAIProviderFromEnv, OpenAIChatProvider } from \"./providers/openai.js\";\nexport type { ProviderAdapter } from \"./providers/provider.js\";\n\n// Testing/Mock infrastructure\nexport type {\n MockMatcher,\n MockMatcherContext,\n MockOptions,\n MockRegistration,\n MockResponse,\n MockStats,\n} from \"./testing/index.js\";\nexport {\n createMockAdapter,\n createMockClient,\n createMockStream,\n createTextMockStream,\n getMockManager,\n MockBuilder,\n MockManager,\n MockProviderAdapter,\n mockLLM,\n} from \"./testing/index.js\";\n","/**\n * Ready-to-use hook configurations for common monitoring, logging, and debugging tasks.\n *\n * HookPresets provide instant observability without writing custom hooks. They're the\n * fastest way to add monitoring to your agents during development and production.\n *\n * ## Available Presets\n *\n * - **logging(options?)** - Log LLM calls and gadget execution\n * - **timing()** - Measure execution time for operations\n * - **tokenTracking()** - Track cumulative token usage and costs\n * - **progressTracking(options?)** - Track progress with iterations, tokens, cost, and timing (SHOWCASE)\n * - **errorLogging()** - Log detailed error information\n * - **silent()** - No output (useful for testing)\n * - **monitoring(options?)** - All-in-one preset combining logging, timing, tokens, and errors\n * - **merge(...hookSets)** - Combine multiple hook configurations\n *\n * ## Quick Start\n *\n * @example\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * // Basic logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging())\n * .ask(\"Your prompt\");\n *\n * // Full monitoring suite (recommended for development)\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring({ verbose: true }))\n * .ask(\"Your prompt\");\n *\n * // Combine multiple presets\n * await LLMist.createAgent()\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * .ask(\"Your prompt\");\n *\n * // Environment-based configuration\n * const hooks = process.env.NODE_ENV === 'production'\n * ? HookPresets.merge(HookPresets.errorLogging(), HookPresets.tokenTracking())\n * : HookPresets.monitoring({ verbose: true });\n *\n * await LLMist.createAgent()\n * .withHooks(hooks)\n * .ask(\"Your prompt\");\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md | Full documentation}\n */\n\nimport type { AgentHooks } from \"./hooks.js\";\nimport type { ModelRegistry } from \"../core/model-registry.js\";\n\n/**\n * Options for logging preset.\n */\nexport interface LoggingOptions {\n /** Include verbose details like parameters and results */\n verbose?: boolean;\n}\n\n/**\n * Progress statistics reported by progressTracking preset.\n *\n * Contains cumulative metrics across all LLM calls in the agent session,\n * useful for building progress UI, cost monitoring, and performance tracking.\n */\nexport interface ProgressStats {\n /** Current iteration number (increments on each LLM call start) */\n currentIteration: number;\n\n /** Total number of completed LLM calls */\n totalCalls: number;\n\n /** Cumulative input tokens across all calls */\n totalInputTokens: number;\n\n /** Cumulative output tokens across all calls */\n totalOutputTokens: number;\n\n /** Total tokens (input + output) */\n totalTokens: number;\n\n /** Cumulative cost in USD (requires modelRegistry) */\n totalCost: number;\n\n /** Elapsed time in seconds since first call */\n elapsedSeconds: number;\n}\n\n/**\n * Options for progressTracking preset.\n *\n * Controls how progress data is tracked and reported during agent execution.\n */\nexport interface ProgressTrackingOptions {\n /**\n * Model registry for cost calculation.\n *\n * If provided, enables automatic cost estimation based on token usage\n * and model pricing data. Without it, totalCost will always be 0.\n *\n * @example\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * const client = LLMist.create();\n * const hooks = HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry // Enable cost tracking\n * });\n * ```\n */\n modelRegistry?: ModelRegistry;\n\n /**\n * Callback invoked after each LLM call completion with cumulative stats.\n *\n * Use this to update progress UI, log metrics, or track budgets in real-time.\n *\n * @example\n * ```typescript\n * HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * console.log(`Iteration #${stats.currentIteration}`);\n * console.log(`Cost so far: $${stats.totalCost.toFixed(4)}`);\n * console.log(`Elapsed: ${stats.elapsedSeconds}s`);\n * }\n * })\n * ```\n */\n onProgress?: (stats: ProgressStats) => void;\n\n /**\n * Whether to log progress to console after each LLM call.\n *\n * When enabled, prints a summary line with tokens, cost, and elapsed time.\n * Useful for quick debugging without implementing a custom callback.\n *\n * Default: false\n *\n * @example\n * ```typescript\n * // Quick console-based progress tracking\n * HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * logProgress: true // Log to console\n * })\n * // Output: 📊 Progress: Iteration #2 | 1,234 tokens | $0.0056 | 12.3s\n * ```\n */\n logProgress?: boolean;\n}\n\n/**\n * Common hook presets.\n */\nexport class HookPresets {\n /**\n * Logs LLM calls and gadget execution to console with optional verbosity.\n *\n * **Output (basic mode):**\n * - LLM call start/complete events with iteration numbers\n * - Gadget execution start/complete with gadget names\n * - Token counts when available\n *\n * **Output (verbose mode):**\n * - All basic mode output\n * - Full gadget parameters (formatted JSON)\n * - Full gadget results\n * - Complete LLM response text\n *\n * **Use cases:**\n * - Basic development debugging and execution flow visibility\n * - Understanding agent decision-making and tool usage\n * - Troubleshooting gadget invocations\n *\n * **Performance:** Minimal overhead. Console writes are synchronous but fast.\n *\n * @param options - Logging options\n * @param options.verbose - Include full parameters and results. Default: false\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging())\n * .ask(\"Calculate 15 * 23\");\n * // Output: [LLM] Starting call (iteration 0)\n * // [GADGET] Executing Calculator\n * // [GADGET] Completed Calculator\n * // [LLM] Completed (tokens: 245)\n * ```\n *\n * @example\n * ```typescript\n * // Verbose logging with full details\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging({ verbose: true }))\n * .ask(\"Calculate 15 * 23\");\n * // Output includes: parameters, results, and full responses\n * ```\n *\n * @example\n * ```typescript\n * // Environment-based verbosity\n * const isDev = process.env.NODE_ENV === 'development';\n * .withHooks(HookPresets.logging({ verbose: isDev }))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsloggingoptions | Full documentation}\n */\n static logging(options: LoggingOptions = {}): AgentHooks {\n return {\n observers: {\n onLLMCallStart: async (ctx) => {\n console.log(`[LLM] Starting call (iteration ${ctx.iteration})`);\n },\n onLLMCallComplete: async (ctx) => {\n const tokens = ctx.usage?.totalTokens ?? \"unknown\";\n console.log(`[LLM] Completed (tokens: ${tokens})`);\n if (options.verbose && ctx.finalMessage) {\n console.log(`[LLM] Response: ${ctx.finalMessage}`);\n }\n },\n onGadgetExecutionStart: async (ctx) => {\n console.log(`[GADGET] Executing ${ctx.gadgetName}`);\n if (options.verbose) {\n console.log(`[GADGET] Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n }\n },\n onGadgetExecutionComplete: async (ctx) => {\n console.log(`[GADGET] Completed ${ctx.gadgetName}`);\n if (options.verbose) {\n const display = ctx.error ?? ctx.finalResult ?? \"(no result)\";\n console.log(`[GADGET] Result: ${display}`);\n }\n },\n },\n };\n }\n\n /**\n * Measures and logs execution time for LLM calls and gadgets.\n *\n * **Output:**\n * - Duration in milliseconds with ⏱️ emoji for each operation\n * - Separate timing for each LLM iteration\n * - Separate timing for each gadget execution\n *\n * **Use cases:**\n * - Performance profiling and optimization\n * - Identifying slow operations (LLM calls vs gadget execution)\n * - Monitoring response times in production\n * - Capacity planning and SLA tracking\n *\n * **Performance:** Negligible overhead. Uses Date.now() for timing measurements.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic timing\n * await LLMist.createAgent()\n * .withHooks(HookPresets.timing())\n * .withGadgets(Weather, Database)\n * .ask(\"What's the weather in NYC?\");\n * // Output: ⏱️ LLM call took 1234ms\n * // ⏱️ Gadget Weather took 567ms\n * // ⏱️ LLM call took 890ms\n * ```\n *\n * @example\n * ```typescript\n * // Combined with logging for full context\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing()\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Correlate performance with cost\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstiming | Full documentation}\n */\n static timing(): AgentHooks {\n const timings = new Map<string, number>();\n\n return {\n observers: {\n onLLMCallStart: async (ctx) => {\n timings.set(`llm-${ctx.iteration}`, Date.now());\n },\n onLLMCallComplete: async (ctx) => {\n const start = timings.get(`llm-${ctx.iteration}`);\n if (start) {\n const duration = Date.now() - start;\n console.log(`⏱️ LLM call took ${duration}ms`);\n timings.delete(`llm-${ctx.iteration}`);\n }\n },\n onGadgetExecutionStart: async (ctx) => {\n const key = `gadget-${ctx.gadgetName}-${Date.now()}`;\n timings.set(key, Date.now());\n // Store key for lookup in complete handler\n (ctx as any)._timingKey = key;\n },\n onGadgetExecutionComplete: async (ctx) => {\n const key = (ctx as any)._timingKey;\n if (key) {\n const start = timings.get(key);\n if (start) {\n const duration = Date.now() - start;\n console.log(`⏱️ Gadget ${ctx.gadgetName} took ${duration}ms`);\n timings.delete(key);\n }\n }\n },\n },\n };\n }\n\n /**\n * Tracks cumulative token usage across all LLM calls.\n *\n * **Output:**\n * - Per-call token count with 📊 emoji\n * - Cumulative total across all calls\n * - Call count for average calculations\n *\n * **Use cases:**\n * - Cost monitoring and budget tracking\n * - Optimizing prompts to reduce token usage\n * - Comparing token efficiency across different approaches\n * - Real-time cost estimation\n *\n * **Performance:** Minimal overhead. Simple counter increments.\n *\n * **Note:** Token counts depend on the provider's response. Some providers\n * may not include usage data, in which case counts won't be logged.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic token tracking\n * await LLMist.createAgent()\n * .withHooks(HookPresets.tokenTracking())\n * .ask(\"Summarize this document...\");\n * // Output: 📊 Tokens this call: 1,234\n * // 📊 Total tokens: 1,234 (across 1 calls)\n * // 📊 Tokens this call: 567\n * // 📊 Total tokens: 1,801 (across 2 calls)\n * ```\n *\n * @example\n * ```typescript\n * // Cost calculation with custom hook\n * let totalTokens = 0;\n * .withHooks(HookPresets.merge(\n * HookPresets.tokenTracking(),\n * {\n * observers: {\n * onLLMCallComplete: async (ctx) => {\n * totalTokens += ctx.usage?.totalTokens ?? 0;\n * const cost = (totalTokens / 1_000_000) * 3.0; // $3 per 1M tokens\n * console.log(`💰 Estimated cost: $${cost.toFixed(4)}`);\n * },\n * },\n * }\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstokentracking | Full documentation}\n */\n static tokenTracking(): AgentHooks {\n let totalTokens = 0;\n let totalCalls = 0;\n\n return {\n observers: {\n onLLMCallComplete: async (ctx) => {\n totalCalls++;\n if (ctx.usage?.totalTokens) {\n totalTokens += ctx.usage.totalTokens;\n console.log(`📊 Tokens this call: ${ctx.usage.totalTokens}`);\n console.log(`📊 Total tokens: ${totalTokens} (across ${totalCalls} calls)`);\n }\n },\n },\n };\n }\n\n /**\n * Tracks comprehensive progress metrics including iterations, tokens, cost, and timing.\n *\n * **This preset showcases llmist's core capabilities by demonstrating:**\n * - Observer pattern for non-intrusive monitoring\n * - Integration with ModelRegistry for cost estimation\n * - Callback-based architecture for flexible UI updates\n * - Provider-agnostic token and cost tracking\n *\n * Unlike `tokenTracking()` which only logs to console, this preset provides\n * structured data through callbacks, making it perfect for building custom UIs,\n * dashboards, or progress indicators (like the llmist CLI).\n *\n * **Output (when logProgress: true):**\n * - Iteration number and call count\n * - Cumulative token usage (input + output)\n * - Cumulative cost in USD (requires modelRegistry)\n * - Elapsed time in seconds\n *\n * **Use cases:**\n * - Building CLI progress indicators with live updates\n * - Creating web dashboards with real-time metrics\n * - Budget monitoring and cost alerts\n * - Performance tracking and optimization\n * - Custom logging to external systems (Datadog, CloudWatch, etc.)\n *\n * **Performance:** Minimal overhead. Uses Date.now() for timing and optional\n * ModelRegistry.estimateCost() which is O(1) lookup. Callback invocation is\n * synchronous and fast.\n *\n * @param options - Progress tracking options\n * @param options.modelRegistry - ModelRegistry for cost estimation (optional)\n * @param options.onProgress - Callback invoked after each LLM call (optional)\n * @param options.logProgress - Log progress to console (default: false)\n * @returns Hook configuration with progress tracking observers\n *\n * @example\n * ```typescript\n * // Basic usage with callback (RECOMMENDED - used by llmist CLI)\n * import { LLMist, HookPresets } from 'llmist';\n *\n * const client = LLMist.create();\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * // Update your UI with stats\n * console.log(`#${stats.currentIteration} | ${stats.totalTokens} tokens | $${stats.totalCost.toFixed(4)}`);\n * }\n * }))\n * .withGadgets(Calculator)\n * .ask(\"Calculate 15 * 23\");\n * // Output: #1 | 245 tokens | $0.0012\n * ```\n *\n * @example\n * ```typescript\n * // Console logging mode (quick debugging)\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * logProgress: true // Simple console output\n * }))\n * .ask(\"Your prompt\");\n * // Output: 📊 Progress: Iteration #1 | 245 tokens | $0.0012 | 1.2s\n * ```\n *\n * @example\n * ```typescript\n * // Budget monitoring with alerts\n * const BUDGET_USD = 0.10;\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * if (stats.totalCost > BUDGET_USD) {\n * throw new Error(`Budget exceeded: $${stats.totalCost.toFixed(4)}`);\n * }\n * }\n * }))\n * .ask(\"Long running task...\");\n * ```\n *\n * @example\n * ```typescript\n * // Web dashboard integration\n * let progressBar: HTMLElement;\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * // Update web UI in real-time\n * progressBar.textContent = `Iteration ${stats.currentIteration}`;\n * progressBar.dataset.cost = stats.totalCost.toFixed(4);\n * progressBar.dataset.tokens = stats.totalTokens.toString();\n * }\n * }))\n * .ask(\"Your prompt\");\n * ```\n *\n * @example\n * ```typescript\n * // External logging (Datadog, CloudWatch, etc.)\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: async (stats) => {\n * await metrics.gauge('llm.iteration', stats.currentIteration);\n * await metrics.gauge('llm.cost', stats.totalCost);\n * await metrics.gauge('llm.tokens', stats.totalTokens);\n * }\n * }))\n * .ask(\"Your prompt\");\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsprogresstrackingoptions | Full documentation}\n * @see {@link ProgressTrackingOptions} for detailed options\n * @see {@link ProgressStats} for the callback data structure\n */\n static progressTracking(options?: ProgressTrackingOptions): AgentHooks {\n const { modelRegistry, onProgress, logProgress = false } = options ?? {};\n\n // State tracking - follows same pattern as tokenTracking()\n let totalCalls = 0;\n let currentIteration = 0;\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCost = 0;\n const startTime = Date.now();\n\n return {\n observers: {\n // Track iteration on each LLM call start\n onLLMCallStart: async (ctx) => {\n currentIteration++;\n },\n\n // Accumulate metrics and report progress on each LLM call completion\n onLLMCallComplete: async (ctx) => {\n totalCalls++;\n\n // Track token usage from provider response\n if (ctx.usage) {\n totalInputTokens += ctx.usage.inputTokens;\n totalOutputTokens += ctx.usage.outputTokens;\n\n // Calculate cost using ModelRegistry (core llmist feature)\n // This showcases integration with llmist's pricing catalog\n if (modelRegistry) {\n try {\n // Extract model name from provider:model format\n // Example: \"openai:gpt-4o\" -> \"gpt-4o\"\n const modelName = ctx.options.model.includes(\":\")\n ? ctx.options.model.split(\":\")[1]\n : ctx.options.model;\n\n // Use core's estimateCost() for accurate pricing\n const costEstimate = modelRegistry.estimateCost(\n modelName,\n ctx.usage.inputTokens,\n ctx.usage.outputTokens,\n );\n\n if (costEstimate) {\n totalCost += costEstimate.totalCost;\n }\n } catch (error) {\n // Graceful degradation - log error but don't crash\n // This follows llmist's principle of non-intrusive monitoring\n if (logProgress) {\n console.warn(`⚠️ Cost estimation failed:`, error);\n }\n }\n }\n }\n\n // Build comprehensive progress stats\n const stats: ProgressStats = {\n currentIteration,\n totalCalls,\n totalInputTokens,\n totalOutputTokens,\n totalTokens: totalInputTokens + totalOutputTokens,\n totalCost,\n elapsedSeconds: Number(((Date.now() - startTime) / 1000).toFixed(1)),\n };\n\n // Invoke callback if provided (used by CLI and custom UIs)\n if (onProgress) {\n onProgress(stats);\n }\n\n // Optional console logging for quick debugging\n if (logProgress) {\n const formattedTokens = stats.totalTokens >= 1000\n ? `${(stats.totalTokens / 1000).toFixed(1)}k`\n : `${stats.totalTokens}`;\n\n const formattedCost = stats.totalCost > 0\n ? `$${stats.totalCost.toFixed(4)}`\n : \"$0\";\n\n console.log(\n `📊 Progress: Iteration #${stats.currentIteration} | ${formattedTokens} tokens | ${formattedCost} | ${stats.elapsedSeconds}s`,\n );\n }\n },\n },\n };\n }\n\n /**\n * Logs detailed error information for debugging and troubleshooting.\n *\n * **Output:**\n * - LLM errors with ❌ emoji, including model and recovery status\n * - Gadget errors with full context (parameters, error message)\n * - Separate logging for LLM and gadget failures\n *\n * **Use cases:**\n * - Troubleshooting production issues\n * - Understanding error patterns and frequency\n * - Debugging error recovery behavior\n * - Collecting error metrics for monitoring\n *\n * **Performance:** Minimal overhead. Only logs when errors occur.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic error logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.errorLogging())\n * .withGadgets(Database)\n * .ask(\"Fetch user data\");\n * // Output (on LLM error): ❌ LLM Error (iteration 1): Rate limit exceeded\n * // Model: gpt-5-nano\n * // Recovered: true\n * // Output (on gadget error): ❌ Gadget Error: Database\n * // Error: Connection timeout\n * // Parameters: {...}\n * ```\n *\n * @example\n * ```typescript\n * // Combine with monitoring for full context\n * .withHooks(HookPresets.merge(\n * HookPresets.monitoring(), // Includes errorLogging\n * customErrorAnalytics\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Error analytics collection\n * const errors: any[] = [];\n * .withHooks(HookPresets.merge(\n * HookPresets.errorLogging(),\n * {\n * observers: {\n * onLLMCallError: async (ctx) => {\n * errors.push({ type: 'llm', error: ctx.error, recovered: ctx.recovered });\n * },\n * },\n * }\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetserrorlogging | Full documentation}\n */\n static errorLogging(): AgentHooks {\n return {\n observers: {\n onLLMCallError: async (ctx) => {\n console.error(`❌ LLM Error (iteration ${ctx.iteration}):`, ctx.error.message);\n console.error(` Model: ${ctx.options.model}`);\n console.error(` Recovered: ${ctx.recovered}`);\n },\n onGadgetExecutionComplete: async (ctx) => {\n if (ctx.error) {\n console.error(`❌ Gadget Error: ${ctx.gadgetName}`);\n console.error(` Error: ${ctx.error}`);\n console.error(` Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n }\n },\n },\n };\n }\n\n /**\n * Returns empty hook configuration for clean output without any logging.\n *\n * **Output:**\n * - None. Returns {} (empty object).\n *\n * **Use cases:**\n * - Clean test output without console noise\n * - Production environments where logging is handled externally\n * - Baseline for custom hook development\n * - Temporary disable of all hook output\n *\n * **Performance:** Zero overhead. No-op hook configuration.\n *\n * @returns Empty hook configuration\n *\n * @example\n * ```typescript\n * // Clean test output\n * describe('Agent tests', () => {\n * it('should calculate correctly', async () => {\n * const result = await LLMist.createAgent()\n * .withHooks(HookPresets.silent()) // No console output\n * .withGadgets(Calculator)\n * .askAndCollect(\"What is 15 times 23?\");\n *\n * expect(result).toContain(\"345\");\n * });\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Conditional silence based on environment\n * const isTesting = process.env.NODE_ENV === 'test';\n * .withHooks(isTesting ? HookPresets.silent() : HookPresets.monitoring())\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetssilent | Full documentation}\n */\n static silent(): AgentHooks {\n return {};\n }\n\n /**\n * Combines multiple hook configurations into one.\n *\n * Merge allows you to compose preset and custom hooks for modular monitoring\n * configurations. Understanding merge behavior is crucial for proper composition.\n *\n * **Merge behavior:**\n * - **Observers:** Composed - all handlers run sequentially in order\n * - **Interceptors:** Last one wins - only the last interceptor applies\n * - **Controllers:** Last one wins - only the last controller applies\n *\n * **Why interceptors/controllers don't compose:**\n * - Interceptors have different signatures per method, making composition impractical\n * - Controllers return specific actions that can't be meaningfully combined\n * - Only observers support composition because they're read-only and independent\n *\n * **Use cases:**\n * - Combining multiple presets (logging + timing + tokens)\n * - Adding custom hooks to presets\n * - Building modular, reusable monitoring configurations\n * - Environment-specific hook composition\n *\n * **Performance:** Minimal overhead for merging. Runtime performance depends on merged hooks.\n *\n * @param hookSets - Variable number of hook configurations to merge\n * @returns Single merged hook configuration with composed/overridden handlers\n *\n * @example\n * ```typescript\n * // Combine multiple presets\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * // All observers from all three presets will run\n * ```\n *\n * @example\n * ```typescript\n * // Add custom observer to preset (both run)\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * {\n * observers: {\n * onLLMCallComplete: async (ctx) => {\n * await saveMetrics({ tokens: ctx.usage?.totalTokens });\n * },\n * },\n * }\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Multiple interceptors (last wins!)\n * .withHooks(HookPresets.merge(\n * {\n * interceptors: {\n * interceptTextChunk: (chunk) => chunk.toUpperCase(), // Ignored\n * },\n * },\n * {\n * interceptors: {\n * interceptTextChunk: (chunk) => chunk.toLowerCase(), // This wins\n * },\n * }\n * ))\n * // Result: text will be lowercase\n * ```\n *\n * @example\n * ```typescript\n * // Modular environment-based configuration\n * const baseHooks = HookPresets.errorLogging();\n * const devHooks = HookPresets.merge(baseHooks, HookPresets.monitoring({ verbose: true }));\n * const prodHooks = HookPresets.merge(baseHooks, HookPresets.tokenTracking());\n *\n * const hooks = process.env.NODE_ENV === 'production' ? prodHooks : devHooks;\n * .withHooks(hooks)\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmergehooksets | Full documentation}\n */\n static merge(...hookSets: AgentHooks[]): AgentHooks {\n const merged: AgentHooks = {\n observers: {},\n interceptors: {},\n controllers: {},\n };\n\n // Compose observers: run all handlers for the same event\n for (const hooks of hookSets) {\n if (hooks.observers) {\n for (const [key, handler] of Object.entries(hooks.observers)) {\n const typedKey = key as keyof typeof hooks.observers;\n if (merged.observers![typedKey]) {\n // Compose: run both existing and new handler\n const existing = merged.observers![typedKey];\n merged.observers![typedKey] = async (ctx: any) => {\n await existing(ctx);\n await handler(ctx);\n };\n } else {\n merged.observers![typedKey] = handler as any;\n }\n }\n }\n\n // Interceptors: last one wins (complex signatures make composition impractical)\n // Each interceptor has different parameters (chunk, message, parameters, etc.)\n // so we can't meaningfully compose them like we do with observers\n if (hooks.interceptors) {\n Object.assign(merged.interceptors!, hooks.interceptors);\n }\n\n // Controllers: last one wins (can't meaningfully compose boolean returns)\n if (hooks.controllers) {\n Object.assign(merged.controllers!, hooks.controllers);\n }\n }\n\n return merged;\n }\n\n /**\n * Composite preset combining logging, timing, tokenTracking, and errorLogging.\n *\n * This is the recommended preset for development and initial production deployments,\n * providing comprehensive observability with a single method call.\n *\n * **Includes:**\n * - All output from `logging()` preset (with optional verbosity)\n * - All output from `timing()` preset (execution times)\n * - All output from `tokenTracking()` preset (token usage)\n * - All output from `errorLogging()` preset (error details)\n *\n * **Output format:**\n * - Event logging: [LLM]/[GADGET] messages\n * - Timing: ⏱️ emoji with milliseconds\n * - Tokens: 📊 emoji with per-call and cumulative counts\n * - Errors: ❌ emoji with full error details\n *\n * **Use cases:**\n * - Full observability during development\n * - Comprehensive monitoring in production\n * - One-liner for complete agent visibility\n * - Troubleshooting and debugging with full context\n *\n * **Performance:** Combined overhead of all four presets, but still minimal in practice.\n *\n * @param options - Monitoring options\n * @param options.verbose - Passed to logging() preset for detailed output. Default: false\n * @returns Merged hook configuration combining all monitoring presets\n *\n * @example\n * ```typescript\n * // Basic monitoring (recommended for development)\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring())\n * .withGadgets(Calculator, Weather)\n * .ask(\"What is 15 times 23, and what's the weather in NYC?\");\n * // Output: All events, timing, tokens, and errors in one place\n * ```\n *\n * @example\n * ```typescript\n * // Verbose monitoring with full details\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring({ verbose: true }))\n * .ask(\"Your prompt\");\n * // Output includes: parameters, results, and complete responses\n * ```\n *\n * @example\n * ```typescript\n * // Environment-based monitoring\n * const isDev = process.env.NODE_ENV === 'development';\n * .withHooks(HookPresets.monitoring({ verbose: isDev }))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmonitoringoptions | Full documentation}\n */\n static monitoring(options: LoggingOptions = {}): AgentHooks {\n return HookPresets.merge(\n HookPresets.logging(options),\n HookPresets.timing(),\n HookPresets.tokenTracking(),\n HookPresets.errorLogging(),\n );\n }\n}\n","/**\n * Agent module - Composable, single-responsibility architecture for LLM agents.\n * This module provides a cleaner alternative to the monolithic AgentLoop.\n */\n\nexport type { AgentOptions } from \"./agent.js\";\nexport { ConversationManager } from \"./conversation-manager.js\";\n// New clean hooks system\nexport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n // Interceptor contexts\n ChunkInterceptorContext,\n Controllers,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n Interceptors,\n // Controller contexts and actions\n LLMCallControllerContext,\n LLMErrorControllerContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetStartContext,\n // Observer contexts\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n Observers,\n} from \"./hooks.js\";\nexport type { IConversationManager } from \"./interfaces.js\";\n\n// StreamProcessor for advanced use cases\nexport {\n type StreamProcessingResult,\n StreamProcessor,\n type StreamProcessorOptions,\n} from \"./stream-processor.js\";\n\n// Gadget output limiting\nexport type { StoredOutput } from \"./gadget-output-store.js\";\nexport { GadgetOutputStore } from \"./gadget-output-store.js\";\n","/**\n * Type-safe gadget factory with automatic parameter inference.\n *\n * Gadget eliminates the need for manual type assertions\n * by automatically inferring parameter types from the Zod schema.\n *\n * @example\n * ```typescript\n * class Calculator extends Gadget({\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 * }) {\n * // ✨ params is automatically typed!\n * execute(params: this['params']): string {\n * const { operation, a, b } = params; // All 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 typed gadget.\n */\nexport interface GadgetConfig<TSchema extends ZodType> {\n /** Human-readable description of what the gadget does */\n description: string;\n\n /** Zod schema for parameter validation */\n schema: TSchema;\n\n /** Optional custom name (defaults to class name) */\n name?: 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 * Factory function to create a typed gadget base class.\n *\n * The returned class automatically infers parameter types from the Zod schema,\n * eliminating the need for manual type assertions in the execute method.\n *\n * @param config - Configuration with description and schema\n * @returns Base class to extend with typed execute method\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { Gadget } from 'llmist';\n *\n * class Calculator extends Gadget({\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 * }) {\n * execute(params: this['params']): string {\n * // params is automatically typed as:\n * // { operation: \"add\" | \"subtract\" | \"multiply\" | \"divide\"; a: number; b: number }\n * const { operation, a, b } = params;\n *\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 * // With async execution\n * class WeatherGadget extends Gadget({\n * description: \"Fetches weather for a city\",\n * schema: z.object({\n * city: z.string().min(1).describe(\"City name\"),\n * }),\n * timeoutMs: 10000,\n * }) {\n * async execute(params: this['params']): Promise<string> {\n * const { city } = params; // Automatically typed as { city: string }\n * const weather = await fetchWeather(city);\n * return `Weather in ${city}: ${weather}`;\n * }\n * }\n * ```\n */\nexport function Gadget<TSchema extends ZodType>(config: GadgetConfig<TSchema>) {\n abstract class GadgetBase extends BaseGadget {\n description = config.description;\n parameterSchema = config.schema;\n name = config.name;\n timeoutMs = config.timeoutMs;\n examples = config.examples;\n\n /**\n * Type helper property for accessing inferred parameter type.\n * This is used in the execute method signature: `execute(params: this['params'])`\n *\n * Note: This is just for type inference - the actual params in execute()\n * will be Record<string, unknown> which you can safely cast to this['params']\n */\n readonly params!: InferSchema<TSchema>;\n\n /**\n * Execute the gadget. Subclasses should cast params to this['params'].\n *\n * @param params - Validated parameters from the LLM\n * @returns Result as a string (or Promise<string> for async gadgets)\n *\n * @example\n * ```typescript\n * execute(params: Record<string, unknown>): string {\n * const typed = params as this['params'];\n * // Now 'typed' is fully typed!\n * return String(typed.a + typed.b);\n * }\n * ```\n */\n abstract execute(params: Record<string, unknown>): string | Promise<string>;\n }\n\n return GadgetBase as {\n new (): GadgetBase & { params: InferSchema<TSchema> };\n };\n}\n","/**\n * Validation utilities for gadget parameters.\n *\n * Provides standalone validation with Zod schema support, including\n * default application and formatted error output.\n *\n * @module gadgets/validation\n */\n\nimport type { ZodTypeAny } from \"zod\";\nimport type { BaseGadget } from \"./gadget.js\";\n\n/**\n * Individual validation issue with path and message.\n */\nexport interface ValidationIssue {\n /** Dot-separated path to the invalid field (e.g., \"user.email\") */\n path: string;\n /** Human-readable error message */\n message: string;\n}\n\n/**\n * Result of parameter validation.\n * Discriminated union based on `success` field.\n */\nexport type ValidationResult<T = Record<string, unknown>> =\n | {\n success: true;\n /** Validated and transformed data with defaults applied */\n data: T;\n }\n | {\n success: false;\n /** Formatted error message */\n error: string;\n /** Individual validation issues */\n issues: ValidationIssue[];\n };\n\n/**\n * Validate parameters against a Zod schema and apply defaults/transformations.\n *\n * This replicates the validation behavior from GadgetExecutor, making it\n * available for direct use in tests and other contexts.\n *\n * @param schema - Zod schema to validate against\n * @param params - Raw parameters to validate\n * @returns ValidationResult with either validated data or error details\n *\n * @example\n * ```typescript\n * import { validateAndApplyDefaults } from 'llmist';\n * import { z } from 'zod';\n *\n * const schema = z.object({\n * delay: z.number().default(100),\n * retries: z.number().int().min(0).default(3),\n * });\n *\n * const result = validateAndApplyDefaults(schema, { delay: 50 });\n * if (result.success) {\n * console.log(result.data); // { delay: 50, retries: 3 }\n * }\n * ```\n */\nexport function validateAndApplyDefaults<T = Record<string, unknown>>(\n schema: ZodTypeAny,\n params: Record<string, unknown>,\n): ValidationResult<T> {\n const result = schema.safeParse(params);\n\n if (result.success) {\n return {\n success: true,\n data: result.data as T,\n };\n }\n\n const issues: ValidationIssue[] = result.error.issues.map((issue) => ({\n path: issue.path.join(\".\") || \"root\",\n message: issue.message,\n }));\n\n const formattedError = `Invalid parameters: ${issues.map((i) => `${i.path}: ${i.message}`).join(\"; \")}`;\n\n return {\n success: false,\n error: formattedError,\n issues,\n };\n}\n\n/**\n * Validate gadget parameters using the gadget's schema.\n *\n * Convenience wrapper that extracts the schema from a gadget instance.\n * If the gadget has no schema, validation always succeeds with the\n * original parameters.\n *\n * @param gadget - Gadget instance with optional parameterSchema\n * @param params - Raw parameters to validate\n * @returns ValidationResult with either validated data or error details\n *\n * @example\n * ```typescript\n * import { validateGadgetParams, createGadget } from 'llmist';\n * import { z } from 'zod';\n *\n * const calculator = createGadget({\n * description: 'Add numbers',\n * schema: z.object({\n * a: z.number(),\n * b: z.number().default(0),\n * }),\n * execute: ({ a, b }) => String(a + b),\n * });\n *\n * const result = validateGadgetParams(calculator, { a: 5 });\n * if (result.success) {\n * console.log(result.data); // { a: 5, b: 0 }\n * }\n * ```\n */\nexport function validateGadgetParams(\n gadget: BaseGadget,\n params: Record<string, unknown>,\n): ValidationResult {\n if (!gadget.parameterSchema) {\n return {\n success: true,\n data: params,\n };\n }\n\n return validateAndApplyDefaults(gadget.parameterSchema, params);\n}\n","import type { ILogObj, Logger } from \"tslog\";\nimport { createLogger } from \"../logging/logger.js\";\nimport type {\n MockMatcherContext,\n MockOptions,\n MockRegistration,\n MockResponse,\n MockStats,\n} from \"./mock-types.js\";\n\n/**\n * Global singleton instance for managing LLM mocks.\n * This allows mocks to be registered once and used across the application.\n */\nexport class MockManager {\n private static instance: MockManager | null = null;\n private mocks: Map<string, MockRegistration> = new Map();\n private stats: Map<string, MockStats> = new Map();\n private options: Required<MockOptions>;\n private logger: Logger<ILogObj>;\n private nextId = 1;\n\n private constructor(options: MockOptions = {}) {\n this.options = {\n strictMode: options.strictMode ?? false,\n debug: options.debug ?? false,\n recordStats: options.recordStats ?? true,\n };\n this.logger = createLogger({ name: \"MockManager\", minLevel: this.options.debug ? 2 : 3 });\n }\n\n /**\n * Get the global MockManager instance.\n * Creates one if it doesn't exist.\n */\n static getInstance(options?: MockOptions): MockManager {\n if (!MockManager.instance) {\n MockManager.instance = new MockManager(options);\n } else if (options) {\n // Warn if options are provided after initialization\n console.warn(\n \"MockManager.getInstance() called with options, but instance already exists. \" +\n \"Options are ignored. Use setOptions() to update options or reset() to reinitialize.\",\n );\n }\n return MockManager.instance;\n }\n\n /**\n * Reset the global instance (useful for testing).\n */\n static reset(): void {\n MockManager.instance = null;\n }\n\n /**\n * Register a new mock.\n *\n * @param registration - The mock registration configuration\n * @returns The ID of the registered mock\n *\n * @example\n * const manager = MockManager.getInstance();\n * const mockId = manager.register({\n * label: 'GPT-4 mock',\n * matcher: (ctx) => ctx.modelName.includes('gpt-4'),\n * response: { text: 'Mocked response' }\n * });\n */\n register(registration: Omit<MockRegistration, \"id\"> & { id?: string }): string {\n const id = registration.id ?? `mock-${this.nextId++}`;\n const mock: MockRegistration = {\n id,\n matcher: registration.matcher,\n response: registration.response,\n label: registration.label,\n once: registration.once,\n };\n\n this.mocks.set(id, mock);\n\n if (this.options.recordStats) {\n this.stats.set(id, { matchCount: 0 });\n }\n\n this.logger.debug(\n `Registered mock: ${id}${mock.label ? ` (${mock.label})` : \"\"}${mock.once ? \" [once]\" : \"\"}`,\n );\n\n return id;\n }\n\n /**\n * Unregister a mock by ID.\n */\n unregister(id: string): boolean {\n const deleted = this.mocks.delete(id);\n if (deleted) {\n this.stats.delete(id);\n this.logger.debug(`Unregistered mock: ${id}`);\n }\n return deleted;\n }\n\n /**\n * Clear all registered mocks.\n */\n clear(): void {\n this.mocks.clear();\n this.stats.clear();\n this.logger.debug(\"Cleared all mocks\");\n }\n\n /**\n * Find and return a matching mock for the given context.\n * Returns the mock response if found, null otherwise.\n */\n async findMatch(context: MockMatcherContext): Promise<MockResponse | null> {\n this.logger.debug(\n `Finding match for: ${context.provider}:${context.modelName} (${this.mocks.size} mocks registered)`,\n );\n\n for (const [id, mock] of this.mocks.entries()) {\n let matches = false;\n\n try {\n matches = await Promise.resolve(mock.matcher(context));\n } catch (error) {\n // Matcher errors are caught - a matcher that throws simply doesn't match\n this.logger.warn(`Error in matcher ${id}:`, error);\n // In strict mode, re-throw matcher errors to help catch bugs\n if (this.options.strictMode) {\n throw new Error(`Matcher error in mock ${id}: ${error}`);\n }\n continue; // Skip to next mock\n }\n\n if (matches) {\n this.logger.debug(`Mock matched: ${id}${mock.label ? ` (${mock.label})` : \"\"}`);\n\n // Record stats\n if (this.options.recordStats) {\n const stats = this.stats.get(id);\n if (stats) {\n stats.matchCount++;\n stats.lastUsed = new Date();\n }\n }\n\n // Remove if once\n if (mock.once) {\n this.mocks.delete(id);\n this.stats.delete(id);\n this.logger.debug(`Removed one-time mock: ${id}`);\n }\n\n // Resolve response (could be a function)\n // Response errors are NOT caught - they should propagate to the caller\n const response =\n typeof mock.response === \"function\"\n ? await Promise.resolve(mock.response(context))\n : mock.response;\n\n return response;\n }\n }\n\n // No match found\n this.logger.debug(\"No mock matched\");\n\n if (this.options.strictMode) {\n throw new Error(\n `No mock registered for ${context.provider}:${context.modelName}. ` +\n `Register a mock using MockManager.getInstance().register() or disable strictMode.`,\n );\n }\n\n // Return empty response in non-strict mode\n return {\n text: \"\",\n usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\n finishReason: \"stop\",\n };\n }\n\n /**\n * Get statistics for a specific mock.\n */\n getStats(id: string): MockStats | undefined {\n return this.stats.get(id);\n }\n\n /**\n * Get all registered mock IDs.\n */\n getMockIds(): string[] {\n return Array.from(this.mocks.keys());\n }\n\n /**\n * Get the number of registered mocks.\n */\n getCount(): number {\n return this.mocks.size;\n }\n\n /**\n * Update the mock manager options.\n */\n setOptions(options: Partial<MockOptions>): void {\n this.options = { ...this.options, ...options };\n this.logger = createLogger({ name: \"MockManager\", minLevel: this.options.debug ? 2 : 3 });\n }\n}\n\n/**\n * Helper function to get the global mock manager instance.\n */\nexport function getMockManager(options?: MockOptions): MockManager {\n return MockManager.getInstance(options);\n}\n","import { GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { LLMStream, LLMStreamChunk } from \"../core/options.js\";\nimport type { MockResponse } from \"./mock-types.js\";\n\n/**\n * Utility to sleep for a given duration.\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Generate a unique invocation ID for gadget calls.\n */\nfunction generateInvocationId(): string {\n return `inv-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Split text into chunks for streaming simulation.\n * Tries to split on word boundaries for more realistic streaming.\n */\nfunction splitIntoChunks(text: string, minChunkSize = 5, maxChunkSize = 30): string[] {\n const chunks: string[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n // Determine chunk size\n const chunkSize = Math.min(\n Math.floor(Math.random() * (maxChunkSize - minChunkSize + 1)) + minChunkSize,\n remaining.length,\n );\n\n // Try to split on word boundary\n let chunk: string;\n if (chunkSize < remaining.length) {\n const substr = remaining.substring(0, chunkSize);\n const lastSpace = substr.lastIndexOf(\" \");\n if (lastSpace > minChunkSize / 2) {\n chunk = substr.substring(0, lastSpace + 1);\n } else {\n chunk = substr;\n }\n } else {\n chunk = remaining;\n }\n\n chunks.push(chunk);\n remaining = remaining.substring(chunk.length);\n }\n\n return chunks;\n}\n\n/**\n * Convert gadget calls in MockResponse to their text representation.\n * Formats them as the stream parser expects: !!!GADGET_START:name\\n{params}\\n!!!GADGET_END\n */\nfunction formatGadgetCalls(gadgetCalls: NonNullable<MockResponse[\"gadgetCalls\"]>): {\n text: string;\n calls: Array<{ name: string; invocationId: string }>;\n} {\n let text = \"\";\n const calls: Array<{ name: string; invocationId: string }> = [];\n\n for (const call of gadgetCalls) {\n const invocationId = call.invocationId ?? generateInvocationId();\n calls.push({ name: call.gadgetName, invocationId });\n\n // Format parameters as JSON (default format)\n const paramsJson = JSON.stringify(call.parameters);\n\n // Format using the new gadget marker format\n text += `\\n${GADGET_START_PREFIX}${call.gadgetName}\\n${paramsJson}\\n${GADGET_END_PREFIX}`;\n }\n\n return { text, calls };\n}\n\n/**\n * Create a mock LLM stream from a mock response.\n * This simulates the streaming behavior of real LLM providers.\n *\n * @param response - The mock response configuration\n * @returns An async iterable that yields LLMStreamChunks\n */\nexport async function* createMockStream(response: MockResponse): LLMStream {\n // Initial delay (simulate network latency)\n if (response.delayMs) {\n await sleep(response.delayMs);\n }\n\n const streamDelay = response.streamDelayMs ?? 0;\n let fullText = response.text ?? \"\";\n\n // Add gadget calls to the text if provided\n if (response.gadgetCalls && response.gadgetCalls.length > 0) {\n const { text: gadgetText } = formatGadgetCalls(response.gadgetCalls);\n fullText += gadgetText;\n }\n\n // Stream the text in chunks\n if (fullText.length > 0) {\n const chunks = streamDelay > 0 ? splitIntoChunks(fullText) : [fullText];\n\n for (let i = 0; i < chunks.length; i++) {\n const isLast = i === chunks.length - 1;\n\n const chunk: LLMStreamChunk = {\n text: chunks[i],\n };\n\n // Add finish reason and usage on the last chunk\n if (isLast) {\n if (response.finishReason !== undefined) {\n chunk.finishReason = response.finishReason;\n }\n if (response.usage) {\n chunk.usage = response.usage;\n }\n }\n\n yield chunk;\n\n // Delay between chunks\n if (streamDelay > 0 && !isLast) {\n await sleep(streamDelay);\n }\n }\n } else {\n // Empty response - still yield a final chunk with metadata\n yield {\n text: \"\",\n finishReason: response.finishReason ?? \"stop\",\n usage: response.usage ?? { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\n };\n }\n}\n\n/**\n * Create a simple text-only mock stream.\n * Convenience helper for quickly creating mock responses.\n *\n * @param text - The text to stream\n * @param options - Optional streaming configuration\n *\n * @example\n * const stream = createTextMockStream('Hello, world!');\n * for await (const chunk of stream) {\n * console.log(chunk.text);\n * }\n */\nexport function createTextMockStream(\n text: string,\n options?: {\n delayMs?: number;\n streamDelayMs?: number;\n usage?: MockResponse[\"usage\"];\n },\n): LLMStream {\n return createMockStream({\n text,\n delayMs: options?.delayMs,\n streamDelayMs: options?.streamDelayMs,\n usage: options?.usage,\n finishReason: \"stop\",\n });\n}\n","import type { LLMMessage } from \"../core/messages.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport { ModelIdentifierParser } from \"../core/options.js\";\nimport type { ProviderAdapter } from \"../providers/provider.js\";\nimport { getMockManager, type MockManager } from \"./mock-manager.js\";\nimport { createMockStream } from \"./mock-stream.js\";\nimport type { MockMatcherContext, MockOptions } from \"./mock-types.js\";\n\n/**\n * Provider adapter that serves mock responses instead of making real LLM API calls.\n * This is useful for testing applications that use llmist without incurring API costs.\n *\n * The MockProviderAdapter has high priority (100) and is always checked before\n * real providers when both are registered. This enables selective mocking where\n * some models use mocks while others use real providers. If no matching mock is\n * found and strictMode is disabled, requests return an empty response.\n *\n * @example\n * ```typescript\n * import { LLMist, createMockAdapter, mockLLM } from 'llmist/testing';\n *\n * // Use with real providers for selective mocking\n * const client = new LLMist({\n * adapters: [createMockAdapter()],\n * autoDiscoverProviders: true // Also loads real OpenAI, Anthropic, etc.\n * });\n *\n * // Register mocks for specific models\n * mockLLM()\n * .forModel('gpt-5-nano')\n * .returns('Test response')\n * .register();\n *\n * // gpt-5-nano uses mock, other models use real providers\n * const stream = client.stream({\n * model: 'openai:gpt-5-nano',\n * messages: [{ role: 'user', content: 'test' }]\n * });\n * ```\n */\nexport class MockProviderAdapter implements ProviderAdapter {\n readonly providerId = \"mock\";\n readonly priority = 100; // High priority: check mocks before real providers\n private readonly mockManager: MockManager;\n\n constructor(options?: MockOptions) {\n this.mockManager = getMockManager(options);\n }\n\n supports(descriptor: ModelDescriptor): boolean {\n // Support any provider when using mock adapter\n // This allows tests to use \"openai:gpt-4\", \"anthropic:claude\", etc.\n return true;\n }\n\n stream(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n // spec is unused for mocks\n // biome-ignore lint/correctness/noUnusedVariables: spec parameter required by interface\n spec?: unknown,\n ): LLMStream {\n // Create matcher context\n const context: MockMatcherContext = {\n model: options.model,\n provider: descriptor.provider,\n modelName: descriptor.name,\n options,\n messages: options.messages,\n };\n\n // Find matching mock (async operation)\n // We need to handle this in the stream generator\n return this.createMockStreamFromContext(context);\n }\n\n private async *createMockStreamFromContext(context: MockMatcherContext): LLMStream {\n try {\n // Find matching mock\n const mockResponse = await this.mockManager.findMatch(context);\n\n if (!mockResponse) {\n // This should not happen if MockManager is configured correctly\n // but handle it gracefully\n yield {\n text: \"\",\n finishReason: \"stop\",\n usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\n };\n return;\n }\n\n // Stream the mock response\n yield* createMockStream(mockResponse);\n } catch (error) {\n // If an error occurs (e.g., strictMode with no match), we need to handle it\n throw error;\n }\n }\n}\n\n/**\n * Create a mock provider adapter instance.\n * This is a convenience factory function.\n *\n * @param options - Optional configuration for the mock system\n * @returns A configured MockProviderAdapter\n *\n * @example\n * ```typescript\n * const adapter = createMockAdapter({ strictMode: true, debug: true });\n * const client = new LLMist([adapter]);\n * ```\n */\nexport function createMockAdapter(options?: MockOptions): MockProviderAdapter {\n return new MockProviderAdapter(options);\n}\n","import type { LLMMessage } from \"../core/messages.js\";\nimport { getMockManager } from \"./mock-manager.js\";\nimport type {\n MockMatcher,\n MockMatcherContext,\n MockRegistration,\n MockResponse,\n} from \"./mock-types.js\";\n\n/**\n * Fluent builder for creating mock responses and registrations.\n * Provides a convenient API for common mocking scenarios.\n *\n * @example\n * ```typescript\n * import { mockLLM } from 'llmist';\n *\n * // Simple text mock\n * mockLLM()\n * .forModel('gpt-5')\n * .returns('Hello, world!')\n * .register();\n *\n * // Mock with gadget calls\n * mockLLM()\n * .forProvider('anthropic')\n * .whenMessageContains('calculate')\n * .returnsGadgetCalls([\n * { gadgetName: 'calculator', parameters: { operation: 'add', a: 1, b: 2 } }\n * ])\n * .register();\n *\n * // Complex conditional mock\n * mockLLM()\n * .when((ctx) => ctx.messages.length > 5)\n * .returns('This conversation is getting long!')\n * .once()\n * .register();\n * ```\n */\nexport class MockBuilder {\n private matchers: MockMatcher[] = [];\n private response:\n | MockResponse\n | ((context: MockMatcherContext) => MockResponse | Promise<MockResponse>) = {};\n private label?: string;\n private isOnce = false;\n private id?: string;\n\n /**\n * Match calls to a specific model (by name, supports partial matching).\n *\n * @example\n * mockLLM().forModel('gpt-5')\n * mockLLM().forModel('claude') // matches any Claude model\n */\n forModel(modelName: string): this {\n if (!modelName || modelName.trim() === \"\") {\n throw new Error(\"Model name cannot be empty\");\n }\n this.matchers.push((ctx) => ctx.modelName.includes(modelName));\n return this;\n }\n\n /**\n * Match calls to any model.\n * Useful when you want to mock responses regardless of the model used.\n *\n * @example\n * mockLLM().forAnyModel()\n */\n forAnyModel(): this {\n this.matchers.push(() => true);\n return this;\n }\n\n /**\n * Match calls to a specific provider.\n *\n * @example\n * mockLLM().forProvider('openai')\n * mockLLM().forProvider('anthropic')\n */\n forProvider(provider: string): this {\n if (!provider || provider.trim() === \"\") {\n throw new Error(\"Provider name cannot be empty\");\n }\n this.matchers.push((ctx) => ctx.provider === provider);\n return this;\n }\n\n /**\n * Match calls to any provider.\n * Useful when you want to mock responses regardless of the provider used.\n *\n * @example\n * mockLLM().forAnyProvider()\n */\n forAnyProvider(): this {\n this.matchers.push(() => true);\n return this;\n }\n\n /**\n * Match when any message contains the given text (case-insensitive).\n *\n * @example\n * mockLLM().whenMessageContains('hello')\n */\n whenMessageContains(text: string): this {\n this.matchers.push((ctx) =>\n ctx.messages.some((msg) => msg.content?.toLowerCase().includes(text.toLowerCase())),\n );\n return this;\n }\n\n /**\n * Match when the last message contains the given text (case-insensitive).\n *\n * @example\n * mockLLM().whenLastMessageContains('goodbye')\n */\n whenLastMessageContains(text: string): this {\n this.matchers.push((ctx) => {\n const lastMsg = ctx.messages[ctx.messages.length - 1];\n return lastMsg?.content?.toLowerCase().includes(text.toLowerCase()) ?? false;\n });\n return this;\n }\n\n /**\n * Match when any message matches the given regex.\n *\n * @example\n * mockLLM().whenMessageMatches(/calculate \\d+/)\n */\n whenMessageMatches(regex: RegExp): this {\n this.matchers.push((ctx) => ctx.messages.some((msg) => regex.test(msg.content ?? \"\")));\n return this;\n }\n\n /**\n * Match when a message with a specific role contains text.\n *\n * @example\n * mockLLM().whenRoleContains('system', 'You are a helpful assistant')\n */\n whenRoleContains(role: LLMMessage[\"role\"], text: string): this {\n this.matchers.push((ctx) =>\n ctx.messages.some(\n (msg) => msg.role === role && msg.content?.toLowerCase().includes(text.toLowerCase()),\n ),\n );\n return this;\n }\n\n /**\n * Match based on the number of messages in the conversation.\n *\n * @example\n * mockLLM().whenMessageCount((count) => count > 10)\n */\n whenMessageCount(predicate: (count: number) => boolean): this {\n this.matchers.push((ctx) => predicate(ctx.messages.length));\n return this;\n }\n\n /**\n * Add a custom matcher function.\n * This provides full control over matching logic.\n *\n * @example\n * mockLLM().when((ctx) => {\n * return ctx.options.temperature > 0.8;\n * })\n */\n when(matcher: MockMatcher): this {\n this.matchers.push(matcher);\n return this;\n }\n\n /**\n * Set the text response to return.\n * Can be a static string or a function that returns a string dynamically.\n *\n * @example\n * mockLLM().returns('Hello, world!')\n * mockLLM().returns(() => `Response at ${Date.now()}`)\n * mockLLM().returns((ctx) => `You said: ${ctx.messages[0]?.content}`)\n */\n returns(text: string | ((context: MockMatcherContext) => string | Promise<string>)): this {\n if (typeof text === \"function\") {\n // Convert function to full response generator\n // Use Promise.resolve().then() to properly handle both sync and async errors\n this.response = async (ctx) => {\n const resolvedText = await Promise.resolve().then(() => text(ctx));\n return { text: resolvedText };\n };\n } else {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use returns() after withResponse() with a function\");\n }\n this.response.text = text;\n }\n return this;\n }\n\n /**\n * Set gadget calls to include in the response.\n *\n * @example\n * mockLLM().returnsGadgetCalls([\n * { gadgetName: 'calculator', parameters: { op: 'add', a: 1, b: 2 } }\n * ])\n */\n returnsGadgetCalls(\n calls: Array<{\n gadgetName: string;\n parameters: Record<string, unknown>;\n invocationId?: string;\n }>,\n ): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use returnsGadgetCalls() after withResponse() with a function\");\n }\n this.response.gadgetCalls = calls;\n return this;\n }\n\n /**\n * Add a single gadget call to the response.\n *\n * @example\n * mockLLM()\n * .returnsGadgetCall('calculator', { op: 'add', a: 1, b: 2 })\n * .returnsGadgetCall('logger', { message: 'Done!' })\n */\n returnsGadgetCall(gadgetName: string, parameters: Record<string, unknown>): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use returnsGadgetCall() after withResponse() with a function\");\n }\n if (!this.response.gadgetCalls) {\n this.response.gadgetCalls = [];\n }\n this.response.gadgetCalls.push({ gadgetName, parameters });\n return this;\n }\n\n /**\n * Set the complete mock response object.\n * This allows full control over all response properties.\n * Can also be a function that generates the response dynamically based on context.\n *\n * @example\n * // Static response\n * mockLLM().withResponse({\n * text: 'Hello',\n * usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },\n * finishReason: 'stop'\n * })\n *\n * @example\n * // Dynamic response\n * mockLLM().withResponse((ctx) => ({\n * text: `You said: ${ctx.messages[ctx.messages.length - 1]?.content}`,\n * usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 }\n * }))\n */\n withResponse(\n response:\n | MockResponse\n | ((context: MockMatcherContext) => MockResponse | Promise<MockResponse>),\n ): this {\n this.response = response;\n return this;\n }\n\n /**\n * Set simulated token usage.\n *\n * @example\n * mockLLM().withUsage({ inputTokens: 100, outputTokens: 50, totalTokens: 150 })\n */\n withUsage(usage: { inputTokens: number; outputTokens: number; totalTokens: number }): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use withUsage() after withResponse() with a function\");\n }\n if (usage.inputTokens < 0 || usage.outputTokens < 0 || usage.totalTokens < 0) {\n throw new Error(\"Token counts cannot be negative\");\n }\n if (usage.totalTokens !== usage.inputTokens + usage.outputTokens) {\n throw new Error(\"totalTokens must equal inputTokens + outputTokens\");\n }\n this.response.usage = usage;\n return this;\n }\n\n /**\n * Set the finish reason.\n *\n * @example\n * mockLLM().withFinishReason('stop')\n * mockLLM().withFinishReason('length')\n */\n withFinishReason(reason: string): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use withFinishReason() after withResponse() with a function\");\n }\n this.response.finishReason = reason;\n return this;\n }\n\n /**\n * Set initial delay before streaming starts (simulates network latency).\n *\n * @example\n * mockLLM().withDelay(100) // 100ms delay\n */\n withDelay(ms: number): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use withDelay() after withResponse() with a function\");\n }\n if (ms < 0) {\n throw new Error(\"Delay must be non-negative\");\n }\n this.response.delayMs = ms;\n return this;\n }\n\n /**\n * Set delay between stream chunks (simulates realistic streaming).\n *\n * @example\n * mockLLM().withStreamDelay(10) // 10ms between chunks\n */\n withStreamDelay(ms: number): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use withStreamDelay() after withResponse() with a function\");\n }\n if (ms < 0) {\n throw new Error(\"Stream delay must be non-negative\");\n }\n this.response.streamDelayMs = ms;\n return this;\n }\n\n /**\n * Set a label for this mock (useful for debugging).\n *\n * @example\n * mockLLM().withLabel('greeting mock')\n */\n withLabel(label: string): this {\n this.label = label;\n return this;\n }\n\n /**\n * Set a specific ID for this mock.\n *\n * @example\n * mockLLM().withId('my-custom-mock-id')\n */\n withId(id: string): this {\n this.id = id;\n return this;\n }\n\n /**\n * Mark this mock as one-time use (will be removed after first match).\n *\n * @example\n * mockLLM().once()\n */\n once(): this {\n this.isOnce = true;\n return this;\n }\n\n /**\n * Build the mock registration without registering it.\n * Useful if you want to register it manually later.\n *\n * @returns The built MockRegistration object (without id if not specified)\n */\n build(): Omit<MockRegistration, \"id\"> & { id?: string } {\n // Guard against empty matchers\n if (this.matchers.length === 0) {\n throw new Error(\n \"Mock must have at least one matcher. Use .when(), .forModel(), .forProvider(), etc.\",\n );\n }\n\n // Combine all matchers with AND logic\n const combinedMatcher: MockMatcher = async (ctx) => {\n for (const matcher of this.matchers) {\n const matches = await Promise.resolve(matcher(ctx));\n if (!matches) return false;\n }\n return true;\n };\n\n return {\n id: this.id,\n matcher: combinedMatcher,\n response: this.response,\n label: this.label,\n once: this.isOnce,\n };\n }\n\n /**\n * Register this mock with the global MockManager.\n * Returns the ID of the registered mock.\n *\n * @example\n * const mockId = mockLLM().forModel('gpt-5').returns('Hello!').register();\n * // Later: getMockManager().unregister(mockId);\n */\n register(): string {\n const mockManager = getMockManager();\n const registration = this.build();\n return mockManager.register(registration);\n }\n}\n\n/**\n * Create a new MockBuilder instance.\n * This is the main entry point for the fluent mock API.\n *\n * @example\n * ```typescript\n * import { mockLLM } from 'llmist';\n *\n * mockLLM()\n * .forModel('gpt-5')\n * .whenMessageContains('hello')\n * .returns('Hello there!')\n * .register();\n * ```\n */\nexport function mockLLM(): MockBuilder {\n return new MockBuilder();\n}\n","import { LLMist } from \"../core/client.js\";\nimport { MockProviderAdapter } from \"./mock-adapter.js\";\nimport type { MockOptions } from \"./mock-types.js\";\n\n/**\n * Create a preconfigured LLMist client with mock adapter.\n * This is a convenience function for testing scenarios.\n *\n * @param options - Optional configuration for the mock system\n * @returns A LLMist instance configured to use mocks\n *\n * @example\n * ```typescript\n * import { createMockClient, getMockManager } from 'llmist';\n *\n * // Setup\n * const client = createMockClient({ strictMode: true });\n * const mockManager = getMockManager();\n *\n * // Register mocks\n * mockManager.register({\n * matcher: (ctx) => ctx.modelName === 'gpt-4',\n * response: { text: 'Mocked response' }\n * });\n *\n * // Use in tests\n * const stream = client.stream({\n * model: 'mock:gpt-4',\n * messages: [{ role: 'user', content: 'test' }]\n * });\n * ```\n */\nexport function createMockClient(options?: MockOptions): LLMist {\n return new LLMist({\n adapters: [new MockProviderAdapter(options)],\n autoDiscoverProviders: false,\n defaultProvider: \"mock\",\n });\n}\n","/**\n * Mock gadget utilities for testing.\n *\n * Provides helpers for creating mock gadgets with configurable behavior\n * and call tracking.\n *\n * @module testing/mock-gadget\n */\n\nimport type { ZodType } from \"zod\";\nimport { BaseGadget } from \"../gadgets/gadget.js\";\n\n/**\n * Recorded gadget call for tracking.\n */\nexport interface RecordedCall {\n /** Parameters passed to execute() */\n params: Record<string, unknown>;\n /** When the call was made */\n timestamp: number;\n}\n\n/**\n * Mock gadget with call tracking capabilities.\n */\nexport interface MockGadget extends BaseGadget {\n /** Get all recorded calls */\n getCalls(): RecordedCall[];\n /** Get number of times the gadget was executed */\n getCallCount(): number;\n /** Reset call history */\n resetCalls(): void;\n /** Check if gadget was called with specific params (partial match) */\n wasCalledWith(params: Partial<Record<string, unknown>>): boolean;\n /** Get the last call's parameters */\n getLastCall(): RecordedCall | undefined;\n}\n\n/**\n * Configuration for creating a mock gadget.\n */\nexport interface MockGadgetConfig<TSchema extends ZodType = ZodType> {\n /** Gadget name (required) */\n name: string;\n /** Gadget description */\n description?: string;\n /** Parameter schema */\n schema?: TSchema;\n /** Static result to return */\n result?: string;\n /** Dynamic result based on parameters */\n resultFn?: (params: Record<string, unknown>) => string | Promise<string>;\n /** Error to throw on execution */\n error?: Error | string;\n /** Enable call tracking (default: true) */\n trackCalls?: boolean;\n /** Execution delay in ms */\n delayMs?: number;\n /** Gadget timeout setting */\n timeoutMs?: number;\n}\n\n/**\n * Implementation of MockGadget.\n */\nclass MockGadgetImpl extends BaseGadget implements MockGadget {\n override name: string;\n override description: string;\n override parameterSchema?: ZodType;\n override timeoutMs?: number;\n\n private calls: RecordedCall[] = [];\n private readonly resultValue?: string;\n private readonly resultFn?: (params: Record<string, unknown>) => string | Promise<string>;\n private readonly errorToThrow?: Error;\n private readonly delayMs: number;\n private readonly shouldTrackCalls: boolean;\n\n constructor(config: MockGadgetConfig) {\n super();\n this.name = config.name;\n this.description = config.description ?? `Mock gadget: ${config.name}`;\n this.parameterSchema = config.schema;\n this.resultValue = config.result;\n this.resultFn = config.resultFn;\n this.delayMs = config.delayMs ?? 0;\n this.shouldTrackCalls = config.trackCalls ?? true;\n this.timeoutMs = config.timeoutMs;\n\n if (config.error) {\n this.errorToThrow = typeof config.error === \"string\" ? new Error(config.error) : config.error;\n }\n }\n\n async execute(params: Record<string, unknown>): Promise<string> {\n if (this.shouldTrackCalls) {\n this.calls.push({ params: { ...params }, timestamp: Date.now() });\n }\n\n if (this.delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, this.delayMs));\n }\n\n if (this.errorToThrow) {\n throw this.errorToThrow;\n }\n\n if (this.resultFn) {\n return this.resultFn(params);\n }\n\n return this.resultValue ?? \"mock result\";\n }\n\n getCalls(): RecordedCall[] {\n return [...this.calls];\n }\n\n getCallCount(): number {\n return this.calls.length;\n }\n\n resetCalls(): void {\n this.calls = [];\n }\n\n wasCalledWith(params: Partial<Record<string, unknown>>): boolean {\n return this.calls.some((call) =>\n Object.entries(params).every(([key, value]) => call.params[key] === value),\n );\n }\n\n getLastCall(): RecordedCall | undefined {\n return this.calls.length > 0 ? this.calls[this.calls.length - 1] : undefined;\n }\n}\n\n/**\n * Create a mock gadget for testing.\n *\n * @param config - Mock gadget configuration\n * @returns MockGadget instance with call tracking\n *\n * @example\n * ```typescript\n * import { createMockGadget } from 'llmist/testing';\n * import { z } from 'zod';\n *\n * const calculator = createMockGadget({\n * name: 'Calculator',\n * schema: z.object({ a: z.number(), b: z.number() }),\n * resultFn: ({ a, b }) => String(Number(a) + Number(b)),\n * });\n *\n * // Use in tests\n * const registry = new GadgetRegistry();\n * registry.registerByClass(calculator);\n *\n * // After running agent...\n * expect(calculator.getCallCount()).toBe(1);\n * expect(calculator.wasCalledWith({ a: 5 })).toBe(true);\n * ```\n */\nexport function createMockGadget<TSchema extends ZodType>(\n config: MockGadgetConfig<TSchema>,\n): MockGadget {\n return new MockGadgetImpl(config);\n}\n\n/**\n * Fluent builder for creating mock gadgets.\n *\n * @example\n * ```typescript\n * import { mockGadget } from 'llmist/testing';\n * import { z } from 'zod';\n *\n * const mock = mockGadget()\n * .withName('Weather')\n * .withDescription('Get weather for a city')\n * .withSchema(z.object({ city: z.string() }))\n * .returns('Sunny, 72F')\n * .trackCalls()\n * .build();\n *\n * // Or for error testing\n * const errorMock = mockGadget()\n * .withName('Unstable')\n * .throws('Service unavailable')\n * .build();\n * ```\n */\nexport class MockGadgetBuilder {\n private config: MockGadgetConfig = { name: \"MockGadget\" };\n\n /**\n * Set the gadget name.\n */\n withName(name: string): this {\n this.config.name = name;\n return this;\n }\n\n /**\n * Set the gadget description.\n */\n withDescription(description: string): this {\n this.config.description = description;\n return this;\n }\n\n /**\n * Set the parameter schema.\n */\n withSchema<T extends ZodType>(schema: T): MockGadgetBuilder {\n this.config.schema = schema;\n return this;\n }\n\n /**\n * Set a static result to return.\n */\n returns(result: string): this {\n this.config.result = result;\n this.config.resultFn = undefined;\n return this;\n }\n\n /**\n * Set a dynamic result function.\n */\n returnsAsync(resultFn: (params: Record<string, unknown>) => string | Promise<string>): this {\n this.config.resultFn = resultFn;\n this.config.result = undefined;\n return this;\n }\n\n /**\n * Make the gadget throw an error on execution.\n */\n throws(error: Error | string): this {\n this.config.error = error;\n return this;\n }\n\n /**\n * Add execution delay.\n */\n withDelay(ms: number): this {\n this.config.delayMs = ms;\n return this;\n }\n\n /**\n * Set timeout for the gadget.\n */\n withTimeout(ms: number): this {\n this.config.timeoutMs = ms;\n return this;\n }\n\n /**\n * Enable call tracking (enabled by default).\n */\n trackCalls(): this {\n this.config.trackCalls = true;\n return this;\n }\n\n /**\n * Disable call tracking.\n */\n noTracking(): this {\n this.config.trackCalls = false;\n return this;\n }\n\n /**\n * Build the mock gadget.\n */\n build(): MockGadget {\n return createMockGadget(this.config);\n }\n}\n\n/**\n * Create a fluent builder for mock gadgets.\n *\n * @returns New MockGadgetBuilder instance\n *\n * @example\n * ```typescript\n * const mock = mockGadget()\n * .withName('Search')\n * .withSchema(z.object({ query: z.string() }))\n * .returnsAsync(async ({ query }) => {\n * return `Results for: ${query}`;\n * })\n * .build();\n * ```\n */\nexport function mockGadget(): MockGadgetBuilder {\n return new MockGadgetBuilder();\n}\n"],"mappings":"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","names":["z","keyIndentLen","yaml","parseToml","stream","stream","init_constants","Anthropic","init_constants","stream","init_constants","stream","OpenAI","init_constants","stream","providerSpecs","import_zod"]}
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/error-formatter.ts","../src/gadgets/exceptions.ts","../src/gadgets/executor.ts","../src/gadgets/block-params.ts","../src/gadgets/parser.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/index.ts","../src/agent/hook-presets.ts","../src/agent/index.ts","../src/gadgets/typed-gadget.ts","../src/gadgets/validation.ts","../src/testing/mock-manager.ts","../src/testing/mock-stream.ts","../src/testing/mock-adapter.ts","../src/testing/mock-builder.ts","../src/testing/mock-client.ts","../src/testing/mock-gadget.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 { 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 type { ILogObj, Logger } from \"tslog\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { GadgetErrorFormatter, type ErrorFormatterOptions } from \"./error-formatter.js\";\nimport { BreakLoopException, HumanInputException, TimeoutException } from \"./exceptions.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\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 }\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 if (gadget.parameterSchema) {\n const validationResult = gadget.parameterSchema.safeParse(rawParameters);\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: rawParameters,\n error: validationError,\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n validatedParameters = validationResult.data as Record<string, unknown>;\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","import { GADGET_ARG_PREFIX } from \"../core/constants.js\";\n\nexport interface BlockParseOptions {\n /** Prefix that declares an argument. Default: \"!!!ARG:\" */\n argPrefix?: string;\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 // 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, \"\");\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);\n }\n\n return result;\n}\n\n/**\n * Coerce a string value to its appropriate primitive type.\n * - \"true\" / \"false\" → boolean\n * - Numeric strings → number\n * - Everything else stays string\n *\n * Only coerces single-line values to avoid accidentally converting\n * code or multiline content that happens to look like a number/boolean.\n */\nfunction coerceValue(value: string): 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 // 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 automatically coerced to appropriate types (boolean, number)\n * for single-line values.\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 * @throws Error if array index gaps detected\n */\nfunction setByPointer(\n obj: Record<string, unknown>,\n pointer: string,\n value: string\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 // Coerce the value to appropriate type\n const coercedValue = coerceValue(value);\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 { 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","/**\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 );\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","// Re-export Zod's z for schema definitions\n// Using llmist's z ensures .describe() metadata is preserved in JSON schemas\nexport { z } from \"zod\";\n// Syntactic sugar: Agent builder and event handlers\nexport type { HistoryMessage } from \"./agent/builder.js\";\nexport { AgentBuilder } from \"./agent/builder.js\";\nexport type { EventHandlers } from \"./agent/event-handlers.js\";\nexport { collectEvents, collectText, runWithHandlers } from \"./agent/event-handlers.js\";\n// Syntactic sugar: Hook presets\nexport type { LoggingOptions } from \"./agent/hook-presets.js\";\nexport { HookPresets } from \"./agent/hook-presets.js\";\n// Agent infrastructure\n// New clean hooks system\nexport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n AgentOptions,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n // Interceptor contexts\n ChunkInterceptorContext,\n Controllers,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n IConversationManager,\n Interceptors,\n // Controller contexts and actions\n LLMCallControllerContext,\n LLMErrorControllerContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetStartContext,\n // Observer contexts\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n Observers,\n StreamProcessingResult,\n StreamProcessorOptions,\n // Gadget output limiting\n StoredOutput,\n} from \"./agent/index.js\";\nexport { ConversationManager, GadgetOutputStore, StreamProcessor } from \"./agent/index.js\";\nexport type { LLMistOptions } from \"./core/client.js\";\nexport { LLMist } from \"./core/client.js\";\nexport type { LLMMessage, LLMRole } from \"./core/messages.js\";\nexport { LLMMessageBuilder } from \"./core/messages.js\";\n// Model catalog\nexport type {\n CostEstimate,\n ModelFeatures,\n ModelLimits,\n ModelPricing,\n ModelSpec,\n} from \"./core/model-catalog.js\";\nexport { ModelRegistry } from \"./core/model-registry.js\";\n\n// Syntactic sugar: Model shortcuts and quick methods\nexport {\n getModelId,\n getProvider,\n hasProviderPrefix,\n MODEL_ALIASES,\n resolveModel,\n} from \"./core/model-shortcuts.js\";\nexport type {\n LLMGenerationOptions,\n LLMStream,\n LLMStreamChunk,\n ModelDescriptor,\n ProviderIdentifier,\n TokenUsage,\n} from \"./core/options.js\";\nexport { ModelIdentifierParser } from \"./core/options.js\";\nexport type { PromptConfig, PromptContext, PromptTemplate } from \"./core/prompt-config.js\";\nexport {\n DEFAULT_PROMPTS,\n resolvePromptTemplate,\n resolveRulesTemplate,\n} from \"./core/prompt-config.js\";\nexport type { QuickOptions } from \"./core/quick-methods.js\";\nexport { complete, stream } from \"./core/quick-methods.js\";\nexport type { CreateGadgetConfig } from \"./gadgets/create-gadget.js\";\nexport { createGadget } from \"./gadgets/create-gadget.js\";\n// Gadget output viewer (for custom output store integration)\nexport { createGadgetOutputViewer } from \"./gadgets/output-viewer.js\";\n// Gadget infrastructure\nexport { BreakLoopException, HumanInputException } from \"./gadgets/exceptions.js\";\nexport { GadgetExecutor } from \"./gadgets/executor.js\";\nexport { BaseGadget } from \"./gadgets/gadget.js\";\nexport { StreamParser } from \"./gadgets/parser.js\";\nexport type { GadgetClass, GadgetOrClass } from \"./gadgets/registry.js\";\nexport { GadgetRegistry } from \"./gadgets/registry.js\";\n\n// Syntactic sugar: Typed gadgets and helpers\nexport type { GadgetConfig } from \"./gadgets/typed-gadget.js\";\nexport { Gadget } from \"./gadgets/typed-gadget.js\";\nexport type {\n GadgetExample,\n GadgetExecutionResult,\n ParsedGadgetCall,\n StreamEvent,\n TextOnlyAction,\n TextOnlyContext,\n TextOnlyCustomHandler,\n TextOnlyGadgetConfig,\n TextOnlyHandler,\n TextOnlyStrategy,\n} from \"./gadgets/types.js\";\nexport type { ValidationIssue, ValidationResult } from \"./gadgets/validation.js\";\nexport { validateAndApplyDefaults, validateGadgetParams } from \"./gadgets/validation.js\";\nexport type { LoggerOptions } from \"./logging/logger.js\";\nexport { createLogger, defaultLogger } from \"./logging/logger.js\";\nexport {\n AnthropicMessagesProvider,\n createAnthropicProviderFromEnv,\n} from \"./providers/anthropic.js\";\nexport { discoverProviderAdapters } from \"./providers/discovery.js\";\nexport { createGeminiProviderFromEnv, GeminiGenerativeProvider } from \"./providers/gemini.js\";\nexport { createOpenAIProviderFromEnv, OpenAIChatProvider } from \"./providers/openai.js\";\nexport type { ProviderAdapter } from \"./providers/provider.js\";\n\n// Testing/Mock infrastructure\nexport type {\n MockMatcher,\n MockMatcherContext,\n MockOptions,\n MockRegistration,\n MockResponse,\n MockStats,\n} from \"./testing/index.js\";\nexport {\n createMockAdapter,\n createMockClient,\n createMockStream,\n createTextMockStream,\n getMockManager,\n MockBuilder,\n MockManager,\n MockProviderAdapter,\n mockLLM,\n} from \"./testing/index.js\";\n","/**\n * Ready-to-use hook configurations for common monitoring, logging, and debugging tasks.\n *\n * HookPresets provide instant observability without writing custom hooks. They're the\n * fastest way to add monitoring to your agents during development and production.\n *\n * ## Available Presets\n *\n * - **logging(options?)** - Log LLM calls and gadget execution\n * - **timing()** - Measure execution time for operations\n * - **tokenTracking()** - Track cumulative token usage and costs\n * - **progressTracking(options?)** - Track progress with iterations, tokens, cost, and timing (SHOWCASE)\n * - **errorLogging()** - Log detailed error information\n * - **silent()** - No output (useful for testing)\n * - **monitoring(options?)** - All-in-one preset combining logging, timing, tokens, and errors\n * - **merge(...hookSets)** - Combine multiple hook configurations\n *\n * ## Quick Start\n *\n * @example\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * // Basic logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging())\n * .ask(\"Your prompt\");\n *\n * // Full monitoring suite (recommended for development)\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring({ verbose: true }))\n * .ask(\"Your prompt\");\n *\n * // Combine multiple presets\n * await LLMist.createAgent()\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * .ask(\"Your prompt\");\n *\n * // Environment-based configuration\n * const hooks = process.env.NODE_ENV === 'production'\n * ? HookPresets.merge(HookPresets.errorLogging(), HookPresets.tokenTracking())\n * : HookPresets.monitoring({ verbose: true });\n *\n * await LLMist.createAgent()\n * .withHooks(hooks)\n * .ask(\"Your prompt\");\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md | Full documentation}\n */\n\nimport type { AgentHooks } from \"./hooks.js\";\nimport type { ModelRegistry } from \"../core/model-registry.js\";\n\n/**\n * Options for logging preset.\n */\nexport interface LoggingOptions {\n /** Include verbose details like parameters and results */\n verbose?: boolean;\n}\n\n/**\n * Progress statistics reported by progressTracking preset.\n *\n * Contains cumulative metrics across all LLM calls in the agent session,\n * useful for building progress UI, cost monitoring, and performance tracking.\n */\nexport interface ProgressStats {\n /** Current iteration number (increments on each LLM call start) */\n currentIteration: number;\n\n /** Total number of completed LLM calls */\n totalCalls: number;\n\n /** Cumulative input tokens across all calls */\n totalInputTokens: number;\n\n /** Cumulative output tokens across all calls */\n totalOutputTokens: number;\n\n /** Total tokens (input + output) */\n totalTokens: number;\n\n /** Cumulative cost in USD (requires modelRegistry) */\n totalCost: number;\n\n /** Elapsed time in seconds since first call */\n elapsedSeconds: number;\n}\n\n/**\n * Options for progressTracking preset.\n *\n * Controls how progress data is tracked and reported during agent execution.\n */\nexport interface ProgressTrackingOptions {\n /**\n * Model registry for cost calculation.\n *\n * If provided, enables automatic cost estimation based on token usage\n * and model pricing data. Without it, totalCost will always be 0.\n *\n * @example\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * const client = LLMist.create();\n * const hooks = HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry // Enable cost tracking\n * });\n * ```\n */\n modelRegistry?: ModelRegistry;\n\n /**\n * Callback invoked after each LLM call completion with cumulative stats.\n *\n * Use this to update progress UI, log metrics, or track budgets in real-time.\n *\n * @example\n * ```typescript\n * HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * console.log(`Iteration #${stats.currentIteration}`);\n * console.log(`Cost so far: $${stats.totalCost.toFixed(4)}`);\n * console.log(`Elapsed: ${stats.elapsedSeconds}s`);\n * }\n * })\n * ```\n */\n onProgress?: (stats: ProgressStats) => void;\n\n /**\n * Whether to log progress to console after each LLM call.\n *\n * When enabled, prints a summary line with tokens, cost, and elapsed time.\n * Useful for quick debugging without implementing a custom callback.\n *\n * Default: false\n *\n * @example\n * ```typescript\n * // Quick console-based progress tracking\n * HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * logProgress: true // Log to console\n * })\n * // Output: 📊 Progress: Iteration #2 | 1,234 tokens | $0.0056 | 12.3s\n * ```\n */\n logProgress?: boolean;\n}\n\n/**\n * Common hook presets.\n */\nexport class HookPresets {\n /**\n * Logs LLM calls and gadget execution to console with optional verbosity.\n *\n * **Output (basic mode):**\n * - LLM call start/complete events with iteration numbers\n * - Gadget execution start/complete with gadget names\n * - Token counts when available\n *\n * **Output (verbose mode):**\n * - All basic mode output\n * - Full gadget parameters (formatted JSON)\n * - Full gadget results\n * - Complete LLM response text\n *\n * **Use cases:**\n * - Basic development debugging and execution flow visibility\n * - Understanding agent decision-making and tool usage\n * - Troubleshooting gadget invocations\n *\n * **Performance:** Minimal overhead. Console writes are synchronous but fast.\n *\n * @param options - Logging options\n * @param options.verbose - Include full parameters and results. Default: false\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging())\n * .ask(\"Calculate 15 * 23\");\n * // Output: [LLM] Starting call (iteration 0)\n * // [GADGET] Executing Calculator\n * // [GADGET] Completed Calculator\n * // [LLM] Completed (tokens: 245)\n * ```\n *\n * @example\n * ```typescript\n * // Verbose logging with full details\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging({ verbose: true }))\n * .ask(\"Calculate 15 * 23\");\n * // Output includes: parameters, results, and full responses\n * ```\n *\n * @example\n * ```typescript\n * // Environment-based verbosity\n * const isDev = process.env.NODE_ENV === 'development';\n * .withHooks(HookPresets.logging({ verbose: isDev }))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsloggingoptions | Full documentation}\n */\n static logging(options: LoggingOptions = {}): AgentHooks {\n return {\n observers: {\n onLLMCallStart: async (ctx) => {\n console.log(`[LLM] Starting call (iteration ${ctx.iteration})`);\n },\n onLLMCallComplete: async (ctx) => {\n const tokens = ctx.usage?.totalTokens ?? \"unknown\";\n console.log(`[LLM] Completed (tokens: ${tokens})`);\n if (options.verbose && ctx.finalMessage) {\n console.log(`[LLM] Response: ${ctx.finalMessage}`);\n }\n },\n onGadgetExecutionStart: async (ctx) => {\n console.log(`[GADGET] Executing ${ctx.gadgetName}`);\n if (options.verbose) {\n console.log(`[GADGET] Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n }\n },\n onGadgetExecutionComplete: async (ctx) => {\n console.log(`[GADGET] Completed ${ctx.gadgetName}`);\n if (options.verbose) {\n const display = ctx.error ?? ctx.finalResult ?? \"(no result)\";\n console.log(`[GADGET] Result: ${display}`);\n }\n },\n },\n };\n }\n\n /**\n * Measures and logs execution time for LLM calls and gadgets.\n *\n * **Output:**\n * - Duration in milliseconds with ⏱️ emoji for each operation\n * - Separate timing for each LLM iteration\n * - Separate timing for each gadget execution\n *\n * **Use cases:**\n * - Performance profiling and optimization\n * - Identifying slow operations (LLM calls vs gadget execution)\n * - Monitoring response times in production\n * - Capacity planning and SLA tracking\n *\n * **Performance:** Negligible overhead. Uses Date.now() for timing measurements.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic timing\n * await LLMist.createAgent()\n * .withHooks(HookPresets.timing())\n * .withGadgets(Weather, Database)\n * .ask(\"What's the weather in NYC?\");\n * // Output: ⏱️ LLM call took 1234ms\n * // ⏱️ Gadget Weather took 567ms\n * // ⏱️ LLM call took 890ms\n * ```\n *\n * @example\n * ```typescript\n * // Combined with logging for full context\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing()\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Correlate performance with cost\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstiming | Full documentation}\n */\n static timing(): AgentHooks {\n const timings = new Map<string, number>();\n\n return {\n observers: {\n onLLMCallStart: async (ctx) => {\n timings.set(`llm-${ctx.iteration}`, Date.now());\n },\n onLLMCallComplete: async (ctx) => {\n const start = timings.get(`llm-${ctx.iteration}`);\n if (start) {\n const duration = Date.now() - start;\n console.log(`⏱️ LLM call took ${duration}ms`);\n timings.delete(`llm-${ctx.iteration}`);\n }\n },\n onGadgetExecutionStart: async (ctx) => {\n const key = `gadget-${ctx.gadgetName}-${Date.now()}`;\n timings.set(key, Date.now());\n // Store key for lookup in complete handler\n (ctx as any)._timingKey = key;\n },\n onGadgetExecutionComplete: async (ctx) => {\n const key = (ctx as any)._timingKey;\n if (key) {\n const start = timings.get(key);\n if (start) {\n const duration = Date.now() - start;\n console.log(`⏱️ Gadget ${ctx.gadgetName} took ${duration}ms`);\n timings.delete(key);\n }\n }\n },\n },\n };\n }\n\n /**\n * Tracks cumulative token usage across all LLM calls.\n *\n * **Output:**\n * - Per-call token count with 📊 emoji\n * - Cumulative total across all calls\n * - Call count for average calculations\n *\n * **Use cases:**\n * - Cost monitoring and budget tracking\n * - Optimizing prompts to reduce token usage\n * - Comparing token efficiency across different approaches\n * - Real-time cost estimation\n *\n * **Performance:** Minimal overhead. Simple counter increments.\n *\n * **Note:** Token counts depend on the provider's response. Some providers\n * may not include usage data, in which case counts won't be logged.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic token tracking\n * await LLMist.createAgent()\n * .withHooks(HookPresets.tokenTracking())\n * .ask(\"Summarize this document...\");\n * // Output: 📊 Tokens this call: 1,234\n * // 📊 Total tokens: 1,234 (across 1 calls)\n * // 📊 Tokens this call: 567\n * // 📊 Total tokens: 1,801 (across 2 calls)\n * ```\n *\n * @example\n * ```typescript\n * // Cost calculation with custom hook\n * let totalTokens = 0;\n * .withHooks(HookPresets.merge(\n * HookPresets.tokenTracking(),\n * {\n * observers: {\n * onLLMCallComplete: async (ctx) => {\n * totalTokens += ctx.usage?.totalTokens ?? 0;\n * const cost = (totalTokens / 1_000_000) * 3.0; // $3 per 1M tokens\n * console.log(`💰 Estimated cost: $${cost.toFixed(4)}`);\n * },\n * },\n * }\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstokentracking | Full documentation}\n */\n static tokenTracking(): AgentHooks {\n let totalTokens = 0;\n let totalCalls = 0;\n\n return {\n observers: {\n onLLMCallComplete: async (ctx) => {\n totalCalls++;\n if (ctx.usage?.totalTokens) {\n totalTokens += ctx.usage.totalTokens;\n console.log(`📊 Tokens this call: ${ctx.usage.totalTokens}`);\n console.log(`📊 Total tokens: ${totalTokens} (across ${totalCalls} calls)`);\n }\n },\n },\n };\n }\n\n /**\n * Tracks comprehensive progress metrics including iterations, tokens, cost, and timing.\n *\n * **This preset showcases llmist's core capabilities by demonstrating:**\n * - Observer pattern for non-intrusive monitoring\n * - Integration with ModelRegistry for cost estimation\n * - Callback-based architecture for flexible UI updates\n * - Provider-agnostic token and cost tracking\n *\n * Unlike `tokenTracking()` which only logs to console, this preset provides\n * structured data through callbacks, making it perfect for building custom UIs,\n * dashboards, or progress indicators (like the llmist CLI).\n *\n * **Output (when logProgress: true):**\n * - Iteration number and call count\n * - Cumulative token usage (input + output)\n * - Cumulative cost in USD (requires modelRegistry)\n * - Elapsed time in seconds\n *\n * **Use cases:**\n * - Building CLI progress indicators with live updates\n * - Creating web dashboards with real-time metrics\n * - Budget monitoring and cost alerts\n * - Performance tracking and optimization\n * - Custom logging to external systems (Datadog, CloudWatch, etc.)\n *\n * **Performance:** Minimal overhead. Uses Date.now() for timing and optional\n * ModelRegistry.estimateCost() which is O(1) lookup. Callback invocation is\n * synchronous and fast.\n *\n * @param options - Progress tracking options\n * @param options.modelRegistry - ModelRegistry for cost estimation (optional)\n * @param options.onProgress - Callback invoked after each LLM call (optional)\n * @param options.logProgress - Log progress to console (default: false)\n * @returns Hook configuration with progress tracking observers\n *\n * @example\n * ```typescript\n * // Basic usage with callback (RECOMMENDED - used by llmist CLI)\n * import { LLMist, HookPresets } from 'llmist';\n *\n * const client = LLMist.create();\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * // Update your UI with stats\n * console.log(`#${stats.currentIteration} | ${stats.totalTokens} tokens | $${stats.totalCost.toFixed(4)}`);\n * }\n * }))\n * .withGadgets(Calculator)\n * .ask(\"Calculate 15 * 23\");\n * // Output: #1 | 245 tokens | $0.0012\n * ```\n *\n * @example\n * ```typescript\n * // Console logging mode (quick debugging)\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * logProgress: true // Simple console output\n * }))\n * .ask(\"Your prompt\");\n * // Output: 📊 Progress: Iteration #1 | 245 tokens | $0.0012 | 1.2s\n * ```\n *\n * @example\n * ```typescript\n * // Budget monitoring with alerts\n * const BUDGET_USD = 0.10;\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * if (stats.totalCost > BUDGET_USD) {\n * throw new Error(`Budget exceeded: $${stats.totalCost.toFixed(4)}`);\n * }\n * }\n * }))\n * .ask(\"Long running task...\");\n * ```\n *\n * @example\n * ```typescript\n * // Web dashboard integration\n * let progressBar: HTMLElement;\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * // Update web UI in real-time\n * progressBar.textContent = `Iteration ${stats.currentIteration}`;\n * progressBar.dataset.cost = stats.totalCost.toFixed(4);\n * progressBar.dataset.tokens = stats.totalTokens.toString();\n * }\n * }))\n * .ask(\"Your prompt\");\n * ```\n *\n * @example\n * ```typescript\n * // External logging (Datadog, CloudWatch, etc.)\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: async (stats) => {\n * await metrics.gauge('llm.iteration', stats.currentIteration);\n * await metrics.gauge('llm.cost', stats.totalCost);\n * await metrics.gauge('llm.tokens', stats.totalTokens);\n * }\n * }))\n * .ask(\"Your prompt\");\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsprogresstrackingoptions | Full documentation}\n * @see {@link ProgressTrackingOptions} for detailed options\n * @see {@link ProgressStats} for the callback data structure\n */\n static progressTracking(options?: ProgressTrackingOptions): AgentHooks {\n const { modelRegistry, onProgress, logProgress = false } = options ?? {};\n\n // State tracking - follows same pattern as tokenTracking()\n let totalCalls = 0;\n let currentIteration = 0;\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCost = 0;\n const startTime = Date.now();\n\n return {\n observers: {\n // Track iteration on each LLM call start\n onLLMCallStart: async (ctx) => {\n currentIteration++;\n },\n\n // Accumulate metrics and report progress on each LLM call completion\n onLLMCallComplete: async (ctx) => {\n totalCalls++;\n\n // Track token usage from provider response\n if (ctx.usage) {\n totalInputTokens += ctx.usage.inputTokens;\n totalOutputTokens += ctx.usage.outputTokens;\n\n // Calculate cost using ModelRegistry (core llmist feature)\n // This showcases integration with llmist's pricing catalog\n if (modelRegistry) {\n try {\n // Extract model name from provider:model format\n // Example: \"openai:gpt-4o\" -> \"gpt-4o\"\n const modelName = ctx.options.model.includes(\":\")\n ? ctx.options.model.split(\":\")[1]\n : ctx.options.model;\n\n // Use core's estimateCost() for accurate pricing\n const costEstimate = modelRegistry.estimateCost(\n modelName,\n ctx.usage.inputTokens,\n ctx.usage.outputTokens,\n );\n\n if (costEstimate) {\n totalCost += costEstimate.totalCost;\n }\n } catch (error) {\n // Graceful degradation - log error but don't crash\n // This follows llmist's principle of non-intrusive monitoring\n if (logProgress) {\n console.warn(`⚠️ Cost estimation failed:`, error);\n }\n }\n }\n }\n\n // Build comprehensive progress stats\n const stats: ProgressStats = {\n currentIteration,\n totalCalls,\n totalInputTokens,\n totalOutputTokens,\n totalTokens: totalInputTokens + totalOutputTokens,\n totalCost,\n elapsedSeconds: Number(((Date.now() - startTime) / 1000).toFixed(1)),\n };\n\n // Invoke callback if provided (used by CLI and custom UIs)\n if (onProgress) {\n onProgress(stats);\n }\n\n // Optional console logging for quick debugging\n if (logProgress) {\n const formattedTokens = stats.totalTokens >= 1000\n ? `${(stats.totalTokens / 1000).toFixed(1)}k`\n : `${stats.totalTokens}`;\n\n const formattedCost = stats.totalCost > 0\n ? `$${stats.totalCost.toFixed(4)}`\n : \"$0\";\n\n console.log(\n `📊 Progress: Iteration #${stats.currentIteration} | ${formattedTokens} tokens | ${formattedCost} | ${stats.elapsedSeconds}s`,\n );\n }\n },\n },\n };\n }\n\n /**\n * Logs detailed error information for debugging and troubleshooting.\n *\n * **Output:**\n * - LLM errors with ❌ emoji, including model and recovery status\n * - Gadget errors with full context (parameters, error message)\n * - Separate logging for LLM and gadget failures\n *\n * **Use cases:**\n * - Troubleshooting production issues\n * - Understanding error patterns and frequency\n * - Debugging error recovery behavior\n * - Collecting error metrics for monitoring\n *\n * **Performance:** Minimal overhead. Only logs when errors occur.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic error logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.errorLogging())\n * .withGadgets(Database)\n * .ask(\"Fetch user data\");\n * // Output (on LLM error): ❌ LLM Error (iteration 1): Rate limit exceeded\n * // Model: gpt-5-nano\n * // Recovered: true\n * // Output (on gadget error): ❌ Gadget Error: Database\n * // Error: Connection timeout\n * // Parameters: {...}\n * ```\n *\n * @example\n * ```typescript\n * // Combine with monitoring for full context\n * .withHooks(HookPresets.merge(\n * HookPresets.monitoring(), // Includes errorLogging\n * customErrorAnalytics\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Error analytics collection\n * const errors: any[] = [];\n * .withHooks(HookPresets.merge(\n * HookPresets.errorLogging(),\n * {\n * observers: {\n * onLLMCallError: async (ctx) => {\n * errors.push({ type: 'llm', error: ctx.error, recovered: ctx.recovered });\n * },\n * },\n * }\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetserrorlogging | Full documentation}\n */\n static errorLogging(): AgentHooks {\n return {\n observers: {\n onLLMCallError: async (ctx) => {\n console.error(`❌ LLM Error (iteration ${ctx.iteration}):`, ctx.error.message);\n console.error(` Model: ${ctx.options.model}`);\n console.error(` Recovered: ${ctx.recovered}`);\n },\n onGadgetExecutionComplete: async (ctx) => {\n if (ctx.error) {\n console.error(`❌ Gadget Error: ${ctx.gadgetName}`);\n console.error(` Error: ${ctx.error}`);\n console.error(` Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n }\n },\n },\n };\n }\n\n /**\n * Returns empty hook configuration for clean output without any logging.\n *\n * **Output:**\n * - None. Returns {} (empty object).\n *\n * **Use cases:**\n * - Clean test output without console noise\n * - Production environments where logging is handled externally\n * - Baseline for custom hook development\n * - Temporary disable of all hook output\n *\n * **Performance:** Zero overhead. No-op hook configuration.\n *\n * @returns Empty hook configuration\n *\n * @example\n * ```typescript\n * // Clean test output\n * describe('Agent tests', () => {\n * it('should calculate correctly', async () => {\n * const result = await LLMist.createAgent()\n * .withHooks(HookPresets.silent()) // No console output\n * .withGadgets(Calculator)\n * .askAndCollect(\"What is 15 times 23?\");\n *\n * expect(result).toContain(\"345\");\n * });\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Conditional silence based on environment\n * const isTesting = process.env.NODE_ENV === 'test';\n * .withHooks(isTesting ? HookPresets.silent() : HookPresets.monitoring())\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetssilent | Full documentation}\n */\n static silent(): AgentHooks {\n return {};\n }\n\n /**\n * Combines multiple hook configurations into one.\n *\n * Merge allows you to compose preset and custom hooks for modular monitoring\n * configurations. Understanding merge behavior is crucial for proper composition.\n *\n * **Merge behavior:**\n * - **Observers:** Composed - all handlers run sequentially in order\n * - **Interceptors:** Last one wins - only the last interceptor applies\n * - **Controllers:** Last one wins - only the last controller applies\n *\n * **Why interceptors/controllers don't compose:**\n * - Interceptors have different signatures per method, making composition impractical\n * - Controllers return specific actions that can't be meaningfully combined\n * - Only observers support composition because they're read-only and independent\n *\n * **Use cases:**\n * - Combining multiple presets (logging + timing + tokens)\n * - Adding custom hooks to presets\n * - Building modular, reusable monitoring configurations\n * - Environment-specific hook composition\n *\n * **Performance:** Minimal overhead for merging. Runtime performance depends on merged hooks.\n *\n * @param hookSets - Variable number of hook configurations to merge\n * @returns Single merged hook configuration with composed/overridden handlers\n *\n * @example\n * ```typescript\n * // Combine multiple presets\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * // All observers from all three presets will run\n * ```\n *\n * @example\n * ```typescript\n * // Add custom observer to preset (both run)\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * {\n * observers: {\n * onLLMCallComplete: async (ctx) => {\n * await saveMetrics({ tokens: ctx.usage?.totalTokens });\n * },\n * },\n * }\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Multiple interceptors (last wins!)\n * .withHooks(HookPresets.merge(\n * {\n * interceptors: {\n * interceptTextChunk: (chunk) => chunk.toUpperCase(), // Ignored\n * },\n * },\n * {\n * interceptors: {\n * interceptTextChunk: (chunk) => chunk.toLowerCase(), // This wins\n * },\n * }\n * ))\n * // Result: text will be lowercase\n * ```\n *\n * @example\n * ```typescript\n * // Modular environment-based configuration\n * const baseHooks = HookPresets.errorLogging();\n * const devHooks = HookPresets.merge(baseHooks, HookPresets.monitoring({ verbose: true }));\n * const prodHooks = HookPresets.merge(baseHooks, HookPresets.tokenTracking());\n *\n * const hooks = process.env.NODE_ENV === 'production' ? prodHooks : devHooks;\n * .withHooks(hooks)\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmergehooksets | Full documentation}\n */\n static merge(...hookSets: AgentHooks[]): AgentHooks {\n const merged: AgentHooks = {\n observers: {},\n interceptors: {},\n controllers: {},\n };\n\n // Compose observers: run all handlers for the same event\n for (const hooks of hookSets) {\n if (hooks.observers) {\n for (const [key, handler] of Object.entries(hooks.observers)) {\n const typedKey = key as keyof typeof hooks.observers;\n if (merged.observers![typedKey]) {\n // Compose: run both existing and new handler\n const existing = merged.observers![typedKey];\n merged.observers![typedKey] = async (ctx: any) => {\n await existing(ctx);\n await handler(ctx);\n };\n } else {\n merged.observers![typedKey] = handler as any;\n }\n }\n }\n\n // Interceptors: last one wins (complex signatures make composition impractical)\n // Each interceptor has different parameters (chunk, message, parameters, etc.)\n // so we can't meaningfully compose them like we do with observers\n if (hooks.interceptors) {\n Object.assign(merged.interceptors!, hooks.interceptors);\n }\n\n // Controllers: last one wins (can't meaningfully compose boolean returns)\n if (hooks.controllers) {\n Object.assign(merged.controllers!, hooks.controllers);\n }\n }\n\n return merged;\n }\n\n /**\n * Composite preset combining logging, timing, tokenTracking, and errorLogging.\n *\n * This is the recommended preset for development and initial production deployments,\n * providing comprehensive observability with a single method call.\n *\n * **Includes:**\n * - All output from `logging()` preset (with optional verbosity)\n * - All output from `timing()` preset (execution times)\n * - All output from `tokenTracking()` preset (token usage)\n * - All output from `errorLogging()` preset (error details)\n *\n * **Output format:**\n * - Event logging: [LLM]/[GADGET] messages\n * - Timing: ⏱️ emoji with milliseconds\n * - Tokens: 📊 emoji with per-call and cumulative counts\n * - Errors: ❌ emoji with full error details\n *\n * **Use cases:**\n * - Full observability during development\n * - Comprehensive monitoring in production\n * - One-liner for complete agent visibility\n * - Troubleshooting and debugging with full context\n *\n * **Performance:** Combined overhead of all four presets, but still minimal in practice.\n *\n * @param options - Monitoring options\n * @param options.verbose - Passed to logging() preset for detailed output. Default: false\n * @returns Merged hook configuration combining all monitoring presets\n *\n * @example\n * ```typescript\n * // Basic monitoring (recommended for development)\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring())\n * .withGadgets(Calculator, Weather)\n * .ask(\"What is 15 times 23, and what's the weather in NYC?\");\n * // Output: All events, timing, tokens, and errors in one place\n * ```\n *\n * @example\n * ```typescript\n * // Verbose monitoring with full details\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring({ verbose: true }))\n * .ask(\"Your prompt\");\n * // Output includes: parameters, results, and complete responses\n * ```\n *\n * @example\n * ```typescript\n * // Environment-based monitoring\n * const isDev = process.env.NODE_ENV === 'development';\n * .withHooks(HookPresets.monitoring({ verbose: isDev }))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmonitoringoptions | Full documentation}\n */\n static monitoring(options: LoggingOptions = {}): AgentHooks {\n return HookPresets.merge(\n HookPresets.logging(options),\n HookPresets.timing(),\n HookPresets.tokenTracking(),\n HookPresets.errorLogging(),\n );\n }\n}\n","/**\n * Agent module - Composable, single-responsibility architecture for LLM agents.\n * This module provides a cleaner alternative to the monolithic AgentLoop.\n */\n\nexport type { AgentOptions } from \"./agent.js\";\nexport { ConversationManager } from \"./conversation-manager.js\";\n// New clean hooks system\nexport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n // Interceptor contexts\n ChunkInterceptorContext,\n Controllers,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n Interceptors,\n // Controller contexts and actions\n LLMCallControllerContext,\n LLMErrorControllerContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetStartContext,\n // Observer contexts\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n Observers,\n} from \"./hooks.js\";\nexport type { IConversationManager } from \"./interfaces.js\";\n\n// StreamProcessor for advanced use cases\nexport {\n type StreamProcessingResult,\n StreamProcessor,\n type StreamProcessorOptions,\n} from \"./stream-processor.js\";\n\n// Gadget output limiting\nexport type { StoredOutput } from \"./gadget-output-store.js\";\nexport { GadgetOutputStore } from \"./gadget-output-store.js\";\n","/**\n * Type-safe gadget factory with automatic parameter inference.\n *\n * Gadget eliminates the need for manual type assertions\n * by automatically inferring parameter types from the Zod schema.\n *\n * @example\n * ```typescript\n * class Calculator extends Gadget({\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 * }) {\n * // ✨ params is automatically typed!\n * execute(params: this['params']): string {\n * const { operation, a, b } = params; // All 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 typed gadget.\n */\nexport interface GadgetConfig<TSchema extends ZodType> {\n /** Human-readable description of what the gadget does */\n description: string;\n\n /** Zod schema for parameter validation */\n schema: TSchema;\n\n /** Optional custom name (defaults to class name) */\n name?: 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 * Factory function to create a typed gadget base class.\n *\n * The returned class automatically infers parameter types from the Zod schema,\n * eliminating the need for manual type assertions in the execute method.\n *\n * @param config - Configuration with description and schema\n * @returns Base class to extend with typed execute method\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { Gadget } from 'llmist';\n *\n * class Calculator extends Gadget({\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 * }) {\n * execute(params: this['params']): string {\n * // params is automatically typed as:\n * // { operation: \"add\" | \"subtract\" | \"multiply\" | \"divide\"; a: number; b: number }\n * const { operation, a, b } = params;\n *\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 * // With async execution\n * class WeatherGadget extends Gadget({\n * description: \"Fetches weather for a city\",\n * schema: z.object({\n * city: z.string().min(1).describe(\"City name\"),\n * }),\n * timeoutMs: 10000,\n * }) {\n * async execute(params: this['params']): Promise<string> {\n * const { city } = params; // Automatically typed as { city: string }\n * const weather = await fetchWeather(city);\n * return `Weather in ${city}: ${weather}`;\n * }\n * }\n * ```\n */\nexport function Gadget<TSchema extends ZodType>(config: GadgetConfig<TSchema>) {\n abstract class GadgetBase extends BaseGadget {\n description = config.description;\n parameterSchema = config.schema;\n name = config.name;\n timeoutMs = config.timeoutMs;\n examples = config.examples;\n\n /**\n * Type helper property for accessing inferred parameter type.\n * This is used in the execute method signature: `execute(params: this['params'])`\n *\n * Note: This is just for type inference - the actual params in execute()\n * will be Record<string, unknown> which you can safely cast to this['params']\n */\n readonly params!: InferSchema<TSchema>;\n\n /**\n * Execute the gadget. Subclasses should cast params to this['params'].\n *\n * @param params - Validated parameters from the LLM\n * @returns Result as a string (or Promise<string> for async gadgets)\n *\n * @example\n * ```typescript\n * execute(params: Record<string, unknown>): string {\n * const typed = params as this['params'];\n * // Now 'typed' is fully typed!\n * return String(typed.a + typed.b);\n * }\n * ```\n */\n abstract execute(params: Record<string, unknown>): string | Promise<string>;\n }\n\n return GadgetBase as {\n new (): GadgetBase & { params: InferSchema<TSchema> };\n };\n}\n","/**\n * Validation utilities for gadget parameters.\n *\n * Provides standalone validation with Zod schema support, including\n * default application and formatted error output.\n *\n * @module gadgets/validation\n */\n\nimport type { ZodTypeAny } from \"zod\";\nimport type { BaseGadget } from \"./gadget.js\";\n\n/**\n * Individual validation issue with path and message.\n */\nexport interface ValidationIssue {\n /** Dot-separated path to the invalid field (e.g., \"user.email\") */\n path: string;\n /** Human-readable error message */\n message: string;\n}\n\n/**\n * Result of parameter validation.\n * Discriminated union based on `success` field.\n */\nexport type ValidationResult<T = Record<string, unknown>> =\n | {\n success: true;\n /** Validated and transformed data with defaults applied */\n data: T;\n }\n | {\n success: false;\n /** Formatted error message */\n error: string;\n /** Individual validation issues */\n issues: ValidationIssue[];\n };\n\n/**\n * Validate parameters against a Zod schema and apply defaults/transformations.\n *\n * This replicates the validation behavior from GadgetExecutor, making it\n * available for direct use in tests and other contexts.\n *\n * @param schema - Zod schema to validate against\n * @param params - Raw parameters to validate\n * @returns ValidationResult with either validated data or error details\n *\n * @example\n * ```typescript\n * import { validateAndApplyDefaults } from 'llmist';\n * import { z } from 'zod';\n *\n * const schema = z.object({\n * delay: z.number().default(100),\n * retries: z.number().int().min(0).default(3),\n * });\n *\n * const result = validateAndApplyDefaults(schema, { delay: 50 });\n * if (result.success) {\n * console.log(result.data); // { delay: 50, retries: 3 }\n * }\n * ```\n */\nexport function validateAndApplyDefaults<T = Record<string, unknown>>(\n schema: ZodTypeAny,\n params: Record<string, unknown>,\n): ValidationResult<T> {\n const result = schema.safeParse(params);\n\n if (result.success) {\n return {\n success: true,\n data: result.data as T,\n };\n }\n\n const issues: ValidationIssue[] = result.error.issues.map((issue) => ({\n path: issue.path.join(\".\") || \"root\",\n message: issue.message,\n }));\n\n const formattedError = `Invalid parameters: ${issues.map((i) => `${i.path}: ${i.message}`).join(\"; \")}`;\n\n return {\n success: false,\n error: formattedError,\n issues,\n };\n}\n\n/**\n * Validate gadget parameters using the gadget's schema.\n *\n * Convenience wrapper that extracts the schema from a gadget instance.\n * If the gadget has no schema, validation always succeeds with the\n * original parameters.\n *\n * @param gadget - Gadget instance with optional parameterSchema\n * @param params - Raw parameters to validate\n * @returns ValidationResult with either validated data or error details\n *\n * @example\n * ```typescript\n * import { validateGadgetParams, createGadget } from 'llmist';\n * import { z } from 'zod';\n *\n * const calculator = createGadget({\n * description: 'Add numbers',\n * schema: z.object({\n * a: z.number(),\n * b: z.number().default(0),\n * }),\n * execute: ({ a, b }) => String(a + b),\n * });\n *\n * const result = validateGadgetParams(calculator, { a: 5 });\n * if (result.success) {\n * console.log(result.data); // { a: 5, b: 0 }\n * }\n * ```\n */\nexport function validateGadgetParams(\n gadget: BaseGadget,\n params: Record<string, unknown>,\n): ValidationResult {\n if (!gadget.parameterSchema) {\n return {\n success: true,\n data: params,\n };\n }\n\n return validateAndApplyDefaults(gadget.parameterSchema, params);\n}\n","import type { ILogObj, Logger } from \"tslog\";\nimport { createLogger } from \"../logging/logger.js\";\nimport type {\n MockMatcherContext,\n MockOptions,\n MockRegistration,\n MockResponse,\n MockStats,\n} from \"./mock-types.js\";\n\n/**\n * Global singleton instance for managing LLM mocks.\n * This allows mocks to be registered once and used across the application.\n */\nexport class MockManager {\n private static instance: MockManager | null = null;\n private mocks: Map<string, MockRegistration> = new Map();\n private stats: Map<string, MockStats> = new Map();\n private options: Required<MockOptions>;\n private logger: Logger<ILogObj>;\n private nextId = 1;\n\n private constructor(options: MockOptions = {}) {\n this.options = {\n strictMode: options.strictMode ?? false,\n debug: options.debug ?? false,\n recordStats: options.recordStats ?? true,\n };\n this.logger = createLogger({ name: \"MockManager\", minLevel: this.options.debug ? 2 : 3 });\n }\n\n /**\n * Get the global MockManager instance.\n * Creates one if it doesn't exist.\n */\n static getInstance(options?: MockOptions): MockManager {\n if (!MockManager.instance) {\n MockManager.instance = new MockManager(options);\n } else if (options) {\n // Warn if options are provided after initialization\n console.warn(\n \"MockManager.getInstance() called with options, but instance already exists. \" +\n \"Options are ignored. Use setOptions() to update options or reset() to reinitialize.\",\n );\n }\n return MockManager.instance;\n }\n\n /**\n * Reset the global instance (useful for testing).\n */\n static reset(): void {\n MockManager.instance = null;\n }\n\n /**\n * Register a new mock.\n *\n * @param registration - The mock registration configuration\n * @returns The ID of the registered mock\n *\n * @example\n * const manager = MockManager.getInstance();\n * const mockId = manager.register({\n * label: 'GPT-4 mock',\n * matcher: (ctx) => ctx.modelName.includes('gpt-4'),\n * response: { text: 'Mocked response' }\n * });\n */\n register(registration: Omit<MockRegistration, \"id\"> & { id?: string }): string {\n const id = registration.id ?? `mock-${this.nextId++}`;\n const mock: MockRegistration = {\n id,\n matcher: registration.matcher,\n response: registration.response,\n label: registration.label,\n once: registration.once,\n };\n\n this.mocks.set(id, mock);\n\n if (this.options.recordStats) {\n this.stats.set(id, { matchCount: 0 });\n }\n\n this.logger.debug(\n `Registered mock: ${id}${mock.label ? ` (${mock.label})` : \"\"}${mock.once ? \" [once]\" : \"\"}`,\n );\n\n return id;\n }\n\n /**\n * Unregister a mock by ID.\n */\n unregister(id: string): boolean {\n const deleted = this.mocks.delete(id);\n if (deleted) {\n this.stats.delete(id);\n this.logger.debug(`Unregistered mock: ${id}`);\n }\n return deleted;\n }\n\n /**\n * Clear all registered mocks.\n */\n clear(): void {\n this.mocks.clear();\n this.stats.clear();\n this.logger.debug(\"Cleared all mocks\");\n }\n\n /**\n * Find and return a matching mock for the given context.\n * Returns the mock response if found, null otherwise.\n */\n async findMatch(context: MockMatcherContext): Promise<MockResponse | null> {\n this.logger.debug(\n `Finding match for: ${context.provider}:${context.modelName} (${this.mocks.size} mocks registered)`,\n );\n\n for (const [id, mock] of this.mocks.entries()) {\n let matches = false;\n\n try {\n matches = await Promise.resolve(mock.matcher(context));\n } catch (error) {\n // Matcher errors are caught - a matcher that throws simply doesn't match\n this.logger.warn(`Error in matcher ${id}:`, error);\n // In strict mode, re-throw matcher errors to help catch bugs\n if (this.options.strictMode) {\n throw new Error(`Matcher error in mock ${id}: ${error}`);\n }\n continue; // Skip to next mock\n }\n\n if (matches) {\n this.logger.debug(`Mock matched: ${id}${mock.label ? ` (${mock.label})` : \"\"}`);\n\n // Record stats\n if (this.options.recordStats) {\n const stats = this.stats.get(id);\n if (stats) {\n stats.matchCount++;\n stats.lastUsed = new Date();\n }\n }\n\n // Remove if once\n if (mock.once) {\n this.mocks.delete(id);\n this.stats.delete(id);\n this.logger.debug(`Removed one-time mock: ${id}`);\n }\n\n // Resolve response (could be a function)\n // Response errors are NOT caught - they should propagate to the caller\n const response =\n typeof mock.response === \"function\"\n ? await Promise.resolve(mock.response(context))\n : mock.response;\n\n return response;\n }\n }\n\n // No match found\n this.logger.debug(\"No mock matched\");\n\n if (this.options.strictMode) {\n throw new Error(\n `No mock registered for ${context.provider}:${context.modelName}. ` +\n `Register a mock using MockManager.getInstance().register() or disable strictMode.`,\n );\n }\n\n // Return empty response in non-strict mode\n return {\n text: \"\",\n usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\n finishReason: \"stop\",\n };\n }\n\n /**\n * Get statistics for a specific mock.\n */\n getStats(id: string): MockStats | undefined {\n return this.stats.get(id);\n }\n\n /**\n * Get all registered mock IDs.\n */\n getMockIds(): string[] {\n return Array.from(this.mocks.keys());\n }\n\n /**\n * Get the number of registered mocks.\n */\n getCount(): number {\n return this.mocks.size;\n }\n\n /**\n * Update the mock manager options.\n */\n setOptions(options: Partial<MockOptions>): void {\n this.options = { ...this.options, ...options };\n this.logger = createLogger({ name: \"MockManager\", minLevel: this.options.debug ? 2 : 3 });\n }\n}\n\n/**\n * Helper function to get the global mock manager instance.\n */\nexport function getMockManager(options?: MockOptions): MockManager {\n return MockManager.getInstance(options);\n}\n","import { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { LLMStream, LLMStreamChunk } from \"../core/options.js\";\nimport type { MockResponse } from \"./mock-types.js\";\n\n/**\n * Utility to sleep for a given duration.\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Generate a unique invocation ID for gadget calls.\n */\nfunction generateInvocationId(): string {\n return `inv-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n}\n\n/**\n * Split text into chunks for streaming simulation.\n * Tries to split on word boundaries for more realistic streaming.\n */\nfunction splitIntoChunks(text: string, minChunkSize = 5, maxChunkSize = 30): string[] {\n const chunks: string[] = [];\n let remaining = text;\n\n while (remaining.length > 0) {\n // Determine chunk size\n const chunkSize = Math.min(\n Math.floor(Math.random() * (maxChunkSize - minChunkSize + 1)) + minChunkSize,\n remaining.length,\n );\n\n // Try to split on word boundary\n let chunk: string;\n if (chunkSize < remaining.length) {\n const substr = remaining.substring(0, chunkSize);\n const lastSpace = substr.lastIndexOf(\" \");\n if (lastSpace > minChunkSize / 2) {\n chunk = substr.substring(0, lastSpace + 1);\n } else {\n chunk = substr;\n }\n } else {\n chunk = remaining;\n }\n\n chunks.push(chunk);\n remaining = remaining.substring(chunk.length);\n }\n\n return chunks;\n}\n\n/**\n * Serialize an object to block format parameters with !!!ARG: markers.\n *\n * Example:\n * { operation: \"add\", a: 5, config: { timeout: 30 } }\n * becomes:\n * !!!ARG:operation\n * add\n * !!!ARG:a\n * 5\n * !!!ARG:config/timeout\n * 30\n */\nfunction serializeToBlockFormat(obj: Record<string, unknown>, prefix = \"\"): string {\n let result = \"\";\n\n for (const [key, value] of Object.entries(obj)) {\n const pointer = prefix ? `${prefix}/${key}` : key;\n\n if (value === null || value === undefined) {\n continue;\n }\n\n if (Array.isArray(value)) {\n // Serialize array elements with numeric indices\n for (let i = 0; i < value.length; i++) {\n const item = value[i];\n const itemPointer = `${pointer}/${i}`;\n\n if (typeof item === \"object\" && item !== null && !Array.isArray(item)) {\n // Nested object in array\n result += serializeToBlockFormat(item as Record<string, unknown>, itemPointer);\n } else if (Array.isArray(item)) {\n // Nested array - serialize recursively\n for (let j = 0; j < item.length; j++) {\n result += `${GADGET_ARG_PREFIX}${itemPointer}/${j}\\n${String(item[j])}\\n`;\n }\n } else {\n result += `${GADGET_ARG_PREFIX}${itemPointer}\\n${String(item)}\\n`;\n }\n }\n } else if (typeof value === \"object\") {\n // Nested object - recurse\n result += serializeToBlockFormat(value as Record<string, unknown>, pointer);\n } else {\n // Primitive value\n result += `${GADGET_ARG_PREFIX}${pointer}\\n${String(value)}\\n`;\n }\n }\n\n return result;\n}\n\n/**\n * Convert gadget calls in MockResponse to their text representation.\n * Formats them using block format: !!!GADGET_START:name\\n!!!ARG:...\\n!!!GADGET_END\n */\nfunction formatGadgetCalls(gadgetCalls: NonNullable<MockResponse[\"gadgetCalls\"]>): {\n text: string;\n calls: Array<{ name: string; invocationId: string }>;\n} {\n let text = \"\";\n const calls: Array<{ name: string; invocationId: string }> = [];\n\n for (const call of gadgetCalls) {\n const invocationId = call.invocationId ?? generateInvocationId();\n calls.push({ name: call.gadgetName, invocationId });\n\n // Format parameters using block format with !!!ARG: markers\n const blockParams = serializeToBlockFormat(call.parameters);\n\n // Format using the gadget marker format\n text += `\\n${GADGET_START_PREFIX}${call.gadgetName}\\n${blockParams}${GADGET_END_PREFIX}`;\n }\n\n return { text, calls };\n}\n\n/**\n * Create a mock LLM stream from a mock response.\n * This simulates the streaming behavior of real LLM providers.\n *\n * @param response - The mock response configuration\n * @returns An async iterable that yields LLMStreamChunks\n */\nexport async function* createMockStream(response: MockResponse): LLMStream {\n // Initial delay (simulate network latency)\n if (response.delayMs) {\n await sleep(response.delayMs);\n }\n\n const streamDelay = response.streamDelayMs ?? 0;\n let fullText = response.text ?? \"\";\n\n // Add gadget calls to the text if provided\n if (response.gadgetCalls && response.gadgetCalls.length > 0) {\n const { text: gadgetText } = formatGadgetCalls(response.gadgetCalls);\n fullText += gadgetText;\n }\n\n // Stream the text in chunks\n if (fullText.length > 0) {\n const chunks = streamDelay > 0 ? splitIntoChunks(fullText) : [fullText];\n\n for (let i = 0; i < chunks.length; i++) {\n const isLast = i === chunks.length - 1;\n\n const chunk: LLMStreamChunk = {\n text: chunks[i],\n };\n\n // Add finish reason and usage on the last chunk\n if (isLast) {\n if (response.finishReason !== undefined) {\n chunk.finishReason = response.finishReason;\n }\n if (response.usage) {\n chunk.usage = response.usage;\n }\n }\n\n yield chunk;\n\n // Delay between chunks\n if (streamDelay > 0 && !isLast) {\n await sleep(streamDelay);\n }\n }\n } else {\n // Empty response - still yield a final chunk with metadata\n yield {\n text: \"\",\n finishReason: response.finishReason ?? \"stop\",\n usage: response.usage ?? { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\n };\n }\n}\n\n/**\n * Create a simple text-only mock stream.\n * Convenience helper for quickly creating mock responses.\n *\n * @param text - The text to stream\n * @param options - Optional streaming configuration\n *\n * @example\n * const stream = createTextMockStream('Hello, world!');\n * for await (const chunk of stream) {\n * console.log(chunk.text);\n * }\n */\nexport function createTextMockStream(\n text: string,\n options?: {\n delayMs?: number;\n streamDelayMs?: number;\n usage?: MockResponse[\"usage\"];\n },\n): LLMStream {\n return createMockStream({\n text,\n delayMs: options?.delayMs,\n streamDelayMs: options?.streamDelayMs,\n usage: options?.usage,\n finishReason: \"stop\",\n });\n}\n","import type { LLMMessage } from \"../core/messages.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport { ModelIdentifierParser } from \"../core/options.js\";\nimport type { ProviderAdapter } from \"../providers/provider.js\";\nimport { getMockManager, type MockManager } from \"./mock-manager.js\";\nimport { createMockStream } from \"./mock-stream.js\";\nimport type { MockMatcherContext, MockOptions } from \"./mock-types.js\";\n\n/**\n * Provider adapter that serves mock responses instead of making real LLM API calls.\n * This is useful for testing applications that use llmist without incurring API costs.\n *\n * The MockProviderAdapter has high priority (100) and is always checked before\n * real providers when both are registered. This enables selective mocking where\n * some models use mocks while others use real providers. If no matching mock is\n * found and strictMode is disabled, requests return an empty response.\n *\n * @example\n * ```typescript\n * import { LLMist, createMockAdapter, mockLLM } from 'llmist/testing';\n *\n * // Use with real providers for selective mocking\n * const client = new LLMist({\n * adapters: [createMockAdapter()],\n * autoDiscoverProviders: true // Also loads real OpenAI, Anthropic, etc.\n * });\n *\n * // Register mocks for specific models\n * mockLLM()\n * .forModel('gpt-5-nano')\n * .returns('Test response')\n * .register();\n *\n * // gpt-5-nano uses mock, other models use real providers\n * const stream = client.stream({\n * model: 'openai:gpt-5-nano',\n * messages: [{ role: 'user', content: 'test' }]\n * });\n * ```\n */\nexport class MockProviderAdapter implements ProviderAdapter {\n readonly providerId = \"mock\";\n readonly priority = 100; // High priority: check mocks before real providers\n private readonly mockManager: MockManager;\n\n constructor(options?: MockOptions) {\n this.mockManager = getMockManager(options);\n }\n\n supports(descriptor: ModelDescriptor): boolean {\n // Support any provider when using mock adapter\n // This allows tests to use \"openai:gpt-4\", \"anthropic:claude\", etc.\n return true;\n }\n\n stream(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n // spec is unused for mocks\n // biome-ignore lint/correctness/noUnusedVariables: spec parameter required by interface\n spec?: unknown,\n ): LLMStream {\n // Create matcher context\n const context: MockMatcherContext = {\n model: options.model,\n provider: descriptor.provider,\n modelName: descriptor.name,\n options,\n messages: options.messages,\n };\n\n // Find matching mock (async operation)\n // We need to handle this in the stream generator\n return this.createMockStreamFromContext(context);\n }\n\n private async *createMockStreamFromContext(context: MockMatcherContext): LLMStream {\n try {\n // Find matching mock\n const mockResponse = await this.mockManager.findMatch(context);\n\n if (!mockResponse) {\n // This should not happen if MockManager is configured correctly\n // but handle it gracefully\n yield {\n text: \"\",\n finishReason: \"stop\",\n usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\n };\n return;\n }\n\n // Stream the mock response\n yield* createMockStream(mockResponse);\n } catch (error) {\n // If an error occurs (e.g., strictMode with no match), we need to handle it\n throw error;\n }\n }\n}\n\n/**\n * Create a mock provider adapter instance.\n * This is a convenience factory function.\n *\n * @param options - Optional configuration for the mock system\n * @returns A configured MockProviderAdapter\n *\n * @example\n * ```typescript\n * const adapter = createMockAdapter({ strictMode: true, debug: true });\n * const client = new LLMist([adapter]);\n * ```\n */\nexport function createMockAdapter(options?: MockOptions): MockProviderAdapter {\n return new MockProviderAdapter(options);\n}\n","import type { LLMMessage } from \"../core/messages.js\";\nimport { getMockManager } from \"./mock-manager.js\";\nimport type {\n MockMatcher,\n MockMatcherContext,\n MockRegistration,\n MockResponse,\n} from \"./mock-types.js\";\n\n/**\n * Fluent builder for creating mock responses and registrations.\n * Provides a convenient API for common mocking scenarios.\n *\n * @example\n * ```typescript\n * import { mockLLM } from 'llmist';\n *\n * // Simple text mock\n * mockLLM()\n * .forModel('gpt-5')\n * .returns('Hello, world!')\n * .register();\n *\n * // Mock with gadget calls\n * mockLLM()\n * .forProvider('anthropic')\n * .whenMessageContains('calculate')\n * .returnsGadgetCalls([\n * { gadgetName: 'calculator', parameters: { operation: 'add', a: 1, b: 2 } }\n * ])\n * .register();\n *\n * // Complex conditional mock\n * mockLLM()\n * .when((ctx) => ctx.messages.length > 5)\n * .returns('This conversation is getting long!')\n * .once()\n * .register();\n * ```\n */\nexport class MockBuilder {\n private matchers: MockMatcher[] = [];\n private response:\n | MockResponse\n | ((context: MockMatcherContext) => MockResponse | Promise<MockResponse>) = {};\n private label?: string;\n private isOnce = false;\n private id?: string;\n\n /**\n * Match calls to a specific model (by name, supports partial matching).\n *\n * @example\n * mockLLM().forModel('gpt-5')\n * mockLLM().forModel('claude') // matches any Claude model\n */\n forModel(modelName: string): this {\n if (!modelName || modelName.trim() === \"\") {\n throw new Error(\"Model name cannot be empty\");\n }\n this.matchers.push((ctx) => ctx.modelName.includes(modelName));\n return this;\n }\n\n /**\n * Match calls to any model.\n * Useful when you want to mock responses regardless of the model used.\n *\n * @example\n * mockLLM().forAnyModel()\n */\n forAnyModel(): this {\n this.matchers.push(() => true);\n return this;\n }\n\n /**\n * Match calls to a specific provider.\n *\n * @example\n * mockLLM().forProvider('openai')\n * mockLLM().forProvider('anthropic')\n */\n forProvider(provider: string): this {\n if (!provider || provider.trim() === \"\") {\n throw new Error(\"Provider name cannot be empty\");\n }\n this.matchers.push((ctx) => ctx.provider === provider);\n return this;\n }\n\n /**\n * Match calls to any provider.\n * Useful when you want to mock responses regardless of the provider used.\n *\n * @example\n * mockLLM().forAnyProvider()\n */\n forAnyProvider(): this {\n this.matchers.push(() => true);\n return this;\n }\n\n /**\n * Match when any message contains the given text (case-insensitive).\n *\n * @example\n * mockLLM().whenMessageContains('hello')\n */\n whenMessageContains(text: string): this {\n this.matchers.push((ctx) =>\n ctx.messages.some((msg) => msg.content?.toLowerCase().includes(text.toLowerCase())),\n );\n return this;\n }\n\n /**\n * Match when the last message contains the given text (case-insensitive).\n *\n * @example\n * mockLLM().whenLastMessageContains('goodbye')\n */\n whenLastMessageContains(text: string): this {\n this.matchers.push((ctx) => {\n const lastMsg = ctx.messages[ctx.messages.length - 1];\n return lastMsg?.content?.toLowerCase().includes(text.toLowerCase()) ?? false;\n });\n return this;\n }\n\n /**\n * Match when any message matches the given regex.\n *\n * @example\n * mockLLM().whenMessageMatches(/calculate \\d+/)\n */\n whenMessageMatches(regex: RegExp): this {\n this.matchers.push((ctx) => ctx.messages.some((msg) => regex.test(msg.content ?? \"\")));\n return this;\n }\n\n /**\n * Match when a message with a specific role contains text.\n *\n * @example\n * mockLLM().whenRoleContains('system', 'You are a helpful assistant')\n */\n whenRoleContains(role: LLMMessage[\"role\"], text: string): this {\n this.matchers.push((ctx) =>\n ctx.messages.some(\n (msg) => msg.role === role && msg.content?.toLowerCase().includes(text.toLowerCase()),\n ),\n );\n return this;\n }\n\n /**\n * Match based on the number of messages in the conversation.\n *\n * @example\n * mockLLM().whenMessageCount((count) => count > 10)\n */\n whenMessageCount(predicate: (count: number) => boolean): this {\n this.matchers.push((ctx) => predicate(ctx.messages.length));\n return this;\n }\n\n /**\n * Add a custom matcher function.\n * This provides full control over matching logic.\n *\n * @example\n * mockLLM().when((ctx) => {\n * return ctx.options.temperature > 0.8;\n * })\n */\n when(matcher: MockMatcher): this {\n this.matchers.push(matcher);\n return this;\n }\n\n /**\n * Set the text response to return.\n * Can be a static string or a function that returns a string dynamically.\n *\n * @example\n * mockLLM().returns('Hello, world!')\n * mockLLM().returns(() => `Response at ${Date.now()}`)\n * mockLLM().returns((ctx) => `You said: ${ctx.messages[0]?.content}`)\n */\n returns(text: string | ((context: MockMatcherContext) => string | Promise<string>)): this {\n if (typeof text === \"function\") {\n // Convert function to full response generator\n // Use Promise.resolve().then() to properly handle both sync and async errors\n this.response = async (ctx) => {\n const resolvedText = await Promise.resolve().then(() => text(ctx));\n return { text: resolvedText };\n };\n } else {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use returns() after withResponse() with a function\");\n }\n this.response.text = text;\n }\n return this;\n }\n\n /**\n * Set gadget calls to include in the response.\n *\n * @example\n * mockLLM().returnsGadgetCalls([\n * { gadgetName: 'calculator', parameters: { op: 'add', a: 1, b: 2 } }\n * ])\n */\n returnsGadgetCalls(\n calls: Array<{\n gadgetName: string;\n parameters: Record<string, unknown>;\n invocationId?: string;\n }>,\n ): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use returnsGadgetCalls() after withResponse() with a function\");\n }\n this.response.gadgetCalls = calls;\n return this;\n }\n\n /**\n * Add a single gadget call to the response.\n *\n * @example\n * mockLLM()\n * .returnsGadgetCall('calculator', { op: 'add', a: 1, b: 2 })\n * .returnsGadgetCall('logger', { message: 'Done!' })\n */\n returnsGadgetCall(gadgetName: string, parameters: Record<string, unknown>): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use returnsGadgetCall() after withResponse() with a function\");\n }\n if (!this.response.gadgetCalls) {\n this.response.gadgetCalls = [];\n }\n this.response.gadgetCalls.push({ gadgetName, parameters });\n return this;\n }\n\n /**\n * Set the complete mock response object.\n * This allows full control over all response properties.\n * Can also be a function that generates the response dynamically based on context.\n *\n * @example\n * // Static response\n * mockLLM().withResponse({\n * text: 'Hello',\n * usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 },\n * finishReason: 'stop'\n * })\n *\n * @example\n * // Dynamic response\n * mockLLM().withResponse((ctx) => ({\n * text: `You said: ${ctx.messages[ctx.messages.length - 1]?.content}`,\n * usage: { inputTokens: 10, outputTokens: 5, totalTokens: 15 }\n * }))\n */\n withResponse(\n response:\n | MockResponse\n | ((context: MockMatcherContext) => MockResponse | Promise<MockResponse>),\n ): this {\n this.response = response;\n return this;\n }\n\n /**\n * Set simulated token usage.\n *\n * @example\n * mockLLM().withUsage({ inputTokens: 100, outputTokens: 50, totalTokens: 150 })\n */\n withUsage(usage: { inputTokens: number; outputTokens: number; totalTokens: number }): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use withUsage() after withResponse() with a function\");\n }\n if (usage.inputTokens < 0 || usage.outputTokens < 0 || usage.totalTokens < 0) {\n throw new Error(\"Token counts cannot be negative\");\n }\n if (usage.totalTokens !== usage.inputTokens + usage.outputTokens) {\n throw new Error(\"totalTokens must equal inputTokens + outputTokens\");\n }\n this.response.usage = usage;\n return this;\n }\n\n /**\n * Set the finish reason.\n *\n * @example\n * mockLLM().withFinishReason('stop')\n * mockLLM().withFinishReason('length')\n */\n withFinishReason(reason: string): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use withFinishReason() after withResponse() with a function\");\n }\n this.response.finishReason = reason;\n return this;\n }\n\n /**\n * Set initial delay before streaming starts (simulates network latency).\n *\n * @example\n * mockLLM().withDelay(100) // 100ms delay\n */\n withDelay(ms: number): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use withDelay() after withResponse() with a function\");\n }\n if (ms < 0) {\n throw new Error(\"Delay must be non-negative\");\n }\n this.response.delayMs = ms;\n return this;\n }\n\n /**\n * Set delay between stream chunks (simulates realistic streaming).\n *\n * @example\n * mockLLM().withStreamDelay(10) // 10ms between chunks\n */\n withStreamDelay(ms: number): this {\n if (typeof this.response === \"function\") {\n throw new Error(\"Cannot use withStreamDelay() after withResponse() with a function\");\n }\n if (ms < 0) {\n throw new Error(\"Stream delay must be non-negative\");\n }\n this.response.streamDelayMs = ms;\n return this;\n }\n\n /**\n * Set a label for this mock (useful for debugging).\n *\n * @example\n * mockLLM().withLabel('greeting mock')\n */\n withLabel(label: string): this {\n this.label = label;\n return this;\n }\n\n /**\n * Set a specific ID for this mock.\n *\n * @example\n * mockLLM().withId('my-custom-mock-id')\n */\n withId(id: string): this {\n this.id = id;\n return this;\n }\n\n /**\n * Mark this mock as one-time use (will be removed after first match).\n *\n * @example\n * mockLLM().once()\n */\n once(): this {\n this.isOnce = true;\n return this;\n }\n\n /**\n * Build the mock registration without registering it.\n * Useful if you want to register it manually later.\n *\n * @returns The built MockRegistration object (without id if not specified)\n */\n build(): Omit<MockRegistration, \"id\"> & { id?: string } {\n // Guard against empty matchers\n if (this.matchers.length === 0) {\n throw new Error(\n \"Mock must have at least one matcher. Use .when(), .forModel(), .forProvider(), etc.\",\n );\n }\n\n // Combine all matchers with AND logic\n const combinedMatcher: MockMatcher = async (ctx) => {\n for (const matcher of this.matchers) {\n const matches = await Promise.resolve(matcher(ctx));\n if (!matches) return false;\n }\n return true;\n };\n\n return {\n id: this.id,\n matcher: combinedMatcher,\n response: this.response,\n label: this.label,\n once: this.isOnce,\n };\n }\n\n /**\n * Register this mock with the global MockManager.\n * Returns the ID of the registered mock.\n *\n * @example\n * const mockId = mockLLM().forModel('gpt-5').returns('Hello!').register();\n * // Later: getMockManager().unregister(mockId);\n */\n register(): string {\n const mockManager = getMockManager();\n const registration = this.build();\n return mockManager.register(registration);\n }\n}\n\n/**\n * Create a new MockBuilder instance.\n * This is the main entry point for the fluent mock API.\n *\n * @example\n * ```typescript\n * import { mockLLM } from 'llmist';\n *\n * mockLLM()\n * .forModel('gpt-5')\n * .whenMessageContains('hello')\n * .returns('Hello there!')\n * .register();\n * ```\n */\nexport function mockLLM(): MockBuilder {\n return new MockBuilder();\n}\n","import { LLMist } from \"../core/client.js\";\nimport { MockProviderAdapter } from \"./mock-adapter.js\";\nimport type { MockOptions } from \"./mock-types.js\";\n\n/**\n * Create a preconfigured LLMist client with mock adapter.\n * This is a convenience function for testing scenarios.\n *\n * @param options - Optional configuration for the mock system\n * @returns A LLMist instance configured to use mocks\n *\n * @example\n * ```typescript\n * import { createMockClient, getMockManager } from 'llmist';\n *\n * // Setup\n * const client = createMockClient({ strictMode: true });\n * const mockManager = getMockManager();\n *\n * // Register mocks\n * mockManager.register({\n * matcher: (ctx) => ctx.modelName === 'gpt-4',\n * response: { text: 'Mocked response' }\n * });\n *\n * // Use in tests\n * const stream = client.stream({\n * model: 'mock:gpt-4',\n * messages: [{ role: 'user', content: 'test' }]\n * });\n * ```\n */\nexport function createMockClient(options?: MockOptions): LLMist {\n return new LLMist({\n adapters: [new MockProviderAdapter(options)],\n autoDiscoverProviders: false,\n defaultProvider: \"mock\",\n });\n}\n","/**\n * Mock gadget utilities for testing.\n *\n * Provides helpers for creating mock gadgets with configurable behavior\n * and call tracking.\n *\n * @module testing/mock-gadget\n */\n\nimport type { ZodType } from \"zod\";\nimport { BaseGadget } from \"../gadgets/gadget.js\";\n\n/**\n * Recorded gadget call for tracking.\n */\nexport interface RecordedCall {\n /** Parameters passed to execute() */\n params: Record<string, unknown>;\n /** When the call was made */\n timestamp: number;\n}\n\n/**\n * Mock gadget with call tracking capabilities.\n */\nexport interface MockGadget extends BaseGadget {\n /** Get all recorded calls */\n getCalls(): RecordedCall[];\n /** Get number of times the gadget was executed */\n getCallCount(): number;\n /** Reset call history */\n resetCalls(): void;\n /** Check if gadget was called with specific params (partial match) */\n wasCalledWith(params: Partial<Record<string, unknown>>): boolean;\n /** Get the last call's parameters */\n getLastCall(): RecordedCall | undefined;\n}\n\n/**\n * Configuration for creating a mock gadget.\n */\nexport interface MockGadgetConfig<TSchema extends ZodType = ZodType> {\n /** Gadget name (required) */\n name: string;\n /** Gadget description */\n description?: string;\n /** Parameter schema */\n schema?: TSchema;\n /** Static result to return */\n result?: string;\n /** Dynamic result based on parameters */\n resultFn?: (params: Record<string, unknown>) => string | Promise<string>;\n /** Error to throw on execution */\n error?: Error | string;\n /** Enable call tracking (default: true) */\n trackCalls?: boolean;\n /** Execution delay in ms */\n delayMs?: number;\n /** Gadget timeout setting */\n timeoutMs?: number;\n}\n\n/**\n * Implementation of MockGadget.\n */\nclass MockGadgetImpl extends BaseGadget implements MockGadget {\n override name: string;\n override description: string;\n override parameterSchema?: ZodType;\n override timeoutMs?: number;\n\n private calls: RecordedCall[] = [];\n private readonly resultValue?: string;\n private readonly resultFn?: (params: Record<string, unknown>) => string | Promise<string>;\n private readonly errorToThrow?: Error;\n private readonly delayMs: number;\n private readonly shouldTrackCalls: boolean;\n\n constructor(config: MockGadgetConfig) {\n super();\n this.name = config.name;\n this.description = config.description ?? `Mock gadget: ${config.name}`;\n this.parameterSchema = config.schema;\n this.resultValue = config.result;\n this.resultFn = config.resultFn;\n this.delayMs = config.delayMs ?? 0;\n this.shouldTrackCalls = config.trackCalls ?? true;\n this.timeoutMs = config.timeoutMs;\n\n if (config.error) {\n this.errorToThrow = typeof config.error === \"string\" ? new Error(config.error) : config.error;\n }\n }\n\n async execute(params: Record<string, unknown>): Promise<string> {\n if (this.shouldTrackCalls) {\n this.calls.push({ params: { ...params }, timestamp: Date.now() });\n }\n\n if (this.delayMs > 0) {\n await new Promise((resolve) => setTimeout(resolve, this.delayMs));\n }\n\n if (this.errorToThrow) {\n throw this.errorToThrow;\n }\n\n if (this.resultFn) {\n return this.resultFn(params);\n }\n\n return this.resultValue ?? \"mock result\";\n }\n\n getCalls(): RecordedCall[] {\n return [...this.calls];\n }\n\n getCallCount(): number {\n return this.calls.length;\n }\n\n resetCalls(): void {\n this.calls = [];\n }\n\n wasCalledWith(params: Partial<Record<string, unknown>>): boolean {\n return this.calls.some((call) =>\n Object.entries(params).every(([key, value]) => call.params[key] === value),\n );\n }\n\n getLastCall(): RecordedCall | undefined {\n return this.calls.length > 0 ? this.calls[this.calls.length - 1] : undefined;\n }\n}\n\n/**\n * Create a mock gadget for testing.\n *\n * @param config - Mock gadget configuration\n * @returns MockGadget instance with call tracking\n *\n * @example\n * ```typescript\n * import { createMockGadget } from 'llmist/testing';\n * import { z } from 'zod';\n *\n * const calculator = createMockGadget({\n * name: 'Calculator',\n * schema: z.object({ a: z.number(), b: z.number() }),\n * resultFn: ({ a, b }) => String(Number(a) + Number(b)),\n * });\n *\n * // Use in tests\n * const registry = new GadgetRegistry();\n * registry.registerByClass(calculator);\n *\n * // After running agent...\n * expect(calculator.getCallCount()).toBe(1);\n * expect(calculator.wasCalledWith({ a: 5 })).toBe(true);\n * ```\n */\nexport function createMockGadget<TSchema extends ZodType>(\n config: MockGadgetConfig<TSchema>,\n): MockGadget {\n return new MockGadgetImpl(config);\n}\n\n/**\n * Fluent builder for creating mock gadgets.\n *\n * @example\n * ```typescript\n * import { mockGadget } from 'llmist/testing';\n * import { z } from 'zod';\n *\n * const mock = mockGadget()\n * .withName('Weather')\n * .withDescription('Get weather for a city')\n * .withSchema(z.object({ city: z.string() }))\n * .returns('Sunny, 72F')\n * .trackCalls()\n * .build();\n *\n * // Or for error testing\n * const errorMock = mockGadget()\n * .withName('Unstable')\n * .throws('Service unavailable')\n * .build();\n * ```\n */\nexport class MockGadgetBuilder {\n private config: MockGadgetConfig = { name: \"MockGadget\" };\n\n /**\n * Set the gadget name.\n */\n withName(name: string): this {\n this.config.name = name;\n return this;\n }\n\n /**\n * Set the gadget description.\n */\n withDescription(description: string): this {\n this.config.description = description;\n return this;\n }\n\n /**\n * Set the parameter schema.\n */\n withSchema<T extends ZodType>(schema: T): MockGadgetBuilder {\n this.config.schema = schema;\n return this;\n }\n\n /**\n * Set a static result to return.\n */\n returns(result: string): this {\n this.config.result = result;\n this.config.resultFn = undefined;\n return this;\n }\n\n /**\n * Set a dynamic result function.\n */\n returnsAsync(resultFn: (params: Record<string, unknown>) => string | Promise<string>): this {\n this.config.resultFn = resultFn;\n this.config.result = undefined;\n return this;\n }\n\n /**\n * Make the gadget throw an error on execution.\n */\n throws(error: Error | string): this {\n this.config.error = error;\n return this;\n }\n\n /**\n * Add execution delay.\n */\n withDelay(ms: number): this {\n this.config.delayMs = ms;\n return this;\n }\n\n /**\n * Set timeout for the gadget.\n */\n withTimeout(ms: number): this {\n this.config.timeoutMs = ms;\n return this;\n }\n\n /**\n * Enable call tracking (enabled by default).\n */\n trackCalls(): this {\n this.config.trackCalls = true;\n return this;\n }\n\n /**\n * Disable call tracking.\n */\n noTracking(): this {\n this.config.trackCalls = false;\n return this;\n }\n\n /**\n * Build the mock gadget.\n */\n build(): MockGadget {\n return createMockGadget(this.config);\n }\n}\n\n/**\n * Create a fluent builder for mock gadgets.\n *\n * @returns New MockGadgetBuilder instance\n *\n * @example\n * ```typescript\n * const mock = mockGadget()\n * .withName('Search')\n * .withSchema(z.object({ query: z.string() }))\n * .returnsAsync(async ({ query }) => {\n * return `Results for: ${query}`;\n * })\n * .build();\n * ```\n */\nexport function mockGadget(): MockGadgetBuilder {\n return new MockGadgetBuilder();\n}\n"],"mappings":"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","names":["z","pointer","stream","stream","init_constants","Anthropic","init_constants","stream","init_constants","stream","OpenAI","init_constants","stream","providerSpecs","import_zod"]}