llmist 1.6.1 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-X5XQ6M5P.js → chunk-E52IO2NO.js} +93 -9
- package/dist/chunk-E52IO2NO.js.map +1 -0
- package/dist/{chunk-QR5IQXEM.js → chunk-JGORHSHC.js} +2 -2
- package/dist/chunk-JGORHSHC.js.map +1 -0
- package/dist/cli.cjs +93 -9
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +92 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +2 -2
- package/dist/{mock-stream-Cc47j12U.d.cts → mock-stream-BMuFlQI1.d.cts} +38 -1
- package/dist/{mock-stream-Cc47j12U.d.ts → mock-stream-BMuFlQI1.d.ts} +38 -1
- package/dist/testing/index.cjs +92 -8
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +2 -2
- package/dist/testing/index.d.ts +2 -2
- package/dist/testing/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-QR5IQXEM.js.map +0 -1
- package/dist/chunk-X5XQ6M5P.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/logging/logger.ts","../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/gadgets/schema-to-json.ts","../src/gadgets/gadget.ts","../src/gadgets/create-gadget.ts","../src/gadgets/output-viewer.ts","../src/agent/compaction/config.ts","../src/agent/compaction/strategy.ts","../src/agent/compaction/strategies/sliding-window.ts","../src/agent/compaction/strategies/summarization.ts","../src/agent/compaction/strategies/hybrid.ts","../src/agent/compaction/strategies/index.ts","../src/agent/compaction/manager.ts","../src/agent/gadget-output-store.ts","../src/agent/agent-internal-key.ts","../src/agent/conversation-manager.ts","../src/agent/event-handlers.ts","../src/agent/hook-validators.ts","../src/gadgets/schema-introspector.ts","../src/gadgets/block-params.ts","../src/gadgets/error-formatter.ts","../src/gadgets/exceptions.ts","../src/gadgets/parser.ts","../src/gadgets/executor.ts","../src/agent/stream-processor.ts","../src/agent/agent.ts","../src/agent/builder.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/gadgets/validation.ts","../src/testing/gadget-testing.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","../src/testing/stream-helpers.ts","../src/testing/conversation-fixtures.ts","../src/testing/mock-conversation.ts","../src/testing/cli-helpers.ts"],"sourcesContent":["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","// Gadget marker constants\nexport const GADGET_START_PREFIX = \"!!!GADGET_START:\";\nexport const GADGET_END_PREFIX = \"!!!GADGET_END\";\nexport const GADGET_ARG_PREFIX = \"!!!ARG:\";\n\n// Default configuration values\nexport const DEFAULT_MAX_TOKENS = 1024;\nexport const DEFAULT_MAX_ITERATIONS = 10;\n\n// Gadget output limiting defaults\n/** Default: gadget output limiting is enabled */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT = true;\n\n/** Default: limit gadget output to 15% of context window */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;\n\n/** Approximate characters per token for limit calculation */\nexport const CHARS_PER_TOKEN = 4;\n\n/** Fallback context window size if model is not in registry */\nexport const FALLBACK_CONTEXT_WINDOW = 128_000;\n","/**\n * Model shortcuts and aliases for more expressive DX.\n *\n * This module provides convenient aliases for common model names,\n * allowing developers to use short, memorable names instead of\n * verbose provider:model-id formats.\n *\n * @example\n * ```typescript\n * // Instead of:\n * model: \"openai:gpt-5-nano\"\n *\n * // You can use:\n * model: \"gpt5-nano\"\n * // or even:\n * model: \"gpt-5-nano\" // Auto-detects provider\n * ```\n */\n\n/**\n * Map of common model aliases to their full provider:model-id format.\n */\nexport const MODEL_ALIASES: Record<string, string> = {\n // OpenAI aliases\n gpt4: \"openai:gpt-4o\",\n gpt4o: \"openai:gpt-4o\",\n gpt5: \"openai:gpt-5\",\n \"gpt5-mini\": \"openai:gpt-5-mini\",\n \"gpt5-nano\": \"openai:gpt-5-nano\",\n\n // Anthropic aliases\n sonnet: \"anthropic:claude-sonnet-4-5\",\n \"claude-sonnet\": \"anthropic:claude-sonnet-4-5\",\n haiku: \"anthropic:claude-haiku-4-5\",\n \"claude-haiku\": \"anthropic:claude-haiku-4-5\",\n opus: \"anthropic:claude-opus-4-5\",\n \"claude-opus\": \"anthropic:claude-opus-4-5\",\n\n // Gemini aliases\n flash: \"gemini:gemini-2.0-flash\",\n \"gemini-flash\": \"gemini:gemini-2.0-flash\",\n \"gemini-pro\": \"gemini:gemini-2.5-pro\",\n pro: \"gemini:gemini-2.5-pro\",\n};\n\n/**\n * Options for resolveModel function.\n */\nexport interface ResolveModelOptions {\n /**\n * If true, throw an error for unknown model names instead of falling back to OpenAI.\n * This helps catch typos like \"gp4\" instead of \"gpt4\".\n * Default: false\n */\n strict?: boolean;\n\n /**\n * If true, suppress warnings for unknown model names.\n * Default: false\n */\n silent?: boolean;\n}\n\n/**\n * Known model name patterns for validation.\n * These patterns help detect typos and unknown models.\n */\nconst KNOWN_MODEL_PATTERNS = [\n /^gpt-?\\d/i, // gpt-4, gpt-3.5, gpt4, etc.\n /^claude-?\\d/i, // claude-3, claude-2, etc.\n /^gemini-?(\\d|pro|flash)/i, // gemini-2.0, gemini-pro, gemini-flash, etc.\n /^o\\d/i, // OpenAI o1, o3, etc.\n];\n\n/**\n * Check if a model name matches known patterns.\n *\n * @param model - Model name to check\n * @returns True if the model matches a known pattern\n */\nfunction isKnownModelPattern(model: string): boolean {\n const normalized = model.toLowerCase();\n\n // Check if it's a known alias\n if (MODEL_ALIASES[normalized]) {\n return true;\n }\n\n // Check against known patterns\n return KNOWN_MODEL_PATTERNS.some((pattern) => pattern.test(model));\n}\n\n/**\n * Resolves a model name to its full provider:model format.\n *\n * Supports:\n * - Direct aliases: 'gpt5', 'sonnet', 'flash'\n * - Auto-detection: 'gpt-5-nano' → 'openai:gpt-5-nano'\n * - Pass-through: 'openai:gpt-5' → 'openai:gpt-5'\n *\n * Warnings:\n * - Logs a warning when an unknown model name falls back to OpenAI\n * - Use { strict: true } to throw an error instead\n * - Use { silent: true } to suppress warnings\n *\n * @param model - Model name or alias\n * @param options - Resolution options\n * @returns Full provider:model-id string\n *\n * @example\n * ```typescript\n * resolveModel('gpt5') // → 'openai:gpt-5'\n * resolveModel('sonnet') // → 'anthropic:claude-sonnet-4-5'\n * resolveModel('gpt-5-nano') // → 'openai:gpt-5-nano'\n * resolveModel('openai:gpt-5') // → 'openai:gpt-5' (passthrough)\n * resolveModel('claude-3-5-sonnet') // → 'anthropic:claude-3-5-sonnet'\n *\n * // Typo detection\n * resolveModel('gp5') // ⚠️ Warning: Unknown model 'gp5', falling back to 'openai:gp5'\n *\n * // Strict mode (throws on typos)\n * resolveModel('gp5', { strict: true }) // ❌ Error: Unknown model 'gp5'\n * ```\n */\nexport function resolveModel(model: string, options: ResolveModelOptions = {}): string {\n // Already has provider prefix - pass through\n if (model.includes(\":\")) {\n return model;\n }\n\n // Check if it's a known alias\n const normalized = model.toLowerCase();\n if (MODEL_ALIASES[normalized]) {\n return MODEL_ALIASES[normalized];\n }\n\n // Smart detection by model name patterns\n const modelLower = model.toLowerCase();\n\n // OpenAI models start with 'gpt'\n if (modelLower.startsWith(\"gpt\")) {\n return `openai:${model}`;\n }\n\n // Anthropic models start with 'claude'\n if (modelLower.startsWith(\"claude\")) {\n return `anthropic:${model}`;\n }\n\n // Gemini models start with 'gemini'\n if (modelLower.startsWith(\"gemini\")) {\n return `gemini:${model}`;\n }\n\n // OpenAI o-series models (o1, o3, etc.)\n if (modelLower.match(/^o\\d/)) {\n return `openai:${model}`;\n }\n\n // Unknown model: validate and warn/error\n if (!isKnownModelPattern(model)) {\n if (options.strict) {\n throw new Error(\n `Unknown model '${model}'. Did you mean one of: gpt4, sonnet, haiku, flash? ` +\n `Use explicit provider prefix like 'openai:${model}' to bypass this check.`,\n );\n }\n\n if (!options.silent) {\n console.warn(\n `⚠️ Unknown model '${model}', falling back to 'openai:${model}'. ` +\n `This might be a typo. Did you mean: gpt4, gpt5, gpt5-nano, sonnet, haiku, flash? ` +\n `Use { strict: true } to error on unknown models, or { silent: true } to suppress this warning.`,\n );\n }\n }\n\n // Default: assume OpenAI for unknown models\n // This provides a reasonable fallback for most cases\n return `openai:${model}`;\n}\n\n/**\n * Check if a model string is already in provider:model format.\n *\n * @param model - Model string to check\n * @returns True if the model has a provider prefix\n *\n * @example\n * ```typescript\n * hasProviderPrefix('openai:gpt-4o') // → true\n * hasProviderPrefix('gpt4') // → false\n * hasProviderPrefix('claude-3-5-sonnet') // → false\n * ```\n */\nexport function hasProviderPrefix(model: string): boolean {\n return model.includes(\":\");\n}\n\n/**\n * Extract the provider from a full model string.\n *\n * @param model - Full model string (provider:model-id)\n * @returns Provider name, or undefined if no prefix\n *\n * @example\n * ```typescript\n * getProvider('openai:gpt-4o') // → 'openai'\n * getProvider('anthropic:claude') // → 'anthropic'\n * getProvider('gpt4') // → undefined\n * ```\n */\nexport function getProvider(model: string): string | undefined {\n const separatorIndex = model.indexOf(\":\");\n if (separatorIndex === -1) {\n return undefined;\n }\n return model.slice(0, separatorIndex);\n}\n\n/**\n * Extract the model ID from a full model string.\n *\n * @param model - Full model string (provider:model-id)\n * @returns Model ID, or the original string if no prefix\n *\n * @example\n * ```typescript\n * getModelId('openai:gpt-4o') // → 'gpt-4o'\n * getModelId('anthropic:claude') // → 'claude'\n * getModelId('gpt4') // → 'gpt4'\n * ```\n */\nexport function getModelId(model: string): string {\n const separatorIndex = model.indexOf(\":\");\n if (separatorIndex === -1) {\n return model;\n }\n return model.slice(separatorIndex + 1);\n}\n","import type { ZodTypeAny } from \"zod\";\nimport * as z from \"zod\";\n\n/**\n * Validates that a Zod schema doesn't contain z.unknown() which produces\n * incomplete JSON schemas without type information.\n *\n * @param schema - The Zod schema to validate\n * @param gadgetName - Name of the gadget (for error messages)\n * @throws Error if z.unknown() is detected with helpful suggestions\n */\nexport function validateGadgetSchema(schema: ZodTypeAny, gadgetName: string): void {\n let jsonSchema;\n try {\n jsonSchema = z.toJSONSchema(schema, { target: \"draft-7\" });\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Gadget \"${gadgetName}\" has a schema that cannot be serialized to JSON Schema.\\n` +\n `This usually happens with unsupported patterns like:\\n` +\n `- z.record() - use z.object({}).passthrough() instead\\n` +\n `- Complex transforms or custom refinements\\n` +\n `- Circular references\\n` +\n `\\n` +\n `Original error: ${errorMessage}\\n` +\n `\\n` +\n `Only use schema patterns that Zod v4's native toJSONSchema() supports.`,\n );\n }\n const issues = findUnknownTypes(jsonSchema);\n\n if (issues.length > 0) {\n const fieldList = issues.join(\", \");\n throw new Error(\n `Gadget \"${gadgetName}\" uses z.unknown() which produces incomplete schemas.\\n` +\n `Problematic fields: ${fieldList}\\n` +\n `\\n` +\n `z.unknown() doesn't generate type information in JSON Schema, making it unclear\\n` +\n `to the LLM what data structure to provide.\\n` +\n `\\n` +\n `Suggestions:\\n` +\n `- Use z.object({}).passthrough() for flexible objects\\n` +\n `- Use z.record(z.string()) for key-value objects with string values\\n` +\n `- Define specific structure if possible\\n` +\n `\\n` +\n `Example fixes:\\n` +\n ` // ❌ Bad\\n` +\n ` content: z.unknown()\\n` +\n `\\n` +\n ` // ✅ Good\\n` +\n ` content: z.object({}).passthrough() // for flexible objects\\n` +\n ` content: z.record(z.string()) // for key-value objects\\n` +\n ` content: z.array(z.string()) // for arrays of strings\\n`,\n );\n }\n}\n\n/**\n * Recursively searches a JSON Schema for properties without type information,\n * which indicates z.unknown() usage.\n *\n * @param schema - JSON Schema object to search\n * @param path - Current path in schema (for error reporting)\n * @returns Array of problematic field paths\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction findUnknownTypes(schema: any, path: string[] = []): string[] {\n const issues: string[] = [];\n\n if (!schema || typeof schema !== \"object\") {\n return issues;\n }\n\n // Check if we're in a definitions block\n if (schema.definitions) {\n for (const defSchema of Object.values(schema.definitions)) {\n issues.push(...findUnknownTypes(defSchema, []));\n }\n }\n\n // Check properties of objects\n if (schema.properties) {\n for (const [propName, propSchema] of Object.entries(schema.properties)) {\n const propPath = [...path, propName];\n\n // Check if this property has no type information\n if (hasNoType(propSchema)) {\n issues.push(propPath.join(\".\") || propName);\n }\n\n // Recursively check nested properties\n issues.push(...findUnknownTypes(propSchema, propPath));\n }\n }\n\n // Check array items\n if (schema.items) {\n const itemPath = [...path, \"[]\"];\n if (hasNoType(schema.items)) {\n issues.push(itemPath.join(\".\"));\n }\n issues.push(...findUnknownTypes(schema.items, itemPath));\n }\n\n // Check anyOf/oneOf/allOf unions\n if (schema.anyOf) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema.anyOf.forEach((subSchema: any, index: number) => {\n issues.push(...findUnknownTypes(subSchema, [...path, `anyOf[${index}]`]));\n });\n }\n\n if (schema.oneOf) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema.oneOf.forEach((subSchema: any, index: number) => {\n issues.push(...findUnknownTypes(subSchema, [...path, `oneOf[${index}]`]));\n });\n }\n\n if (schema.allOf) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema.allOf.forEach((subSchema: any, index: number) => {\n issues.push(...findUnknownTypes(subSchema, [...path, `allOf[${index}]`]));\n });\n }\n\n return issues;\n}\n\n/**\n * Checks if a schema property has no type information.\n * This indicates z.unknown() usage.\n *\n * A property has \"no type\" if it:\n * - Is an object\n * - Has no \"type\" field\n * - Has no \"$ref\" (reference to definition)\n * - Has no \"anyOf\", \"oneOf\", or \"allOf\" (union types)\n * - Has only \"description\" or is empty\n *\n * @param prop - Property schema to check\n * @returns true if property has no type information\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction hasNoType(prop: any): boolean {\n if (!prop || typeof prop !== \"object\") {\n return false;\n }\n\n const hasType = prop.type !== undefined;\n const hasRef = prop.$ref !== undefined;\n const hasUnion = prop.anyOf !== undefined || prop.oneOf !== undefined || prop.allOf !== undefined;\n\n // If it has any type information, it's fine\n if (hasType || hasRef || hasUnion) {\n return false;\n }\n\n // Check if it only has description and/or other non-type metadata\n const keys = Object.keys(prop);\n const metadataKeys = [\"description\", \"title\", \"default\", \"examples\"];\n const hasOnlyMetadata = keys.every((key) => metadataKeys.includes(key));\n\n // If it only has metadata or is empty (besides metadata), it's missing type info\n return hasOnlyMetadata || keys.length === 0;\n}\n","import type { BaseGadget } from \"./gadget.js\";\nimport { validateGadgetSchema } from \"./schema-validator.js\";\n\n// Type for gadget constructor\nexport type GadgetClass = new (...args: unknown[]) => BaseGadget;\n\n// Type for gadget or gadget class\nexport type GadgetOrClass = BaseGadget | GadgetClass;\n\nexport class GadgetRegistry {\n private readonly gadgets = new Map<string, BaseGadget>();\n\n /**\n * Creates a registry from an array of gadget classes or instances,\n * or an object mapping names to gadgets.\n *\n * @param gadgets - Array of gadgets/classes or object with custom names\n * @returns New GadgetRegistry with all gadgets registered\n *\n * @example\n * ```typescript\n * // From array of classes\n * const registry = GadgetRegistry.from([Calculator, Weather]);\n *\n * // From array of instances\n * const registry = GadgetRegistry.from([new Calculator(), new Weather()]);\n *\n * // From object with custom names\n * const registry = GadgetRegistry.from({\n * calc: Calculator,\n * weather: new Weather({ apiKey: \"...\" })\n * });\n * ```\n */\n static from(gadgets: GadgetOrClass[] | Record<string, GadgetOrClass>): GadgetRegistry {\n const registry = new GadgetRegistry();\n\n if (Array.isArray(gadgets)) {\n // Array of gadgets or classes\n registry.registerMany(gadgets);\n } else {\n // Object with custom names\n for (const [name, gadget] of Object.entries(gadgets)) {\n const instance = typeof gadget === \"function\" ? new gadget() : gadget;\n registry.register(name, instance);\n }\n }\n\n return registry;\n }\n\n /**\n * Registers multiple gadgets at once from an array.\n *\n * @param gadgets - Array of gadget instances or classes\n * @returns This registry for chaining\n *\n * @example\n * ```typescript\n * registry.registerMany([Calculator, Weather, Email]);\n * registry.registerMany([new Calculator(), new Weather()]);\n * ```\n */\n registerMany(gadgets: GadgetOrClass[]): this {\n for (const gadget of gadgets) {\n const instance = typeof gadget === \"function\" ? new gadget() : gadget;\n this.registerByClass(instance);\n }\n return this;\n }\n\n // Register a gadget by name\n register(name: string, gadget: BaseGadget): void {\n const normalizedName = name.toLowerCase();\n if (this.gadgets.has(normalizedName)) {\n throw new Error(`Gadget '${name}' is already registered`);\n }\n\n // Validate schema if present\n if (gadget.parameterSchema) {\n validateGadgetSchema(gadget.parameterSchema, name);\n }\n\n this.gadgets.set(normalizedName, gadget);\n }\n\n // Register a gadget using its name property or class name\n registerByClass(gadget: BaseGadget): void {\n const name = gadget.name ?? gadget.constructor.name;\n this.register(name, gadget);\n }\n\n // Get gadget by name (case-insensitive)\n get(name: string): BaseGadget | undefined {\n return this.gadgets.get(name.toLowerCase());\n }\n\n // Check if gadget exists (case-insensitive)\n has(name: string): boolean {\n return this.gadgets.has(name.toLowerCase());\n }\n\n // Get all registered gadget names\n getNames(): string[] {\n return Array.from(this.gadgets.keys());\n }\n\n // Get all gadgets for instruction generation\n getAll(): BaseGadget[] {\n return Array.from(this.gadgets.values());\n }\n\n // Unregister gadget (useful for testing, case-insensitive)\n unregister(name: string): boolean {\n return this.gadgets.delete(name.toLowerCase());\n }\n\n // Clear all gadgets (useful for testing)\n clear(): void {\n this.gadgets.clear();\n }\n}\n","/**\n * Context provided to prompt template functions for rendering dynamic content.\n */\nexport interface PromptContext {\n /** Custom gadget start prefix */\n startPrefix: string;\n /** Custom gadget end prefix */\n endPrefix: string;\n /** Custom argument prefix for block format */\n argPrefix: string;\n /** Number of gadgets being registered */\n gadgetCount: number;\n /** Names of all gadgets */\n gadgetNames: string[];\n}\n\n/**\n * Context provided to hint template functions for rendering dynamic hints.\n */\nexport interface HintContext {\n /** Current iteration (1-based for readability) */\n iteration: number;\n /** Maximum iterations allowed */\n maxIterations: number;\n /** Iterations remaining (maxIterations - iteration) */\n remaining: number;\n /** Number of gadget calls in the current response */\n gadgetCallCount?: number;\n}\n\n/**\n * Template that can be either a static string or a function that renders based on context.\n */\nexport type PromptTemplate = string | ((context: PromptContext) => string);\n\n/**\n * Template for hints that can be either a static string or a function that renders based on hint context.\n */\nexport type HintTemplate = string | ((context: HintContext) => string);\n\n/**\n * Configuration for customizing all prompts used internally by llmist.\n *\n * Each field can be either a string (static text) or a function that receives\n * context and returns a string (for dynamic content).\n *\n * @example\n * ```typescript\n * const customConfig: PromptConfig = {\n * mainInstruction: \"USE ONLY THE GADGET MARKERS BELOW:\",\n * criticalUsage: \"Important: Follow the exact format shown.\",\n * rules: (ctx) => [\n * \"Always use the markers to invoke gadgets\",\n * \"Never use function calling\",\n * `You have ${ctx.gadgetCount} gadgets available`\n * ]\n * };\n * ```\n */\nexport interface PromptConfig {\n /**\n * Main instruction block that appears at the start of the gadget system prompt.\n * Default emphasizes using text markers instead of function calling.\n */\n mainInstruction?: PromptTemplate;\n\n /**\n * Critical usage instruction that appears in the usage section.\n * Default emphasizes the exact format requirement.\n */\n criticalUsage?: PromptTemplate;\n\n /**\n * Format description for the block parameter format.\n * Default uses the configured argPrefix dynamically.\n */\n formatDescription?: PromptTemplate;\n\n /**\n * Rules that appear in the rules section.\n * Can be an array of strings or a function that returns an array.\n * Default includes rules about not using function calling.\n */\n rules?: PromptTemplate | string[] | ((context: PromptContext) => string[]);\n\n /**\n * Custom examples to show in the examples section.\n * If provided, replaces the default examples entirely.\n * Should be a function that returns formatted example strings.\n */\n customExamples?: (context: PromptContext) => string;\n\n // ============================================================================\n // HINT TEMPLATES\n // ============================================================================\n\n /**\n * Hint shown when LLM uses only one gadget per response.\n * Encourages parallel gadget usage for efficiency.\n */\n parallelGadgetsHint?: HintTemplate;\n\n /**\n * Template for iteration progress hint.\n * Informs the LLM about remaining iterations to help plan work.\n *\n * When using a string template, supports placeholders:\n * - {iteration}: Current iteration (1-based)\n * - {maxIterations}: Maximum iterations allowed\n * - {remaining}: Iterations remaining\n */\n iterationProgressHint?: HintTemplate;\n}\n\n/**\n * Default hint templates used by llmist.\n */\nexport const DEFAULT_HINTS = {\n parallelGadgetsHint:\n \"Tip: You can call multiple gadgets in a single response for efficiency.\",\n\n iterationProgressHint:\n \"[Iteration {iteration}/{maxIterations}] Plan your actions accordingly.\",\n} as const;\n\n/**\n * Default prompt templates used by llmist.\n */\nexport const DEFAULT_PROMPTS: Required<\n Omit<PromptConfig, \"rules\" | \"customExamples\" | \"parallelGadgetsHint\" | \"iterationProgressHint\"> & {\n rules: (context: PromptContext) => string[];\n customExamples: null;\n }\n> = {\n mainInstruction: [\n \"⚠️ CRITICAL: RESPOND ONLY WITH GADGET INVOCATIONS\",\n \"DO NOT use function calling or tool calling\",\n \"You must output the exact text markers shown below in plain text.\",\n \"EACH MARKER MUST START WITH A NEWLINE.\",\n ].join(\"\\n\"),\n\n criticalUsage: \"INVOKE gadgets using the markers - do not describe what you want to do.\",\n\n formatDescription: (ctx) =>\n `Parameters using ${ctx.argPrefix}name markers (value on next line(s), no escaping needed)`,\n\n rules: () => [\n \"Output ONLY plain text with the exact markers - never use function/tool calling\",\n \"You can invoke multiple gadgets in a single response\",\n \"For dependent gadgets, invoke the first one and wait for the result\",\n ],\n\n customExamples: null,\n};\n\n/**\n * Resolve a prompt template to a string using the given context.\n */\nexport function resolvePromptTemplate(\n template: PromptTemplate | undefined,\n defaultValue: PromptTemplate,\n context: PromptContext,\n): string {\n const resolved = template ?? defaultValue;\n return typeof resolved === \"function\" ? resolved(context) : resolved;\n}\n\n/**\n * Resolve rules template to an array of strings.\n */\nexport function resolveRulesTemplate(\n rules: PromptConfig[\"rules\"] | undefined,\n context: PromptContext,\n): string[] {\n const resolved = rules ?? DEFAULT_PROMPTS.rules;\n\n if (Array.isArray(resolved)) {\n return resolved;\n }\n\n if (typeof resolved === \"function\") {\n const result = resolved(context);\n return Array.isArray(result) ? result : [result];\n }\n\n return [resolved];\n}\n\n/**\n * Resolve a hint template to a string using the given context.\n * Supports both function templates and string templates with placeholders.\n *\n * @param template - The hint template to resolve\n * @param defaultValue - Default value if template is undefined\n * @param context - Context for rendering the template\n * @returns The resolved hint string\n */\nexport function resolveHintTemplate(\n template: HintTemplate | undefined,\n defaultValue: string,\n context: HintContext,\n): string {\n const resolved = template ?? defaultValue;\n\n if (typeof resolved === \"function\") {\n return resolved(context);\n }\n\n // Replace placeholders in string template\n return resolved\n .replace(/\\{iteration\\}/g, String(context.iteration))\n .replace(/\\{maxIterations\\}/g, String(context.maxIterations))\n .replace(/\\{remaining\\}/g, String(context.remaining));\n}\n","import type { BaseGadget } from \"../gadgets/gadget.js\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"./constants.js\";\nimport type { PromptConfig } from \"./prompt-config.js\";\nimport { DEFAULT_PROMPTS, resolvePromptTemplate, resolveRulesTemplate } from \"./prompt-config.js\";\n\nexport type LLMRole = \"system\" | \"user\" | \"assistant\";\n\nexport interface LLMMessage {\n role: LLMRole;\n content: string;\n name?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport class LLMMessageBuilder {\n private readonly messages: LLMMessage[] = [];\n private startPrefix: string = GADGET_START_PREFIX;\n private endPrefix: string = GADGET_END_PREFIX;\n private argPrefix: string = GADGET_ARG_PREFIX;\n private promptConfig: PromptConfig;\n\n constructor(promptConfig?: PromptConfig) {\n this.promptConfig = promptConfig ?? {};\n }\n\n /**\n * Set custom prefixes for gadget markers.\n * Used to configure history builder to match system prompt markers.\n */\n withPrefixes(startPrefix: string, endPrefix: string, argPrefix?: string): this {\n this.startPrefix = startPrefix;\n this.endPrefix = endPrefix;\n if (argPrefix) {\n this.argPrefix = argPrefix;\n }\n return this;\n }\n\n addSystem(content: string, metadata?: Record<string, unknown>): this {\n this.messages.push({ role: \"system\", content, metadata });\n return this;\n }\n\n addGadgets(\n gadgets: BaseGadget[],\n options?: { startPrefix?: string; endPrefix?: string; argPrefix?: string },\n ): this {\n // Store custom prefixes for later use in addGadgetCall\n if (options?.startPrefix) {\n this.startPrefix = options.startPrefix;\n }\n if (options?.endPrefix) {\n this.endPrefix = options.endPrefix;\n }\n if (options?.argPrefix) {\n this.argPrefix = options.argPrefix;\n }\n\n const context = {\n startPrefix: this.startPrefix,\n endPrefix: this.endPrefix,\n argPrefix: this.argPrefix,\n gadgetCount: gadgets.length,\n gadgetNames: gadgets.map((g) => g.name ?? g.constructor.name),\n };\n\n const parts: string[] = [];\n\n // Use configurable main instruction\n const mainInstruction = resolvePromptTemplate(\n this.promptConfig.mainInstruction,\n DEFAULT_PROMPTS.mainInstruction,\n context,\n );\n parts.push(mainInstruction);\n\n parts.push(this.buildGadgetsSection(gadgets));\n parts.push(this.buildUsageSection(context));\n\n this.messages.push({ role: \"system\", content: parts.join(\"\") });\n return this;\n }\n\n private buildGadgetsSection(gadgets: BaseGadget[]): string {\n const parts: string[] = [];\n parts.push(\"\\n\\nAVAILABLE GADGETS\");\n parts.push(\"\\n=================\\n\");\n\n for (const gadget of gadgets) {\n const gadgetName = gadget.name ?? gadget.constructor.name;\n const instruction = gadget.getInstruction(this.argPrefix);\n\n // Parse instruction to separate description and schema\n const schemaMarker = \"\\n\\nInput Schema (BLOCK):\";\n const schemaIndex = instruction.indexOf(schemaMarker);\n\n const description = (\n schemaIndex !== -1 ? instruction.substring(0, schemaIndex) : instruction\n ).trim();\n const schema =\n schemaIndex !== -1 ? instruction.substring(schemaIndex + schemaMarker.length).trim() : \"\";\n\n parts.push(`\\nGADGET: ${gadgetName}`);\n parts.push(`\\n${description}`);\n if (schema) {\n parts.push(`\\n\\nPARAMETERS (BLOCK):\\n${schema}`);\n }\n parts.push(\"\\n\\n---\");\n }\n\n return parts.join(\"\");\n }\n\n private buildUsageSection(context: {\n startPrefix: string;\n endPrefix: string;\n argPrefix: string;\n gadgetCount: number;\n gadgetNames: string[];\n }): string {\n const parts: string[] = [];\n\n // Use configurable format description\n const formatDescription = resolvePromptTemplate(\n this.promptConfig.formatDescription,\n DEFAULT_PROMPTS.formatDescription,\n context,\n );\n\n parts.push(\"\\n\\nHOW TO INVOKE GADGETS\");\n parts.push(\"\\n=====================\\n\");\n\n // Use configurable critical usage instruction\n const criticalUsage = resolvePromptTemplate(\n this.promptConfig.criticalUsage,\n DEFAULT_PROMPTS.criticalUsage,\n context,\n );\n parts.push(`\\nCRITICAL: ${criticalUsage}\\n`);\n\n // Format section\n parts.push(\"\\nFORMAT:\");\n parts.push(`\\n 1. Start marker: ${this.startPrefix}gadget_name`);\n parts.push(`\\n 2. ${formatDescription}`);\n parts.push(`\\n 3. End marker: ${this.endPrefix}`);\n\n parts.push(this.buildExamplesSection(context));\n parts.push(this.buildRulesSection(context));\n\n parts.push(\"\\n\");\n\n return parts.join(\"\");\n }\n\n private buildExamplesSection(context: {\n startPrefix: string;\n endPrefix: string;\n argPrefix: string;\n gadgetCount: number;\n gadgetNames: string[];\n }): string {\n // Allow custom examples to completely replace default examples\n if (this.promptConfig.customExamples) {\n return this.promptConfig.customExamples(context);\n }\n\n const parts: string[] = [];\n\n // Single gadget example\n const singleExample = `${this.startPrefix}translate\n${this.argPrefix}from\nEnglish\n${this.argPrefix}to\nPolish\n${this.argPrefix}content\nParis is the capital of France: a beautiful city.\n${this.endPrefix}`;\n\n parts.push(`\\n\\nEXAMPLE (Single Gadget):\\n\\n${singleExample}`);\n\n // Multiple gadget example with multiline content\n const multipleExample = `${this.startPrefix}translate\n${this.argPrefix}from\nEnglish\n${this.argPrefix}to\nPolish\n${this.argPrefix}content\nParis is the capital of France: a beautiful city.\n${this.endPrefix}\n${this.startPrefix}analyze\n${this.argPrefix}type\neconomic_analysis\n${this.argPrefix}matter\nPolish Economy\n${this.argPrefix}question\nAnalyze the following:\n- Polish arms exports 2025\n- Economic implications\n${this.endPrefix}`;\n\n parts.push(`\\n\\nEXAMPLE (Multiple Gadgets):\\n\\n${multipleExample}`);\n\n // Block format syntax guide\n parts.push(`\n\nBLOCK FORMAT SYNTAX:\nBlock format uses ${this.argPrefix}name markers. Values are captured verbatim until the next marker.\n\n${this.argPrefix}filename\ncalculator.ts\n${this.argPrefix}code\nclass Calculator {\n private history: string[] = [];\n\n add(a: number, b: number): number {\n const result = a + b;\n this.history.push(\\`\\${a} + \\${b} = \\${result}\\`);\n return result;\n }\n}\n\nBLOCK FORMAT RULES:\n- Each parameter starts with ${this.argPrefix}parameterName on its own line\n- The value starts on the NEXT line after the marker\n- Value ends when the next ${this.argPrefix} or ${this.endPrefix} appears\n- NO escaping needed - write values exactly as they should appear\n- Perfect for code, JSON, markdown, or any content with special characters\n\nNESTED OBJECTS (use / separator):\n${this.argPrefix}config/timeout\n30\n${this.argPrefix}config/retries\n3\nProduces: { \"config\": { \"timeout\": \"30\", \"retries\": \"3\" } }\n\nARRAYS (use numeric indices):\n${this.argPrefix}items/0\nfirst\n${this.argPrefix}items/1\nsecond\nProduces: { \"items\": [\"first\", \"second\"] }`);\n\n return parts.join(\"\");\n }\n\n private buildRulesSection(context: {\n startPrefix: string;\n endPrefix: string;\n argPrefix: string;\n gadgetCount: number;\n gadgetNames: string[];\n }): string {\n const parts: string[] = [];\n parts.push(\"\\n\\nRULES:\");\n\n // Use configurable rules\n const rules = resolveRulesTemplate(this.promptConfig.rules, context);\n\n for (const rule of rules) {\n parts.push(`\\n - ${rule}`);\n }\n\n return parts.join(\"\");\n }\n\n addUser(content: string, metadata?: Record<string, unknown>): this {\n this.messages.push({ role: \"user\", content, metadata });\n return this;\n }\n\n addAssistant(content: string, metadata?: Record<string, unknown>): this {\n this.messages.push({ role: \"assistant\", content, metadata });\n return this;\n }\n\n addGadgetCall(gadget: string, parameters: Record<string, unknown>, result: string) {\n const paramStr = this.formatBlockParameters(parameters, \"\");\n\n // Assistant message with simplified gadget markers (no invocation ID)\n this.messages.push({\n role: \"assistant\",\n content: `${this.startPrefix}${gadget}\\n${paramStr}\\n${this.endPrefix}`,\n });\n\n // User message with result\n this.messages.push({\n role: \"user\",\n content: `Result: ${result}`,\n });\n\n return this;\n }\n\n /**\n * Format parameters as Block format with JSON Pointer paths.\n * Uses the configured argPrefix for consistency with system prompt.\n */\n private formatBlockParameters(\n params: Record<string, unknown>,\n prefix: string,\n ): string {\n const lines: string[] = [];\n\n for (const [key, value] of Object.entries(params)) {\n const fullPath = prefix ? `${prefix}/${key}` : key;\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n const itemPath = `${fullPath}/${index}`;\n if (typeof item === \"object\" && item !== null) {\n lines.push(this.formatBlockParameters(item as Record<string, unknown>, itemPath));\n } else {\n lines.push(`${this.argPrefix}${itemPath}`);\n lines.push(String(item));\n }\n });\n } else if (typeof value === \"object\" && value !== null) {\n lines.push(this.formatBlockParameters(value as Record<string, unknown>, fullPath));\n } else {\n lines.push(`${this.argPrefix}${fullPath}`);\n lines.push(String(value));\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n build(): LLMMessage[] {\n return [...this.messages];\n }\n}\n\nexport const isLLMMessage = (value: unknown): value is LLMMessage => {\n if (typeof value !== \"object\" || value === null) {\n return false;\n }\n\n const message = value as Partial<LLMMessage>;\n return (\n (message.role === \"system\" || message.role === \"user\" || message.role === \"assistant\") &&\n typeof message.content === \"string\"\n );\n};\n","/**\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, GADGET_END_PREFIX, GADGET_START_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 a single parameter line with type info and description.\n * Helper function for formatSchemaAsPlainText.\n */\nfunction formatParamLine(\n key: string,\n propObj: Record<string, unknown>,\n isRequired: boolean,\n indent = \"\",\n): string {\n const type = propObj.type as string;\n const description = propObj.description as string | undefined;\n const enumValues = propObj.enum as string[] | undefined;\n\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 only for nested objects (not at root level where sections indicate this)\n if (isRequired && indent !== \"\") {\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 return line;\n}\n\n/**\n * Format JSON Schema as plain text description.\n * This presents parameters in a neutral, human-readable format\n * that complements the block format used for gadget invocation.\n */\nfunction formatSchemaAsPlainText(schema: Record<string, unknown>, indent = \"\", atRoot = true): string {\n const lines: string[] = [];\n const properties = (schema.properties || {}) as Record<string, unknown>;\n const required = (schema.required || []) as string[];\n\n // At root level: split required/optional\n if (atRoot && indent === \"\") {\n const requiredProps: [string, unknown][] = [];\n const optionalProps: [string, unknown][] = [];\n\n for (const [key, prop] of Object.entries(properties)) {\n if (required.includes(key)) {\n requiredProps.push([key, prop]);\n } else {\n optionalProps.push([key, prop]);\n }\n }\n\n const reqCount = requiredProps.length;\n const optCount = optionalProps.length;\n\n // Add count summary\n if (reqCount > 0 || optCount > 0) {\n const parts: string[] = [];\n if (reqCount > 0) parts.push(`${reqCount} required`);\n if (optCount > 0) parts.push(`${optCount} optional`);\n lines.push(parts.join(\", \"));\n lines.push(\"\"); // Blank line\n }\n\n // Render REQUIRED section\n if (reqCount > 0) {\n lines.push(\"REQUIRED Parameters:\");\n for (const [key, prop] of requiredProps) {\n lines.push(formatParamLine(key, prop as Record<string, unknown>, true, \"\"));\n // Handle nested objects\n const propObj = prop as Record<string, unknown>;\n if (propObj.type === \"object\" && propObj.properties) {\n lines.push(formatSchemaAsPlainText(propObj, \" \", false));\n }\n }\n }\n\n // Render OPTIONAL section\n if (optCount > 0) {\n if (reqCount > 0) lines.push(\"\"); // Blank line between sections\n lines.push(\"OPTIONAL Parameters:\");\n for (const [key, prop] of optionalProps) {\n lines.push(formatParamLine(key, prop as Record<string, unknown>, false, \"\"));\n // Handle nested objects\n const propObj = prop as Record<string, unknown>;\n if (propObj.type === \"object\" && propObj.properties) {\n lines.push(formatSchemaAsPlainText(propObj, \" \", false));\n }\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n // Nested objects: use current behavior (no split)\n for (const [key, prop] of Object.entries(properties)) {\n const isRequired = required.includes(key);\n lines.push(formatParamLine(key, prop as Record<string, unknown>, isRequired, indent));\n\n const propObj = prop as Record<string, unknown>;\n if (propObj.type === \"object\" && propObj.properties) {\n lines.push(formatSchemaAsPlainText(propObj, indent + \" \", false));\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 optionsOrArgPrefix - Optional custom prefixes for examples, or just argPrefix string for backwards compatibility\n * @returns Formatted instruction string\n */\n getInstruction(optionsOrArgPrefix?: string | { argPrefix?: string; startPrefix?: string; endPrefix?: string }): string {\n // Handle backwards compatibility: if string is passed, treat it as argPrefix\n const options = typeof optionsOrArgPrefix === \"string\"\n ? { argPrefix: optionsOrArgPrefix }\n : optionsOrArgPrefix;\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 prefixes if provided, otherwise use defaults\n const effectiveArgPrefix = options?.argPrefix ?? GADGET_ARG_PREFIX;\n const effectiveStartPrefix = options?.startPrefix ?? GADGET_START_PREFIX;\n const effectiveEndPrefix = options?.endPrefix ?? GADGET_END_PREFIX;\n const gadgetName = this.name || this.constructor.name;\n\n this.examples.forEach((example, index) => {\n // Add horizontal rule between examples (but not before the first one)\n if (index > 0) {\n parts.push(\"\");\n parts.push(\"---\");\n parts.push(\"\");\n }\n\n // Add comment if provided\n if (example.comment) {\n parts.push(`# ${example.comment}`);\n }\n\n // Add GADGET_START marker\n parts.push(`${effectiveStartPrefix}${gadgetName}`);\n\n // Render params in block format\n parts.push(formatParamsAsBlock(example.params as Record<string, unknown>, \"\", effectiveArgPrefix));\n\n // Add GADGET_END marker\n parts.push(effectiveEndPrefix);\n\n // Render output if provided\n if (example.output !== undefined) {\n parts.push(\"\"); // Blank line before output\n parts.push(\"Expected Output:\");\n parts.push(example.output);\n }\n });\n }\n\n return parts.join(\"\\n\");\n }\n}\n","/**\n * Function-based gadget creation helper.\n *\n * For simple gadgets, use createGadget() instead of defining a class.\n * Parameters are automatically typed from the Zod schema.\n *\n * @example\n * ```typescript\n * const calculator = createGadget({\n * description: \"Performs arithmetic operations\",\n * schema: z.object({\n * operation: z.enum([\"add\", \"subtract\"]),\n * a: z.number(),\n * b: z.number(),\n * }),\n * execute: ({ operation, a, b }) => {\n * // Automatically typed!\n * return operation === \"add\" ? String(a + b) : String(a - b);\n * },\n * });\n * ```\n */\n\nimport type { ZodType } from \"zod\";\nimport { BaseGadget } from \"./gadget.js\";\nimport type { GadgetExample } from \"./types.js\";\n\n/**\n * Infer the TypeScript type from a Zod schema.\n */\ntype InferSchema<T> = T extends ZodType<infer U> ? U : never;\n\n/**\n * Configuration for creating a function-based gadget.\n */\nexport interface CreateGadgetConfig<TSchema extends ZodType> {\n /** Optional custom name (defaults to \"FunctionGadget\") */\n name?: string;\n\n /** Human-readable description of what the gadget does */\n description: string;\n\n /** Zod schema for parameter validation */\n schema: TSchema;\n\n /** Execution function with typed parameters */\n execute: (params: InferSchema<TSchema>) => string | Promise<string>;\n\n /** Optional timeout in milliseconds */\n timeoutMs?: number;\n\n /** Optional usage examples to help LLMs understand proper invocation */\n examples?: GadgetExample<InferSchema<TSchema>>[];\n}\n\n/**\n * Creates a gadget from a function (simpler than class-based approach).\n *\n * This is perfect for simple gadgets where you don't need the full\n * power of a class. Parameters are automatically typed from the schema.\n *\n * @param config - Configuration with execute function and schema\n * @returns Gadget instance ready to be registered\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { createGadget } from 'llmist';\n *\n * // Simple calculator gadget\n * const calculator = createGadget({\n * description: \"Performs arithmetic operations\",\n * schema: z.object({\n * operation: z.enum([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n * a: z.number().describe(\"First number\"),\n * b: z.number().describe(\"Second number\"),\n * }),\n * execute: ({ operation, a, b }) => {\n * // Parameters are automatically typed!\n * switch (operation) {\n * case \"add\": return String(a + b);\n * case \"subtract\": return String(a - b);\n * case \"multiply\": return String(a * b);\n * case \"divide\": return String(a / b);\n * }\n * },\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Async gadget with custom name and timeout\n * const weather = createGadget({\n * name: \"weather\",\n * description: \"Fetches current weather for a city\",\n * schema: z.object({\n * city: z.string().min(1).describe(\"City name\"),\n * }),\n * timeoutMs: 10000,\n * execute: async ({ city }) => {\n * const response = await fetch(`https://api.weather.com/${city}`);\n * const data = await response.json();\n * return `Weather in ${city}: ${data.description}, ${data.temp}°C`;\n * },\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Use with agent\n * const agent = LLMist.createAgent()\n * .withGadgets(calculator, weather)\n * .ask(\"What's the weather in Paris and what's 10 + 5?\");\n * ```\n */\nexport function createGadget<TSchema extends ZodType>(\n config: CreateGadgetConfig<TSchema>,\n): BaseGadget {\n class DynamicGadget extends BaseGadget {\n name = config.name;\n description = config.description;\n parameterSchema = config.schema;\n timeoutMs = config.timeoutMs;\n examples = config.examples;\n\n execute(params: Record<string, unknown>): string | Promise<string> {\n // Cast to inferred type and call user's function\n return config.execute(params as InferSchema<TSchema>);\n }\n }\n\n return new DynamicGadget();\n}\n","/**\n * GadgetOutputViewer - Browse stored outputs from gadgets that exceeded the size limit.\n *\n * When a gadget returns too much data, the output is stored and can be browsed\n * using this gadget with grep-like pattern filtering and line limiting.\n */\n\nimport { z } from \"zod\";\nimport type { GadgetOutputStore } from \"../agent/gadget-output-store.js\";\nimport { createGadget } from \"./create-gadget.js\";\n\n/**\n * Pattern filter configuration.\n */\ninterface PatternFilter {\n /** Regular expression to match */\n regex: string;\n /** true = keep matches, false = exclude matches */\n include: boolean;\n /** Context lines before match (like grep -B) */\n before: number;\n /** Context lines after match (like grep -A) */\n after: number;\n}\n\n/**\n * Apply a single pattern filter to lines.\n *\n * For include=true: keeps lines that match (with before/after context).\n * For include=false: removes lines that match.\n */\nfunction applyPattern(lines: string[], pattern: PatternFilter): string[] {\n const regex = new RegExp(pattern.regex);\n\n if (!pattern.include) {\n // Exclude mode: remove matching lines\n return lines.filter((line) => !regex.test(line));\n }\n\n // Include mode: keep matching lines with context\n const matchIndices = new Set<number>();\n\n // Find all matching line indices\n for (let i = 0; i < lines.length; i++) {\n if (regex.test(lines[i])) {\n // Add the matching line and its context\n const start = Math.max(0, i - pattern.before);\n const end = Math.min(lines.length - 1, i + pattern.after);\n for (let j = start; j <= end; j++) {\n matchIndices.add(j);\n }\n }\n }\n\n // Return lines at matching indices (preserving order)\n return lines.filter((_, index) => matchIndices.has(index));\n}\n\n/**\n * Apply multiple pattern filters in sequence (like piping through grep commands).\n */\nfunction applyPatterns(lines: string[], patterns: PatternFilter[]): string[] {\n let result = lines;\n for (const pattern of patterns) {\n result = applyPattern(result, pattern);\n }\n return result;\n}\n\n/**\n * Parse and apply a line limit string.\n *\n * Formats:\n * - \"100-\" → first 100 lines (slice 0 to 100)\n * - \"-25\" → last 25 lines (slice -25)\n * - \"50-100\" → lines 50-100 (1-indexed, so slice 49 to 100)\n */\nfunction applyLineLimit(lines: string[], limit: string): string[] {\n const trimmed = limit.trim();\n\n // Format: \"100-\" (first N lines)\n if (trimmed.endsWith(\"-\") && !trimmed.startsWith(\"-\")) {\n const n = parseInt(trimmed.slice(0, -1), 10);\n if (!isNaN(n) && n > 0) {\n return lines.slice(0, n);\n }\n }\n\n // Format: \"-25\" (last N lines)\n if (trimmed.startsWith(\"-\") && !trimmed.includes(\"-\", 1)) {\n const n = parseInt(trimmed, 10);\n if (!isNaN(n) && n < 0) {\n return lines.slice(n);\n }\n }\n\n // Format: \"50-100\" (range, 1-indexed)\n const rangeMatch = trimmed.match(/^(\\d+)-(\\d+)$/);\n if (rangeMatch) {\n const start = parseInt(rangeMatch[1], 10);\n const end = parseInt(rangeMatch[2], 10);\n if (!isNaN(start) && !isNaN(end) && start > 0 && end >= start) {\n // Convert from 1-indexed to 0-indexed\n return lines.slice(start - 1, end);\n }\n }\n\n // Invalid format - return unchanged\n return lines;\n}\n\n/**\n * Schema for pattern filter objects.\n */\nconst patternSchema = z.object({\n regex: z.string().describe(\"Regular expression to match\"),\n include: z\n .boolean()\n .default(true)\n .describe(\"true = keep matching lines, false = exclude matching lines\"),\n before: z\n .number()\n .int()\n .min(0)\n .default(0)\n .describe(\"Context lines before each match (like grep -B)\"),\n after: z\n .number()\n .int()\n .min(0)\n .default(0)\n .describe(\"Context lines after each match (like grep -A)\"),\n});\n\n/**\n * Create a GadgetOutputViewer gadget instance bound to a specific output store.\n *\n * This is a factory function because the gadget needs access to the output store,\n * which is created per-agent-run.\n *\n * @param store - The GadgetOutputStore to read outputs from\n * @returns A GadgetOutputViewer gadget instance\n *\n * @example\n * ```typescript\n * const store = new GadgetOutputStore();\n * const viewer = createGadgetOutputViewer(store);\n * registry.register(\"GadgetOutputViewer\", viewer);\n * ```\n */\nexport function createGadgetOutputViewer(store: GadgetOutputStore) {\n return createGadget({\n name: \"GadgetOutputViewer\",\n description:\n \"View stored output from gadgets that returned too much data. \" +\n \"Use patterns to filter lines (like grep) and limit to control output size. \" +\n \"Patterns are applied first in order, then the limit is applied to the result.\",\n schema: z.object({\n id: z.string().describe(\"ID of the stored output (from the truncation message)\"),\n patterns: z\n .array(patternSchema)\n .optional()\n .describe(\n \"Filter patterns applied in order (like piping through grep). \" +\n \"Each pattern can include or exclude lines with optional before/after context.\",\n ),\n limit: z\n .string()\n .optional()\n .describe(\n \"Line range to return after filtering. \" +\n \"Formats: '100-' (first 100), '-25' (last 25), '50-100' (lines 50-100)\",\n ),\n }),\n examples: [\n {\n comment: \"View first 50 lines of stored output\",\n params: { id: \"Search_abc12345\", limit: \"50-\" },\n },\n {\n comment: \"Filter for error lines with context\",\n params: {\n id: \"Search_abc12345\",\n patterns: [{ regex: \"error|Error|ERROR\", include: true, before: 2, after: 5 }],\n },\n },\n {\n comment: \"Exclude blank lines, then show first 100\",\n params: {\n id: \"Search_abc12345\",\n patterns: [{ regex: \"^\\\\s*$\", include: false, before: 0, after: 0 }],\n limit: \"100-\",\n },\n },\n {\n comment: \"Chain filters: find TODOs, exclude tests, limit to 50 lines\",\n params: {\n id: \"Search_abc12345\",\n patterns: [\n { regex: \"TODO\", include: true, before: 1, after: 1 },\n { regex: \"test|spec\", include: false, before: 0, after: 0 },\n ],\n limit: \"50-\",\n },\n },\n ],\n execute: ({ id, patterns, limit }) => {\n const stored = store.get(id);\n if (!stored) {\n return `Error: No stored output with id \"${id}\". Available IDs: ${store.getIds().join(\", \") || \"(none)\"}`;\n }\n\n let lines = stored.content.split(\"\\n\");\n\n // Step 1: Apply patterns in order (like piping through grep)\n if (patterns && patterns.length > 0) {\n lines = applyPatterns(\n lines,\n patterns.map((p) => ({\n regex: p.regex,\n include: p.include ?? true,\n before: p.before ?? 0,\n after: p.after ?? 0,\n })),\n );\n }\n\n // Step 2: Apply line limit AFTER all patterns\n if (limit) {\n lines = applyLineLimit(lines, limit);\n }\n\n // Return result with metadata\n const totalLines = stored.lineCount;\n const returnedLines = lines.length;\n\n if (returnedLines === 0) {\n return `No lines matched the filters. Original output had ${totalLines} lines.`;\n }\n\n const header =\n returnedLines < totalLines\n ? `[Showing ${returnedLines} of ${totalLines} lines]\\n`\n : `[Showing all ${totalLines} lines]\\n`;\n\n return header + lines.join(\"\\n\");\n },\n });\n}\n\n// Export helpers for testing\nexport { applyPattern, applyPatterns, applyLineLimit };\n","/**\n * Configuration types for the context compaction system.\n *\n * Context compaction automatically manages conversation history to prevent\n * context window overflow in long-running agent conversations.\n */\n\nimport type { CompactionStrategy } from \"./strategy.js\";\n\n/**\n * Event emitted when compaction occurs.\n * This is included in StreamEvent for UI visibility.\n */\nexport interface CompactionEvent {\n /** The strategy that performed the compaction */\n strategy: string;\n /** Token count before compaction */\n tokensBefore: number;\n /** Token count after compaction */\n tokensAfter: number;\n /** Number of messages before compaction */\n messagesBefore: number;\n /** Number of messages after compaction */\n messagesAfter: number;\n /** Summary text if summarization was used */\n summary?: string;\n /** Agent iteration when compaction occurred */\n iteration: number;\n}\n\n/**\n * Statistics about compaction activity.\n */\nexport interface CompactionStats {\n /** Total number of compactions performed */\n totalCompactions: number;\n /** Total tokens saved across all compactions */\n totalTokensSaved: number;\n /** Current context usage */\n currentUsage: {\n tokens: number;\n percent: number;\n };\n /** Model's context window size */\n contextWindow: number;\n}\n\n/**\n * Configuration for the context compaction system.\n *\n * @example\n * ```typescript\n * // Custom configuration\n * const agent = await LLMist.createAgent()\n * .withModel('sonnet')\n * .withCompaction({\n * triggerThresholdPercent: 70,\n * targetPercent: 40,\n * preserveRecentTurns: 10,\n * })\n * .ask('...');\n *\n * // Disable compaction\n * const agent = await LLMist.createAgent()\n * .withModel('sonnet')\n * .withoutCompaction()\n * .ask('...');\n * ```\n */\nexport interface CompactionConfig {\n /**\n * Enable or disable compaction.\n * @default true\n */\n enabled?: boolean;\n\n /**\n * The compaction strategy to use.\n * - 'sliding-window': Fast, drops oldest turns (no LLM call)\n * - 'summarization': LLM-based compression of old messages\n * - 'hybrid': Summarizes old messages + keeps recent turns (recommended)\n * - Or provide a custom CompactionStrategy instance\n * @default 'hybrid'\n */\n strategy?: \"sliding-window\" | \"summarization\" | \"hybrid\" | CompactionStrategy;\n\n /**\n * Context usage percentage that triggers compaction.\n * When token count exceeds this percentage of the context window,\n * compaction is performed before the next LLM call.\n * @default 80\n */\n triggerThresholdPercent?: number;\n\n /**\n * Target context usage percentage after compaction.\n * The compaction will aim to reduce tokens to this percentage.\n * @default 50\n */\n targetPercent?: number;\n\n /**\n * Number of recent turns to preserve during compaction.\n * A \"turn\" is a user message + assistant response pair.\n * Recent turns are kept verbatim while older ones are summarized/dropped.\n * @default 5\n */\n preserveRecentTurns?: number;\n\n /**\n * Model to use for summarization.\n * If not specified, uses the agent's model.\n * @default undefined (uses agent's model)\n */\n summarizationModel?: string;\n\n /**\n * Custom system prompt for summarization.\n * If not specified, uses a default prompt optimized for context preservation.\n */\n summarizationPrompt?: string;\n\n /**\n * Callback invoked when compaction occurs.\n * Useful for logging or analytics.\n */\n onCompaction?: (event: CompactionEvent) => void;\n}\n\n/**\n * Default configuration values for compaction.\n * Compaction is enabled by default with the hybrid strategy.\n */\nexport const DEFAULT_COMPACTION_CONFIG: Required<\n Omit<CompactionConfig, \"summarizationModel\" | \"summarizationPrompt\" | \"onCompaction\">\n> = {\n enabled: true,\n strategy: \"hybrid\",\n triggerThresholdPercent: 80,\n targetPercent: 50,\n preserveRecentTurns: 5,\n};\n\n/**\n * Default prompt used for summarization strategy.\n */\nexport const DEFAULT_SUMMARIZATION_PROMPT = `Summarize this conversation history concisely, preserving:\n1. Key decisions made and their rationale\n2. Important facts and data discovered\n3. Errors encountered and how they were resolved\n4. Current task context and goals\n\nFormat as a brief narrative paragraph, not bullet points.\nPrevious conversation:`;\n\n/**\n * Resolved configuration with all defaults applied.\n */\nexport interface ResolvedCompactionConfig {\n enabled: boolean;\n strategy: \"sliding-window\" | \"summarization\" | \"hybrid\";\n triggerThresholdPercent: number;\n targetPercent: number;\n preserveRecentTurns: number;\n summarizationModel?: string;\n summarizationPrompt: string;\n onCompaction?: (event: CompactionEvent) => void;\n}\n\n/**\n * Resolves partial configuration with defaults.\n */\nexport function resolveCompactionConfig(\n config: CompactionConfig = {},\n): ResolvedCompactionConfig {\n const trigger =\n config.triggerThresholdPercent ?? DEFAULT_COMPACTION_CONFIG.triggerThresholdPercent;\n const target = config.targetPercent ?? DEFAULT_COMPACTION_CONFIG.targetPercent;\n\n // Warn about potentially misconfigured thresholds\n if (target >= trigger) {\n console.warn(\n `[llmist/compaction] targetPercent (${target}) should be less than triggerThresholdPercent (${trigger}) to be effective.`,\n );\n }\n\n // Handle custom strategy instances vs string names\n const strategy = config.strategy ?? DEFAULT_COMPACTION_CONFIG.strategy;\n const strategyName =\n typeof strategy === \"object\" && \"name\" in strategy\n ? (strategy.name as \"sliding-window\" | \"summarization\" | \"hybrid\")\n : strategy;\n\n return {\n enabled: config.enabled ?? DEFAULT_COMPACTION_CONFIG.enabled,\n strategy: strategyName,\n triggerThresholdPercent: trigger,\n targetPercent: target,\n preserveRecentTurns:\n config.preserveRecentTurns ?? DEFAULT_COMPACTION_CONFIG.preserveRecentTurns,\n summarizationModel: config.summarizationModel,\n summarizationPrompt: config.summarizationPrompt ?? DEFAULT_SUMMARIZATION_PROMPT,\n onCompaction: config.onCompaction,\n };\n}\n","/**\n * Strategy interface for context compaction.\n *\n * Strategies define how conversation history is compressed to fit within\n * context window limits. Different strategies trade off between:\n * - Speed (LLM calls vs local processing)\n * - Context preservation (summary quality vs simple truncation)\n * - Cost (summarization model usage)\n */\n\nimport type { LLMist } from \"../../core/client.js\";\nimport type { LLMMessage } from \"../../core/messages.js\";\nimport type { ModelLimits } from \"../../core/model-catalog.js\";\nimport type { ResolvedCompactionConfig } from \"./config.js\";\n\n/**\n * Context provided to compaction strategies.\n */\nexport interface CompactionContext {\n /** Current token count of the conversation */\n currentTokens: number;\n /** Target token count after compaction */\n targetTokens: number;\n /** Model's context window limits */\n modelLimits: ModelLimits;\n /** LLMist client for summarization calls */\n client: LLMist;\n /** Model identifier for token counting and summarization */\n model: string;\n}\n\n/**\n * Result of a compaction operation.\n */\nexport interface CompactionResult {\n /** Compacted messages to replace history with */\n messages: LLMMessage[];\n /** Summary text if summarization was used */\n summary?: string;\n /** The name of the strategy that was ultimately executed */\n strategyName: string;\n /** Metadata about the compaction */\n metadata: {\n /** Number of messages before compaction */\n originalCount: number;\n /** Number of messages after compaction */\n compactedCount: number;\n /** Estimated tokens before compaction */\n tokensBefore: number;\n /** Estimated tokens after compaction */\n tokensAfter: number;\n };\n}\n\n/**\n * Interface for compaction strategy implementations.\n *\n * Strategies receive the conversation history (excluding base messages like\n * system prompt and gadget instructions) and must return a compacted version.\n *\n * @example\n * ```typescript\n * class MyCustomStrategy implements CompactionStrategy {\n * readonly name = 'my-custom';\n *\n * async compact(\n * messages: LLMMessage[],\n * config: ResolvedCompactionConfig,\n * context: CompactionContext\n * ): Promise<CompactionResult> {\n * // Custom compaction logic\n * return {\n * messages: compactedMessages,\n * metadata: { ... }\n * };\n * }\n * }\n * ```\n */\nexport interface CompactionStrategy {\n /** Human-readable name of the strategy */\n readonly name: string;\n\n /**\n * Compact the given messages to fit within target token count.\n *\n * @param messages - Conversation history messages (excludes system/gadget base)\n * @param config - Resolved compaction configuration\n * @param context - Context including token counts and LLM client\n * @returns Compacted messages with metadata\n */\n compact(\n messages: LLMMessage[],\n config: ResolvedCompactionConfig,\n context: CompactionContext,\n ): Promise<CompactionResult>;\n}\n\n/**\n * Utility to group messages into logical conversation turns.\n *\n * A \"turn\" is typically a user message followed by an assistant response.\n * Gadget calls are grouped with the preceding assistant message.\n */\nexport interface MessageTurn {\n /** Messages in this turn (user + assistant + any gadget results) */\n messages: LLMMessage[];\n /** Estimated token count for this turn */\n tokenEstimate: number;\n}\n\n/**\n * Groups messages into logical conversation turns.\n *\n * Rules:\n * - A turn starts with a user message\n * - A turn includes all subsequent assistant messages until the next user message\n * - The first message(s) before any user message are considered \"preamble\"\n *\n * @param messages - Array of conversation messages\n * @returns Array of message turns\n */\nexport function groupIntoTurns(messages: LLMMessage[]): MessageTurn[] {\n const turns: MessageTurn[] = [];\n let currentTurn: LLMMessage[] = [];\n\n for (const msg of messages) {\n if (msg.role === \"user\" && currentTurn.length > 0) {\n // Start new turn - save current one\n turns.push({\n messages: currentTurn,\n tokenEstimate: estimateTurnTokens(currentTurn),\n });\n currentTurn = [msg];\n } else {\n currentTurn.push(msg);\n }\n }\n\n // Don't forget the last turn\n if (currentTurn.length > 0) {\n turns.push({\n messages: currentTurn,\n tokenEstimate: estimateTurnTokens(currentTurn),\n });\n }\n\n return turns;\n}\n\n/**\n * Rough token estimation for a turn (4 chars per token).\n */\nfunction estimateTurnTokens(messages: LLMMessage[]): number {\n return Math.ceil(messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4);\n}\n\n/**\n * Flattens turns back into a message array.\n */\nexport function flattenTurns(turns: MessageTurn[]): LLMMessage[] {\n return turns.flatMap((turn) => turn.messages);\n}\n","/**\n * Sliding Window Compaction Strategy\n *\n * A fast, no-LLM-call strategy that simply keeps the most recent N turns\n * and drops older ones. Best for:\n * - Long-running conversations where older context becomes irrelevant\n * - Scenarios requiring minimal latency\n * - As a fallback when summarization is too slow\n */\n\nimport type { LLMMessage } from \"../../../core/messages.js\";\nimport type { ResolvedCompactionConfig } from \"../config.js\";\nimport {\n type CompactionContext,\n type CompactionResult,\n type CompactionStrategy,\n flattenTurns,\n groupIntoTurns,\n} from \"../strategy.js\";\n\n/**\n * Marker message inserted to indicate truncation.\n */\nconst TRUNCATION_MARKER_TEMPLATE = \"[Previous conversation truncated. Removed {count} turn(s) to fit context window.]\";\n\n/**\n * Sliding window strategy - keeps recent turns, drops older ones.\n *\n * This strategy:\n * 1. Groups messages into logical turns (user + assistant pairs)\n * 2. Keeps the `preserveRecentTurns` most recent turns\n * 3. Inserts a truncation marker at the beginning\n * 4. Requires no LLM call - very fast\n */\nexport class SlidingWindowStrategy implements CompactionStrategy {\n readonly name = \"sliding-window\";\n\n async compact(\n messages: LLMMessage[],\n config: ResolvedCompactionConfig,\n context: CompactionContext,\n ): Promise<CompactionResult> {\n const turns = groupIntoTurns(messages);\n const preserveCount = Math.min(config.preserveRecentTurns, turns.length);\n\n // If we have fewer turns than the preserve count, nothing to compact\n if (turns.length <= preserveCount) {\n return {\n messages,\n strategyName: this.name,\n metadata: {\n originalCount: messages.length,\n compactedCount: messages.length,\n tokensBefore: context.currentTokens,\n tokensAfter: context.currentTokens,\n },\n };\n }\n\n // Keep only the most recent turns\n const turnsToKeep = turns.slice(-preserveCount);\n const turnsRemoved = turns.length - preserveCount;\n\n // Create truncation marker\n const truncationMarker: LLMMessage = {\n role: \"user\",\n content: TRUNCATION_MARKER_TEMPLATE.replace(\"{count}\", turnsRemoved.toString()),\n };\n\n // Build compacted message list\n const compactedMessages: LLMMessage[] = [truncationMarker, ...flattenTurns(turnsToKeep)];\n\n // Estimate new token count\n const tokensAfter = Math.ceil(\n compactedMessages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4,\n );\n\n return {\n messages: compactedMessages,\n strategyName: this.name,\n metadata: {\n originalCount: messages.length,\n compactedCount: compactedMessages.length,\n tokensBefore: context.currentTokens,\n tokensAfter,\n },\n };\n }\n}\n","/**\n * Summarization Compaction Strategy\n *\n * Uses an LLM to summarize older conversation messages into a concise summary.\n * Best for:\n * - Tasks where historical context matters\n * - Complex multi-step reasoning\n * - When accuracy is more important than speed\n */\n\nimport type { LLMMessage } from \"../../../core/messages.js\";\nimport type { ResolvedCompactionConfig } from \"../config.js\";\nimport {\n type CompactionContext,\n type CompactionResult,\n type CompactionStrategy,\n flattenTurns,\n groupIntoTurns,\n} from \"../strategy.js\";\n\n/**\n * Summarization strategy - uses LLM to compress conversation history.\n *\n * This strategy:\n * 1. Groups messages into logical turns\n * 2. Keeps recent turns intact\n * 3. Summarizes older turns using LLM\n * 4. Returns summary + recent turns\n */\nexport class SummarizationStrategy implements CompactionStrategy {\n readonly name = \"summarization\";\n\n async compact(\n messages: LLMMessage[],\n config: ResolvedCompactionConfig,\n context: CompactionContext,\n ): Promise<CompactionResult> {\n const turns = groupIntoTurns(messages);\n const preserveCount = Math.min(config.preserveRecentTurns, turns.length);\n\n // If we have fewer turns than the preserve count, nothing to compact\n if (turns.length <= preserveCount) {\n return {\n messages,\n strategyName: this.name,\n metadata: {\n originalCount: messages.length,\n compactedCount: messages.length,\n tokensBefore: context.currentTokens,\n tokensAfter: context.currentTokens,\n },\n };\n }\n\n // Split into turns to summarize and turns to keep\n const turnsToSummarize = turns.slice(0, -preserveCount);\n const turnsToKeep = turns.slice(-preserveCount);\n\n // Build conversation text to summarize\n const conversationToSummarize = this.formatTurnsForSummary(flattenTurns(turnsToSummarize));\n\n // Generate summary using LLM\n const summary = await this.generateSummary(conversationToSummarize, config, context);\n\n // Create summary message\n const summaryMessage: LLMMessage = {\n role: \"user\",\n content: `[Previous conversation summary]\\n${summary}\\n[End of summary - conversation continues below]`,\n };\n\n // Build compacted message list\n const compactedMessages: LLMMessage[] = [summaryMessage, ...flattenTurns(turnsToKeep)];\n\n // Estimate new token count\n const tokensAfter = Math.ceil(\n compactedMessages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4,\n );\n\n return {\n messages: compactedMessages,\n summary,\n strategyName: this.name,\n metadata: {\n originalCount: messages.length,\n compactedCount: compactedMessages.length,\n tokensBefore: context.currentTokens,\n tokensAfter,\n },\n };\n }\n\n /**\n * Formats messages into a readable conversation format for summarization.\n */\n private formatTurnsForSummary(messages: LLMMessage[]): string {\n return messages\n .map((msg) => {\n const role = msg.role.charAt(0).toUpperCase() + msg.role.slice(1);\n return `${role}: ${msg.content}`;\n })\n .join(\"\\n\\n\");\n }\n\n /**\n * Generates a summary using the configured LLM.\n */\n private async generateSummary(\n conversation: string,\n config: ResolvedCompactionConfig,\n context: CompactionContext,\n ): Promise<string> {\n const model = config.summarizationModel ?? context.model;\n const prompt = `${config.summarizationPrompt}\\n\\n${conversation}`;\n\n // Use the LLMist client's complete method for summarization\n const response = await context.client.complete(prompt, {\n model,\n temperature: 0.3, // Low temperature for factual summarization\n });\n\n return response.trim();\n }\n}\n","/**\n * Hybrid Compaction Strategy\n *\n * Combines sliding window and summarization for the best of both worlds:\n * 1. Identifies which turns to compact vs keep (like sliding window)\n * 2. Summarizes the older turns (like summarization)\n * 3. Returns summary + recent turns intact\n *\n * Falls back to sliding window if there are too few turns to summarize.\n */\n\nimport type { LLMMessage } from \"../../../core/messages.js\";\nimport type { ResolvedCompactionConfig } from \"../config.js\";\nimport {\n type CompactionContext,\n type CompactionResult,\n type CompactionStrategy,\n groupIntoTurns,\n} from \"../strategy.js\";\nimport { SlidingWindowStrategy } from \"./sliding-window.js\";\nimport { SummarizationStrategy } from \"./summarization.js\";\n\n/**\n * Minimum turns needed to make summarization worthwhile.\n * Below this threshold, we fall back to sliding window.\n */\nconst MIN_TURNS_FOR_SUMMARIZATION = 3;\n\n/**\n * Hybrid strategy - summarizes old turns + keeps recent turns.\n *\n * This is the recommended default strategy as it:\n * - Preserves important historical context via summarization\n * - Keeps recent conversation turns verbatim for continuity\n * - Falls back gracefully to sliding window when appropriate\n */\nexport class HybridStrategy implements CompactionStrategy {\n readonly name = \"hybrid\";\n\n private readonly slidingWindow = new SlidingWindowStrategy();\n private readonly summarization = new SummarizationStrategy();\n\n async compact(\n messages: LLMMessage[],\n config: ResolvedCompactionConfig,\n context: CompactionContext,\n ): Promise<CompactionResult> {\n const turns = groupIntoTurns(messages);\n const preserveCount = Math.min(config.preserveRecentTurns, turns.length);\n\n // If we have fewer turns than the preserve count, nothing to compact\n if (turns.length <= preserveCount) {\n return {\n messages,\n strategyName: this.name,\n metadata: {\n originalCount: messages.length,\n compactedCount: messages.length,\n tokensBefore: context.currentTokens,\n tokensAfter: context.currentTokens,\n },\n };\n }\n\n // Calculate how many turns would be summarized\n const turnsToSummarize = turns.length - preserveCount;\n\n // If there are too few turns to summarize, use sliding window instead\n if (turnsToSummarize < MIN_TURNS_FOR_SUMMARIZATION) {\n // Delegate to sliding window - propagate its strategyName for accurate reporting\n return this.slidingWindow.compact(messages, config, context);\n }\n\n // Use summarization for older turns - propagate its strategyName\n return this.summarization.compact(messages, config, context);\n }\n}\n","/**\n * Compaction Strategy Implementations\n *\n * Available strategies:\n * - SlidingWindowStrategy: Fast, drops oldest turns (no LLM call)\n * - SummarizationStrategy: LLM-based compression\n * - HybridStrategy: Summarizes old + keeps recent (recommended)\n */\n\nexport { SlidingWindowStrategy } from \"./sliding-window.js\";\nexport { SummarizationStrategy } from \"./summarization.js\";\nexport { HybridStrategy } from \"./hybrid.js\";\n","/**\n * CompactionManager - Central orchestrator for context compaction.\n *\n * Monitors token usage and coordinates compaction strategies to keep\n * conversation context within model limits.\n */\n\nimport type { LLMist } from \"../../core/client.js\";\nimport type { ModelLimits } from \"../../core/model-catalog.js\";\nimport type { IConversationManager } from \"../interfaces.js\";\nimport {\n type CompactionConfig,\n type CompactionEvent,\n type CompactionStats,\n type ResolvedCompactionConfig,\n resolveCompactionConfig,\n} from \"./config.js\";\nimport type { CompactionStrategy } from \"./strategy.js\";\nimport type { LLMMessage } from \"../../core/messages.js\";\nimport { HybridStrategy, SlidingWindowStrategy, SummarizationStrategy } from \"./strategies/index.js\";\n\n/**\n * Pre-computed token counts to avoid redundant counting.\n * Passed from checkAndCompact to compact for efficiency.\n */\ninterface PrecomputedTokens {\n historyMessages: LLMMessage[];\n baseMessages: LLMMessage[];\n historyTokens: number;\n baseTokens: number;\n currentTokens: number;\n}\n\n/**\n * Creates a strategy instance from a strategy name.\n */\nfunction createStrategy(name: string): CompactionStrategy {\n switch (name) {\n case \"sliding-window\":\n return new SlidingWindowStrategy();\n case \"summarization\":\n return new SummarizationStrategy();\n case \"hybrid\":\n return new HybridStrategy();\n default:\n throw new Error(`Unknown compaction strategy: ${name}`);\n }\n}\n\n/**\n * CompactionManager orchestrates context compaction for an agent.\n *\n * It:\n * - Monitors token usage before each LLM call\n * - Triggers compaction when threshold is exceeded\n * - Coordinates with ConversationManager to update history\n * - Tracks statistics for observability\n */\nexport class CompactionManager {\n private readonly client: LLMist;\n private readonly model: string;\n private readonly config: ResolvedCompactionConfig;\n private readonly strategy: CompactionStrategy;\n private modelLimits?: ModelLimits;\n\n // Statistics\n private totalCompactions = 0;\n private totalTokensSaved = 0;\n private lastTokenCount = 0;\n\n constructor(client: LLMist, model: string, config: CompactionConfig = {}) {\n this.client = client;\n this.model = model;\n this.config = resolveCompactionConfig(config);\n\n // Create strategy instance (support both string name and custom instance)\n if (typeof config.strategy === \"object\" && \"compact\" in config.strategy) {\n this.strategy = config.strategy as CompactionStrategy;\n } else {\n this.strategy = createStrategy(this.config.strategy);\n }\n }\n\n /**\n * Check if compaction is needed and perform it if so.\n *\n * @param conversation - The conversation manager to compact\n * @param iteration - Current agent iteration (for event metadata)\n * @returns CompactionEvent if compaction was performed, null otherwise\n */\n async checkAndCompact(\n conversation: IConversationManager,\n iteration: number,\n ): Promise<CompactionEvent | null> {\n if (!this.config.enabled) {\n return null;\n }\n\n // Get model limits (cached after first call)\n if (!this.modelLimits) {\n this.modelLimits = this.client.modelRegistry.getModelLimits(this.model);\n if (!this.modelLimits) {\n // Model not found in registry, skip compaction silently\n // This is not an error - it just means we can't determine context limits\n return null;\n }\n }\n\n // Count current tokens (skip if client doesn't support token counting)\n if (!this.client.countTokens) {\n return null;\n }\n const messages = conversation.getMessages();\n const currentTokens = await this.client.countTokens(this.model, messages);\n this.lastTokenCount = currentTokens;\n\n // Calculate usage percentage\n const usagePercent = (currentTokens / this.modelLimits.contextWindow) * 100;\n\n // Check if we need to compact\n if (usagePercent < this.config.triggerThresholdPercent) {\n return null;\n }\n\n // Perform compaction with precomputed token counts to avoid redundant counting\n const historyMessages = conversation.getHistoryMessages();\n const baseMessages = conversation.getBaseMessages();\n const historyTokens = await this.client.countTokens(this.model, historyMessages);\n const baseTokens = await this.client.countTokens(this.model, baseMessages);\n\n return this.compact(conversation, iteration, {\n historyMessages,\n baseMessages,\n historyTokens,\n baseTokens,\n currentTokens: historyTokens + baseTokens,\n });\n }\n\n /**\n * Force compaction regardless of threshold.\n *\n * @param conversation - The conversation manager to compact\n * @param iteration - Current agent iteration (for event metadata). Use -1 for manual compaction.\n * @param precomputed - Optional pre-computed token counts (passed from checkAndCompact for efficiency)\n * @returns CompactionEvent with compaction details\n */\n async compact(\n conversation: IConversationManager,\n iteration: number,\n precomputed?: PrecomputedTokens,\n ): Promise<CompactionEvent | null> {\n if (!this.modelLimits) {\n this.modelLimits = this.client.modelRegistry.getModelLimits(this.model);\n if (!this.modelLimits) {\n return null;\n }\n }\n\n // Use precomputed values if available, otherwise compute them\n const historyMessages = precomputed?.historyMessages ?? conversation.getHistoryMessages();\n const baseMessages = precomputed?.baseMessages ?? conversation.getBaseMessages();\n const historyTokens =\n precomputed?.historyTokens ?? (await this.client.countTokens(this.model, historyMessages));\n const baseTokens =\n precomputed?.baseTokens ?? (await this.client.countTokens(this.model, baseMessages));\n const currentTokens = precomputed?.currentTokens ?? historyTokens + baseTokens;\n\n // Calculate target tokens for history (leaving room for base messages and output)\n const targetTotalTokens = Math.floor(\n (this.modelLimits.contextWindow * this.config.targetPercent) / 100,\n );\n const targetHistoryTokens = Math.max(0, targetTotalTokens - baseTokens);\n\n // Run the compaction strategy\n const result = await this.strategy.compact(historyMessages, this.config, {\n currentTokens: historyTokens,\n targetTokens: targetHistoryTokens,\n modelLimits: this.modelLimits,\n client: this.client,\n model: this.config.summarizationModel ?? this.model,\n });\n\n // Replace the conversation history\n conversation.replaceHistory(result.messages);\n\n // Count tokens after compaction\n const afterTokens = await this.client.countTokens(this.model, conversation.getMessages());\n const tokensSaved = currentTokens - afterTokens;\n\n // Update statistics\n this.totalCompactions++;\n this.totalTokensSaved += tokensSaved;\n this.lastTokenCount = afterTokens;\n\n // Create event - use result.strategyName for accurate reporting (e.g., when hybrid falls back to sliding-window)\n const event: CompactionEvent = {\n strategy: result.strategyName,\n tokensBefore: currentTokens,\n tokensAfter: afterTokens,\n messagesBefore: historyMessages.length + baseMessages.length,\n messagesAfter: result.messages.length + baseMessages.length,\n summary: result.summary,\n iteration,\n };\n\n // Call onCompaction callback if provided\n if (this.config.onCompaction) {\n try {\n this.config.onCompaction(event);\n } catch (err) {\n console.warn(\"[llmist/compaction] onCompaction callback error:\", err);\n }\n }\n\n return event;\n }\n\n /**\n * Get compaction statistics.\n */\n getStats(): CompactionStats {\n const contextWindow = this.modelLimits?.contextWindow ?? 0;\n return {\n totalCompactions: this.totalCompactions,\n totalTokensSaved: this.totalTokensSaved,\n currentUsage: {\n tokens: this.lastTokenCount,\n percent: contextWindow > 0 ? (this.lastTokenCount / contextWindow) * 100 : 0,\n },\n contextWindow,\n };\n }\n\n /**\n * Check if compaction is enabled.\n */\n isEnabled(): boolean {\n return this.config.enabled;\n }\n}\n","/**\n * Storage for large gadget outputs that exceed the configured limit.\n *\n * When a gadget returns more data than the configured limit, the output\n * is stored here and can be browsed later using GadgetOutputViewer.\n */\n\nimport { randomBytes } from \"node:crypto\";\n\n/**\n * Metadata and content for a stored gadget output.\n */\nexport interface StoredOutput {\n /** Unique identifier (e.g., \"Search_d34db33f\") */\n id: string;\n /** Name of the gadget that produced this output */\n gadgetName: string;\n /** Full output content */\n content: string;\n /** Size in bytes */\n byteSize: number;\n /** Number of lines */\n lineCount: number;\n /** When the output was stored */\n timestamp: Date;\n}\n\n/**\n * In-memory store for large gadget outputs.\n *\n * Outputs are stored with generated IDs in the format `{GadgetName}_{hex8}`.\n * The store is tied to an agent run and cleared when the agent completes.\n *\n * @example\n * ```typescript\n * const store = new GadgetOutputStore();\n * const id = store.store(\"Search\", largeOutput);\n * // id = \"Search_a1b2c3d4\"\n *\n * const stored = store.get(id);\n * console.log(stored?.lineCount); // 4200\n * ```\n */\nexport class GadgetOutputStore {\n private outputs = new Map<string, StoredOutput>();\n\n /**\n * Store a gadget output and return its ID.\n *\n * @param gadgetName - Name of the gadget that produced the output\n * @param content - Full output content to store\n * @returns Generated ID for retrieving the output later\n */\n store(gadgetName: string, content: string): string {\n const id = this.generateId(gadgetName);\n const encoder = new TextEncoder();\n\n const stored: StoredOutput = {\n id,\n gadgetName,\n content,\n byteSize: encoder.encode(content).length,\n lineCount: content.split(\"\\n\").length,\n timestamp: new Date(),\n };\n\n this.outputs.set(id, stored);\n return id;\n }\n\n /**\n * Retrieve a stored output by ID.\n *\n * @param id - The output ID (e.g., \"Search_d34db33f\")\n * @returns The stored output or undefined if not found\n */\n get(id: string): StoredOutput | undefined {\n return this.outputs.get(id);\n }\n\n /**\n * Check if an output exists.\n *\n * @param id - The output ID to check\n * @returns True if the output exists\n */\n has(id: string): boolean {\n return this.outputs.has(id);\n }\n\n /**\n * Get all stored output IDs.\n *\n * @returns Array of output IDs\n */\n getIds(): string[] {\n return Array.from(this.outputs.keys());\n }\n\n /**\n * Get the number of stored outputs.\n */\n get size(): number {\n return this.outputs.size;\n }\n\n /**\n * Clear all stored outputs.\n * Called when the agent run completes.\n */\n clear(): void {\n this.outputs.clear();\n }\n\n /**\n * Generate a unique ID for a stored output.\n * Format: {GadgetName}_{8 hex chars}\n */\n private generateId(gadgetName: string): string {\n const hex = randomBytes(4).toString(\"hex\");\n return `${gadgetName}_${hex}`;\n }\n}\n","/**\n * Internal key for Agent instantiation.\n * This Symbol is used to ensure only AgentBuilder can create Agent instances.\n *\n * @internal\n */\nexport const AGENT_INTERNAL_KEY = Symbol(\"AGENT_INTERNAL_KEY\");\n\n/**\n * Type guard to check if the key is the correct internal key\n * @internal\n */\nexport function isValidAgentKey(key: unknown): key is typeof AGENT_INTERNAL_KEY {\n return key === AGENT_INTERNAL_KEY;\n}\n","/**\n * ConversationManager handles conversation state and message building.\n * Extracted from AgentLoop to follow Single Responsibility Principle.\n */\n\nimport { type LLMMessage, LLMMessageBuilder } from \"../core/messages.js\";\nimport type { IConversationManager } from \"./interfaces.js\";\n\n/**\n * Options for ConversationManager constructor.\n */\nexport interface ConversationManagerOptions {\n /** Custom gadget start marker prefix */\n startPrefix?: string;\n /** Custom gadget end marker prefix */\n endPrefix?: string;\n /** Custom argument prefix for block format */\n argPrefix?: string;\n}\n\n/**\n * Default implementation of IConversationManager.\n * Manages conversation history by building on top of base messages (system prompt, gadget instructions).\n */\nexport class ConversationManager implements IConversationManager {\n private readonly baseMessages: LLMMessage[];\n private readonly initialMessages: LLMMessage[];\n private historyBuilder: LLMMessageBuilder;\n private readonly startPrefix?: string;\n private readonly endPrefix?: string;\n private readonly argPrefix?: string;\n\n constructor(\n baseMessages: LLMMessage[],\n initialMessages: LLMMessage[],\n options: ConversationManagerOptions = {},\n ) {\n this.baseMessages = baseMessages;\n this.initialMessages = initialMessages;\n this.historyBuilder = new LLMMessageBuilder();\n\n // Store prefixes for history replacement\n this.startPrefix = options.startPrefix;\n this.endPrefix = options.endPrefix;\n this.argPrefix = options.argPrefix;\n\n // Apply custom prefixes if provided (must match system prompt markers)\n if (options.startPrefix && options.endPrefix) {\n this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix, options.argPrefix);\n }\n }\n\n addUserMessage(content: string): void {\n this.historyBuilder.addUser(content);\n }\n\n addAssistantMessage(content: string): void {\n this.historyBuilder.addAssistant(content);\n }\n\n addGadgetCall(gadgetName: string, parameters: Record<string, unknown>, result: string): void {\n this.historyBuilder.addGadgetCall(gadgetName, parameters, result);\n }\n\n getMessages(): LLMMessage[] {\n return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];\n }\n\n getHistoryMessages(): LLMMessage[] {\n return this.historyBuilder.build();\n }\n\n getBaseMessages(): LLMMessage[] {\n return [...this.baseMessages, ...this.initialMessages];\n }\n\n replaceHistory(newHistory: LLMMessage[]): void {\n // Create a new builder with the same prefixes\n this.historyBuilder = new LLMMessageBuilder();\n if (this.startPrefix && this.endPrefix) {\n this.historyBuilder.withPrefixes(this.startPrefix, this.endPrefix, this.argPrefix);\n }\n\n // Add each message from the new history\n for (const msg of newHistory) {\n if (msg.role === \"user\") {\n this.historyBuilder.addUser(msg.content);\n } else if (msg.role === \"assistant\") {\n this.historyBuilder.addAssistant(msg.content);\n }\n // System messages are not added to history (they're in baseMessages)\n }\n }\n}\n","/**\n * Event handler sugar for cleaner event processing.\n *\n * Instead of verbose if/else chains, use named handlers\n * for each event type.\n *\n * @example\n * ```typescript\n * await agent.runWith({\n * onText: (content) => console.log(\"LLM:\", content),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\n\nimport type { StreamEvent } from \"../gadgets/types.js\";\n\n/**\n * Named event handlers for different event types.\n */\nexport interface EventHandlers {\n /** Called when text is generated by the LLM */\n onText?: (content: string) => void | Promise<void>;\n\n /** Called when a gadget is about to be executed */\n onGadgetCall?: (call: {\n gadgetName: string;\n parameters?: Record<string, unknown>;\n parametersRaw: string;\n }) => void | Promise<void>;\n\n /** Called when a gadget execution completes */\n onGadgetResult?: (result: {\n gadgetName: string;\n result?: string;\n error?: string;\n parameters: Record<string, unknown>;\n }) => void | Promise<void>;\n\n /** Called when human input is required */\n onHumanInputRequired?: (data: { question: string; gadgetName: string }) => void | Promise<void>;\n\n /** Called for any other event type */\n onOther?: (event: StreamEvent) => void | Promise<void>;\n}\n\n/**\n * Helper to run an agent with named event handlers.\n *\n * @param agentGenerator - Agent's run() async generator\n * @param handlers - Named event handlers\n *\n * @example\n * ```typescript\n * await runWithHandlers(agent.run(), {\n * onText: (text) => console.log(\"LLM:\", text),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\nexport async function runWithHandlers(\n agentGenerator: AsyncGenerator<StreamEvent>,\n handlers: EventHandlers,\n): Promise<void> {\n for await (const event of agentGenerator) {\n switch (event.type) {\n case \"text\":\n if (handlers.onText) {\n await handlers.onText(event.content);\n }\n break;\n\n case \"gadget_call\":\n if (handlers.onGadgetCall) {\n await handlers.onGadgetCall({\n gadgetName: event.call.gadgetName,\n parameters: event.call.parameters,\n parametersRaw: event.call.parametersRaw,\n });\n }\n break;\n\n case \"gadget_result\":\n if (handlers.onGadgetResult) {\n await handlers.onGadgetResult(event.result);\n }\n break;\n\n case \"human_input_required\":\n if (handlers.onHumanInputRequired) {\n await handlers.onHumanInputRequired({\n question: event.question,\n gadgetName: event.gadgetName,\n });\n }\n break;\n\n default:\n if (handlers.onOther) {\n await handlers.onOther(event);\n }\n break;\n }\n }\n}\n\n/**\n * Helper to collect events by type.\n *\n * @param agentGenerator - Agent's run() async generator\n * @param collect - Object specifying which event types to collect\n * @returns Object with collected events\n *\n * @example\n * ```typescript\n * const { text, gadgetResults } = await collectEvents(agent.run(), {\n * text: true,\n * gadgetResults: true,\n * });\n *\n * console.log(\"Full response:\", text.join(\"\"));\n * console.log(\"Gadget calls:\", gadgetResults.length);\n * ```\n */\nexport async function collectEvents(\n agentGenerator: AsyncGenerator<StreamEvent>,\n collect: {\n text?: boolean;\n gadgetCalls?: boolean;\n gadgetResults?: boolean;\n },\n): Promise<{\n text: string[];\n gadgetCalls: Array<{ gadgetName: string; parameters: Record<string, unknown> }>;\n gadgetResults: Array<{\n gadgetName: string;\n result?: string;\n error?: string;\n parameters: Record<string, unknown>;\n }>;\n}> {\n const result = {\n text: [] as string[],\n gadgetCalls: [] as Array<{ gadgetName: string; parameters: Record<string, unknown> }>,\n gadgetResults: [] as Array<{\n gadgetName: string;\n result?: string;\n error?: string;\n parameters: Record<string, unknown>;\n }>,\n };\n\n for await (const event of agentGenerator) {\n switch (event.type) {\n case \"text\":\n if (collect.text) {\n result.text.push(event.content);\n }\n break;\n\n case \"gadget_call\":\n if (collect.gadgetCalls && event.call.parameters) {\n result.gadgetCalls.push({\n gadgetName: event.call.gadgetName,\n parameters: event.call.parameters,\n });\n }\n break;\n\n case \"gadget_result\":\n if (collect.gadgetResults) {\n result.gadgetResults.push(event.result);\n }\n break;\n }\n }\n\n return result;\n}\n\n/**\n * Helper to collect only text from an agent run.\n *\n * @param agentGenerator - Agent's run() async generator\n * @returns Combined text response\n *\n * @example\n * ```typescript\n * const response = await collectText(agent.run());\n * console.log(response);\n * ```\n */\nexport async function collectText(agentGenerator: AsyncGenerator<StreamEvent>): Promise<string> {\n const chunks: string[] = [];\n\n for await (const event of agentGenerator) {\n if (event.type === \"text\") {\n chunks.push(event.content);\n }\n }\n\n return chunks.join(\"\");\n}\n","/**\n * Runtime validators for hook action types.\n *\n * These validators ensure that controllers return valid action objects,\n * catching common mistakes like missing required fields.\n */\n\nimport type {\n AfterGadgetExecutionAction,\n AfterLLMCallAction,\n AfterLLMErrorAction,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n} from \"./hooks.js\";\n\nexport class HookValidationError extends Error {\n constructor(hookName: string, message: string) {\n super(`Invalid action from ${hookName}: ${message}`);\n this.name = \"HookValidationError\";\n }\n}\n\n/**\n * Validate beforeLLMCall action.\n */\nexport function validateBeforeLLMCallAction(action: BeforeLLMCallAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"beforeLLMCall\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"proceed\" && actionType !== \"skip\") {\n throw new HookValidationError(\n \"beforeLLMCall\",\n `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n );\n }\n\n if (actionType === \"skip\" && !action.syntheticResponse) {\n throw new HookValidationError(\n \"beforeLLMCall\",\n \"When action is 'skip', syntheticResponse is required\",\n );\n }\n}\n\n/**\n * Validate afterLLMCall action.\n */\nexport function validateAfterLLMCallAction(action: AfterLLMCallAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n const validActions = [\"continue\", \"append_messages\", \"modify_and_continue\", \"append_and_modify\"];\n if (!validActions.includes(actionType)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Invalid action type: ${actionType}. Must be one of: ${validActions.join(\", \")}`,\n );\n }\n\n if (actionType === \"append_messages\" || actionType === \"append_and_modify\") {\n if (!(\"messages\" in action) || !action.messages || !Array.isArray(action.messages)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', messages array is required`,\n );\n }\n\n if (action.messages.length === 0) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', messages array must not be empty`,\n );\n }\n\n // Validate each message\n for (let i = 0; i < action.messages.length; i++) {\n const msg = action.messages[i];\n if (!msg || typeof msg !== \"object\") {\n throw new HookValidationError(\"afterLLMCall\", `Message at index ${i} must be an object`);\n }\n if (!msg.role || !msg.content) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Message at index ${i} must have 'role' and 'content' fields`,\n );\n }\n if (![\"system\", \"user\", \"assistant\"].includes(msg.role)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Message at index ${i} has invalid role: ${msg.role}`,\n );\n }\n }\n }\n\n if (actionType === \"modify_and_continue\" || actionType === \"append_and_modify\") {\n if (!(\"modifiedMessage\" in action) || !action.modifiedMessage) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', modifiedMessage is required`,\n );\n }\n }\n}\n\n/**\n * Validate afterLLMError action.\n */\nexport function validateAfterLLMErrorAction(action: AfterLLMErrorAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterLLMError\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"rethrow\" && actionType !== \"recover\") {\n throw new HookValidationError(\n \"afterLLMError\",\n `Invalid action type: ${actionType}. Must be 'rethrow' or 'recover'`,\n );\n }\n\n if (actionType === \"recover\" && !action.fallbackResponse) {\n throw new HookValidationError(\n \"afterLLMError\",\n \"When action is 'recover', fallbackResponse is required\",\n );\n }\n}\n\n/**\n * Validate beforeGadgetExecution action.\n */\nexport function validateBeforeGadgetExecutionAction(action: BeforeGadgetExecutionAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"proceed\" && actionType !== \"skip\") {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n );\n }\n\n if (actionType === \"skip\" && !action.syntheticResult) {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n \"When action is 'skip', syntheticResult is required\",\n );\n }\n}\n\n/**\n * Validate afterGadgetExecution action.\n */\nexport function validateAfterGadgetExecutionAction(action: AfterGadgetExecutionAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"continue\" && actionType !== \"recover\") {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n `Invalid action type: ${actionType}. Must be 'continue' or 'recover'`,\n );\n }\n\n if (actionType === \"recover\" && !action.fallbackResult) {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n \"When action is 'recover', fallbackResult is required\",\n );\n }\n}\n","import type { ZodTypeAny } from \"zod\";\n\n/**\n * Helper to safely access Zod's internal _def structure.\n * Zod's _def is not publicly typed, so we cast through unknown.\n */\nfunction getDef(schema: ZodTypeAny): Record<string, unknown> {\n return schema._def as unknown as Record<string, unknown>;\n}\n\n/**\n * Type hints that guide value coercion.\n * - 'string': Keep the value as a string, no coercion\n * - 'number': Coerce to number if possible\n * - 'boolean': Coerce to boolean if possible\n * - 'unknown': Use default auto-coercion logic (backwards compatible)\n */\nexport type TypeHint = \"string\" | \"number\" | \"boolean\" | \"unknown\";\n\n/**\n * Get the type name from a Zod schema's _def.\n * Handles both Zod v3 (typeName) and Zod v4 (type) structures.\n * Note: We cast _def to any since Zod's internal structure isn't publicly typed.\n */\nfunction getTypeName(schema: ZodTypeAny): string | undefined {\n const def = getDef(schema);\n // Zod v4 uses _def.type, Zod v3 uses _def.typeName\n return (def?.type ?? def?.typeName) as string | undefined;\n}\n\n/**\n * Get the shape from a Zod object schema's _def.\n * Handles both Zod v3 (shape()) and Zod v4 (shape) structures.\n * Note: We cast _def to any since Zod's internal structure isn't publicly typed.\n */\nfunction getShape(\n schema: ZodTypeAny\n): Record<string, ZodTypeAny> | undefined {\n const def = getDef(schema);\n // Zod v4 uses _def.shape directly, Zod v3 uses _def.shape()\n if (typeof def?.shape === \"function\") {\n return (def.shape as () => Record<string, ZodTypeAny>)();\n }\n return def?.shape as Record<string, ZodTypeAny> | undefined;\n}\n\n/**\n * Introspects Zod schemas to determine expected types at JSON pointer paths.\n *\n * This enables schema-aware type coercion - instead of blindly converting\n * \"1\" to a number, the parser can check if the schema expects a string\n * and preserve the original value.\n *\n * Design decisions:\n * - Union types prefer string over other primitives (preserves LLM intent)\n * - Transform/effect schemas return 'unknown' (let Zod handle transformation)\n * - Invalid paths return 'unknown' (fall back to auto-coercion)\n *\n * @example\n * ```typescript\n * const schema = z.object({\n * id: z.string(),\n * count: z.number(),\n * config: z.object({ timeout: z.number() })\n * });\n *\n * const introspector = new SchemaIntrospector(schema);\n * introspector.getTypeAtPath(\"id\"); // 'string'\n * introspector.getTypeAtPath(\"count\"); // 'number'\n * introspector.getTypeAtPath(\"config/timeout\"); // 'number'\n * introspector.getTypeAtPath(\"unknown\"); // 'unknown'\n * ```\n */\nexport class SchemaIntrospector {\n private readonly schema: ZodTypeAny;\n private readonly cache = new Map<string, TypeHint>();\n\n constructor(schema: ZodTypeAny) {\n this.schema = schema;\n }\n\n /**\n * Get the expected type at a JSON pointer path.\n *\n * @param pointer - JSON pointer path without leading / (e.g., \"config/timeout\", \"items/0\")\n * @returns Type hint for coercion decision\n */\n getTypeAtPath(pointer: string): TypeHint {\n // Check cache first\n const cached = this.cache.get(pointer);\n if (cached !== undefined) {\n return cached;\n }\n\n const result = this.resolveTypeAtPath(pointer);\n this.cache.set(pointer, result);\n return result;\n }\n\n /**\n * Internal method to resolve type at path without caching.\n */\n private resolveTypeAtPath(pointer: string): TypeHint {\n // Empty pointer means the root - shouldn't happen for parameters\n if (!pointer) {\n return this.getBaseType(this.schema);\n }\n\n const segments = pointer.split(\"/\");\n let current: ZodTypeAny = this.schema;\n\n for (const segment of segments) {\n // Unwrap any wrapper types (optional, default, nullable, etc.)\n current = this.unwrapSchema(current);\n\n // Navigate based on schema type\n const typeName = getTypeName(current);\n\n if (typeName === \"object\" || typeName === \"ZodObject\") {\n // Navigate into object property\n const shape = getShape(current);\n if (!shape || !(segment in shape)) {\n return \"unknown\"; // Property doesn't exist in schema\n }\n current = shape[segment];\n } else if (typeName === \"array\" || typeName === \"ZodArray\") {\n // For array indices, get element type\n if (!/^\\d+$/.test(segment)) {\n return \"unknown\"; // Not a numeric index\n }\n // Zod v4 uses _def.element, Zod v3 uses _def.type\n const def = getDef(current);\n const elementType = (def?.element ?? def?.type) as ZodTypeAny | undefined;\n if (!elementType) {\n return \"unknown\";\n }\n current = elementType;\n } else if (typeName === \"tuple\" || typeName === \"ZodTuple\") {\n // For tuples, get element at specific index\n if (!/^\\d+$/.test(segment)) {\n return \"unknown\";\n }\n const index = parseInt(segment, 10);\n const def = getDef(current);\n const items = def?.items as ZodTypeAny[] | undefined;\n if (!items || index >= items.length) {\n return \"unknown\";\n }\n current = items[index];\n } else if (typeName === \"record\" || typeName === \"ZodRecord\") {\n // For records, all values have the same type\n // Zod v4 uses _def.valueType, Zod v3 uses _def.valueType\n const def = getDef(current);\n const valueType = def?.valueType as ZodTypeAny | undefined;\n if (!valueType) {\n return \"unknown\";\n }\n current = valueType;\n } else {\n // Can't navigate further (e.g., trying to access property on a string)\n return \"unknown\";\n }\n }\n\n // Get the base type of the final schema\n return this.getBaseType(current);\n }\n\n /**\n * Unwrap schema modifiers (optional, default, nullable, branded, etc.)\n * to get to the underlying type.\n */\n private unwrapSchema(schema: ZodTypeAny): ZodTypeAny {\n let current = schema;\n let iterations = 0;\n const maxIterations = 20; // Prevent infinite loops\n\n while (iterations < maxIterations) {\n const typeName = getTypeName(current);\n\n // Check for wrapper types (both Zod v3 and v4 naming)\n const wrapperTypes = [\n \"optional\",\n \"nullable\",\n \"default\",\n \"catch\",\n \"branded\",\n \"readonly\",\n \"pipeline\",\n \"ZodOptional\",\n \"ZodNullable\",\n \"ZodDefault\",\n \"ZodCatch\",\n \"ZodBranded\",\n \"ZodReadonly\",\n \"ZodPipeline\",\n ];\n\n if (typeName && wrapperTypes.includes(typeName)) {\n const def = getDef(current);\n const inner = (def?.innerType ?? def?.in ?? def?.type) as ZodTypeAny | undefined;\n if (!inner || inner === current) break;\n current = inner;\n iterations++;\n continue;\n }\n\n break;\n }\n\n return current;\n }\n\n /**\n * Get the primitive type hint from an unwrapped schema.\n */\n private getBaseType(schema: ZodTypeAny): TypeHint {\n const unwrapped = this.unwrapSchema(schema);\n const typeName = getTypeName(unwrapped);\n\n // Map both Zod v3 (ZodString) and v4 (string) type names\n switch (typeName) {\n // Primitive types\n case \"string\":\n case \"ZodString\":\n return \"string\";\n case \"number\":\n case \"ZodNumber\":\n case \"bigint\":\n case \"ZodBigInt\":\n return \"number\";\n case \"boolean\":\n case \"ZodBoolean\":\n return \"boolean\";\n\n // Literal types - check the literal value type\n case \"literal\":\n case \"ZodLiteral\": {\n // Zod v4 uses _def.values (array), Zod v3 uses _def.value\n const def = getDef(unwrapped);\n const values = def?.values as unknown[] | undefined;\n const value = values?.[0] ?? def?.value;\n if (typeof value === \"string\") return \"string\";\n if (typeof value === \"number\" || typeof value === \"bigint\")\n return \"number\";\n if (typeof value === \"boolean\") return \"boolean\";\n return \"unknown\";\n }\n\n // Enum - always string keys\n case \"enum\":\n case \"ZodEnum\":\n case \"nativeEnum\":\n case \"ZodNativeEnum\":\n return \"string\";\n\n // Union - return 'unknown' to let auto-coercion decide\n // Since multiple types are valid, we can't definitively say what the LLM intended\n // Auto-coercion will handle common cases (numbers, booleans) appropriately\n case \"union\":\n case \"ZodUnion\":\n return \"unknown\";\n\n // Discriminated union - complex, return unknown\n case \"discriminatedUnion\":\n case \"ZodDiscriminatedUnion\":\n return \"unknown\";\n\n // Intersection - check both sides\n case \"intersection\":\n case \"ZodIntersection\": {\n const def = getDef(unwrapped);\n const left = def?.left as ZodTypeAny | undefined;\n const right = def?.right as ZodTypeAny | undefined;\n if (!left || !right) return \"unknown\";\n\n const leftType = this.getBaseType(left);\n const rightType = this.getBaseType(right);\n\n // If both are the same type, return it\n if (leftType === rightType) return leftType;\n // If one is string, prefer string\n if (leftType === \"string\" || rightType === \"string\") return \"string\";\n // Otherwise return unknown (complex intersection)\n return \"unknown\";\n }\n\n // Effects/transforms - return unknown to let Zod handle it\n case \"effects\":\n case \"ZodEffects\":\n // ZodEffects wraps transforms, refinements, etc.\n // The transform expects input in original format, so don't coerce\n return \"unknown\";\n\n // Lazy - can't resolve without evaluating\n case \"lazy\":\n case \"ZodLazy\":\n return \"unknown\";\n\n // Complex types - return unknown\n case \"object\":\n case \"ZodObject\":\n case \"array\":\n case \"ZodArray\":\n case \"tuple\":\n case \"ZodTuple\":\n case \"record\":\n case \"ZodRecord\":\n case \"map\":\n case \"ZodMap\":\n case \"set\":\n case \"ZodSet\":\n case \"function\":\n case \"ZodFunction\":\n case \"promise\":\n case \"ZodPromise\":\n case \"date\":\n case \"ZodDate\":\n return \"unknown\";\n\n // Unknown/any/never/void/undefined/null\n case \"unknown\":\n case \"ZodUnknown\":\n case \"any\":\n case \"ZodAny\":\n case \"never\":\n case \"ZodNever\":\n case \"void\":\n case \"ZodVoid\":\n case \"undefined\":\n case \"ZodUndefined\":\n case \"null\":\n case \"ZodNull\":\n return \"unknown\";\n\n default:\n return \"unknown\";\n }\n }\n}\n","import type { ZodTypeAny } from \"zod\";\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { SchemaIntrospector, type TypeHint } from \"./schema-introspector.js\";\n\nexport interface BlockParseOptions {\n /** Prefix that declares an argument. Default: \"!!!ARG:\" */\n argPrefix?: string;\n /** Optional Zod schema for schema-aware type coercion */\n schema?: ZodTypeAny;\n}\n\n/**\n * Parse block format parameters into an object.\n *\n * Block format uses !!!ARG:pointer syntax where pointer is a JSON Pointer\n * path (without leading /) that defines where to place the value.\n *\n * Example input:\n * ```\n * !!!ARG:filename\n * calculator.ts\n * !!!ARG:config/timeout\n * 30\n * !!!ARG:items/0\n * first\n * ```\n *\n * Produces:\n * ```json\n * {\n * \"filename\": \"calculator.ts\",\n * \"config\": { \"timeout\": 30 },\n * \"items\": [\"first\"]\n * }\n * ```\n *\n * Single-line values are automatically coerced:\n * - \"true\" / \"false\" → boolean\n * - Numeric strings → number\n * - Multiline values always stay as strings (for code/content)\n *\n * @param content - Raw parameter content (after gadget name line, before end marker)\n * @param options - Parser options\n * @returns Parsed parameters object with coerced values\n * @throws Error if duplicate pointers or invalid array indices\n */\nexport function parseBlockParams(\n content: string,\n options?: BlockParseOptions\n): Record<string, unknown> {\n const argPrefix = options?.argPrefix ?? GADGET_ARG_PREFIX;\n const result: Record<string, unknown> = {};\n const seenPointers = new Set<string>();\n\n // Create schema introspector if schema is provided\n const introspector = options?.schema\n ? new SchemaIntrospector(options.schema)\n : undefined;\n\n // Split content by arg prefix to get individual arg entries\n // First element will be empty or whitespace before first arg\n const parts = content.split(argPrefix);\n\n for (let i = 1; i < parts.length; i++) {\n const part = parts[i];\n\n // Find the pointer (first line) and value (rest)\n const newlineIndex = part.indexOf(\"\\n\");\n if (newlineIndex === -1) {\n // Arg with no value (just the pointer line)\n const pointer = part.trim();\n if (pointer) {\n if (seenPointers.has(pointer)) {\n throw new Error(`Duplicate pointer: ${pointer}`);\n }\n seenPointers.add(pointer);\n setByPointer(result, pointer, \"\", introspector);\n }\n continue;\n }\n\n const pointer = part.substring(0, newlineIndex).trim();\n let value = part.substring(newlineIndex + 1);\n\n // Strip single trailing newline if present (per spec)\n if (value.endsWith(\"\\n\")) {\n value = value.slice(0, -1);\n }\n\n if (!pointer) {\n continue; // Skip empty pointers\n }\n\n if (seenPointers.has(pointer)) {\n throw new Error(`Duplicate pointer: ${pointer}`);\n }\n seenPointers.add(pointer);\n\n setByPointer(result, pointer, value, introspector);\n }\n\n return result;\n}\n\n/**\n * Coerce a string value to its appropriate primitive type.\n *\n * When an `expectedType` hint is provided (from schema introspection), the coercion\n * respects the schema's expected type:\n * - 'string': Keep value as string, no coercion\n * - 'number': Coerce to number if valid\n * - 'boolean': Coerce to boolean if \"true\"/\"false\"\n * - 'unknown': Use auto-coercion logic (backwards compatible)\n *\n * Without a type hint (undefined), uses auto-coercion:\n * - \"true\" / \"false\" → boolean\n * - Numeric strings → number\n * - Everything else stays string\n *\n * Multiline values are never coerced (likely code/content).\n *\n * @param value - The string value to coerce\n * @param expectedType - Optional type hint from schema introspection\n * @returns Coerced value\n */\nfunction coerceValue(\n value: string,\n expectedType?: TypeHint\n): string | number | boolean {\n // Don't coerce multiline values - they're likely code/content\n if (value.includes(\"\\n\")) {\n return value;\n }\n\n const trimmed = value.trim();\n\n // If schema provides a type hint, respect it\n if (expectedType === \"string\") {\n // Keep as string - no coercion at all\n return value;\n }\n\n if (expectedType === \"boolean\") {\n // Only coerce recognized boolean strings\n if (trimmed === \"true\") return true;\n if (trimmed === \"false\") return false;\n // Invalid boolean - keep as string for Zod to report error\n return value;\n }\n\n if (expectedType === \"number\") {\n // Attempt to coerce to number\n const num = Number(trimmed);\n if (!isNaN(num) && isFinite(num) && trimmed !== \"\") {\n return num;\n }\n // Invalid number - keep as string for Zod to report error\n return value;\n }\n\n // expectedType === 'unknown' or undefined: use auto-coercion logic\n // This maintains backwards compatibility when no schema is provided\n // or when schema introspection can't determine the type\n\n // Boolean coercion\n if (trimmed === \"true\") return true;\n if (trimmed === \"false\") return false;\n\n // Number coercion - only for values that look clearly numeric\n // Avoid coercing things like \"123abc\" or empty strings\n if (trimmed !== \"\" && /^-?\\d+(\\.\\d+)?$/.test(trimmed)) {\n const num = Number(trimmed);\n if (!isNaN(num) && isFinite(num)) {\n return num;\n }\n }\n\n return value;\n}\n\n/**\n * Set a value in an object using a JSON Pointer path (without leading /).\n *\n * Handles:\n * - Simple keys: \"name\" → { name: value }\n * - Nested paths: \"config/timeout\" → { config: { timeout: value } }\n * - Array indices: \"items/0\" → { items: [value] }\n *\n * Values are coerced based on the schema's expected type when an introspector\n * is provided. Without a schema, falls back to auto-coercion (backwards compatible).\n *\n * @param obj - Target object to modify\n * @param pointer - JSON Pointer path without leading /\n * @param value - Value to set (string that may be coerced)\n * @param introspector - Optional schema introspector for type-aware coercion\n * @throws Error if array index gaps detected\n */\nfunction setByPointer(\n obj: Record<string, unknown>,\n pointer: string,\n value: string,\n introspector?: SchemaIntrospector\n): void {\n const segments = pointer.split(\"/\");\n let current: Record<string, unknown> | unknown[] = obj;\n\n for (let i = 0; i < segments.length - 1; i++) {\n const segment = segments[i];\n const nextSegment = segments[i + 1];\n const nextIsArrayIndex = /^\\d+$/.test(nextSegment);\n\n if (Array.isArray(current)) {\n const index = parseInt(segment, 10);\n if (isNaN(index) || index < 0) {\n throw new Error(`Invalid array index: ${segment}`);\n }\n // Validate no gaps\n if (index > current.length) {\n throw new Error(`Array index gap: expected ${current.length}, got ${index}`);\n }\n if (current[index] === undefined) {\n current[index] = nextIsArrayIndex ? [] : {};\n }\n current = current[index] as Record<string, unknown> | unknown[];\n } else {\n // current is an object\n const rec = current as Record<string, unknown>;\n if (rec[segment] === undefined) {\n rec[segment] = nextIsArrayIndex ? [] : {};\n }\n current = rec[segment] as Record<string, unknown> | unknown[];\n }\n }\n\n // Set the final value\n const lastSegment = segments[segments.length - 1];\n\n // Get expected type from schema if available, then coerce accordingly\n const expectedType = introspector?.getTypeAtPath(pointer);\n const coercedValue = coerceValue(value, expectedType);\n\n if (Array.isArray(current)) {\n const index = parseInt(lastSegment, 10);\n if (isNaN(index) || index < 0) {\n throw new Error(`Invalid array index: ${lastSegment}`);\n }\n // Validate no gaps\n if (index > current.length) {\n throw new Error(`Array index gap: expected ${current.length}, got ${index}`);\n }\n current[index] = coercedValue;\n } else {\n (current as Record<string, unknown>)[lastSegment] = coercedValue;\n }\n}\n","import type { ZodError } from \"zod\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { BaseGadget } from \"./gadget.js\";\n\nexport interface ErrorFormatterOptions {\n /** Custom argument prefix for block format examples. Default: \"!!!ARG:\" */\n argPrefix?: string;\n /** Custom start prefix for block format examples. Default: \"!!!GADGET_START:\" */\n startPrefix?: string;\n /** Custom end prefix for block format examples. Default: \"!!!GADGET_END\" */\n endPrefix?: string;\n}\n\n/**\n * Formats gadget errors with helpful context for LLMs.\n *\n * This class generates error messages that include:\n * - Clear error description\n * - Full gadget usage instructions (via getInstruction())\n * - Block format reference for parse errors\n *\n * The goal is to help LLMs self-correct on subsequent invocation attempts.\n */\nexport class GadgetErrorFormatter {\n private readonly argPrefix: string;\n private readonly startPrefix: string;\n private readonly endPrefix: string;\n\n constructor(options: ErrorFormatterOptions = {}) {\n this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;\n this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;\n this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;\n }\n\n /**\n * Format a Zod validation error with full gadget instructions.\n *\n * @param gadgetName - Name of the gadget that was called\n * @param zodError - The Zod validation error\n * @param gadget - The gadget instance (for generating instructions)\n * @returns Formatted error message with usage instructions\n */\n formatValidationError(gadgetName: string, zodError: ZodError, gadget: BaseGadget): string {\n const parts: string[] = [];\n\n // Error header\n parts.push(`Error: Invalid parameters for '${gadgetName}':`);\n\n // Format each validation issue\n for (const issue of zodError.issues) {\n const path = issue.path.join(\".\") || \"root\";\n parts.push(` - ${path}: ${issue.message}`);\n }\n\n // Add gadget usage instructions\n parts.push(\"\");\n parts.push(\"Gadget Usage:\");\n parts.push(gadget.getInstruction(this.argPrefix));\n\n return parts.join(\"\\n\");\n }\n\n /**\n * Format a parse error with block format reference.\n *\n * @param gadgetName - Name of the gadget that was called\n * @param parseError - The parse error message\n * @param gadget - The gadget instance if found (for generating instructions)\n * @returns Formatted error message with format reference\n */\n formatParseError(gadgetName: string, parseError: string, gadget: BaseGadget | undefined): string {\n const parts: string[] = [];\n\n // Error header\n parts.push(`Error: Failed to parse parameters for '${gadgetName}':`);\n parts.push(` ${parseError}`);\n\n // Add gadget usage instructions if gadget exists\n if (gadget) {\n parts.push(\"\");\n parts.push(\"Gadget Usage:\");\n parts.push(gadget.getInstruction(this.argPrefix));\n }\n\n // Always add block format reference\n parts.push(\"\");\n parts.push(\"Block Format Reference:\");\n parts.push(` ${this.startPrefix}${gadgetName}`);\n parts.push(` ${this.argPrefix}parameterName`);\n parts.push(\" parameter value here\");\n parts.push(` ${this.endPrefix}`);\n\n return parts.join(\"\\n\");\n }\n\n /**\n * Format a registry error (gadget not found) with available gadgets list.\n *\n * @param gadgetName - Name of the gadget that was not found\n * @param availableGadgets - List of available gadget names\n * @returns Formatted error message with available gadgets\n */\n formatRegistryError(gadgetName: string, availableGadgets: string[]): string {\n const parts: string[] = [];\n\n // Error header\n parts.push(`Error: Gadget '${gadgetName}' not found.`);\n\n // List available gadgets\n if (availableGadgets.length > 0) {\n parts.push(\"\");\n parts.push(`Available gadgets: ${availableGadgets.join(\", \")}`);\n } else {\n parts.push(\"\");\n parts.push(\"No gadgets are currently registered.\");\n }\n\n return parts.join(\"\\n\");\n }\n}\n\n/**\n * Create a pre-configured error formatter instance.\n *\n * @param options - Formatter options\n * @returns Configured GadgetErrorFormatter instance\n */\nexport function createErrorFormatter(options: ErrorFormatterOptions = {}): GadgetErrorFormatter {\n return new GadgetErrorFormatter(options);\n}\n","/**\n * Exception that gadgets can throw to signal the agent loop should terminate.\n *\n * When a gadget throws this exception, the agent loop will:\n * 1. Complete the current iteration\n * 2. Return the exception message as the gadget's result\n * 3. Exit the loop instead of continuing to the next iteration\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * class FinishGadget extends Gadget({\n * name: 'Finish',\n * description: 'Signals task completion',\n * schema: z.object({\n * message: z.string().optional(),\n * }),\n * }) {\n * execute(params: this['params']): string {\n * const message = params.message || 'Task completed';\n * throw new BreakLoopException(message);\n * }\n * }\n * ```\n */\nexport class BreakLoopException extends Error {\n constructor(message?: string) {\n super(message ?? \"Agent loop terminated by gadget\");\n this.name = \"BreakLoopException\";\n }\n}\n\n/**\n * Exception that gadgets can throw to request human input during execution.\n *\n * When a gadget throws this exception, the agent loop will:\n * 1. Pause execution and wait for human input\n * 2. If `onHumanInputRequired` callback is provided, call it and await the answer\n * 3. Return the user's answer as the gadget's result\n * 4. Continue the loop with the answer added to conversation history\n *\n * If no callback is provided, the loop will yield a `human_input_required` event\n * and the caller must handle it externally.\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * class AskUserGadget extends Gadget({\n * name: 'AskUser',\n * description: 'Ask the user a question and get their answer',\n * schema: z.object({\n * question: z.string().min(1, 'Question is required'),\n * }),\n * }) {\n * execute(params: this['params']): string {\n * throw new HumanInputException(params.question);\n * }\n * }\n * ```\n */\nexport class HumanInputException extends Error {\n public readonly question: string;\n\n constructor(question: string) {\n super(`Human input required: ${question}`);\n this.name = \"HumanInputException\";\n this.question = question;\n }\n}\n\n/**\n * Exception thrown when a gadget execution exceeds its timeout limit.\n *\n * When a gadget's execution time exceeds either:\n * - The gadget's own `timeoutMs` property, or\n * - The global `defaultGadgetTimeoutMs` configured in runtime/agent loop options\n *\n * The executor will automatically throw this exception and return it as an error.\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n *\n * class SlowApiGadget extends Gadget({\n * name: 'SlowApi',\n * description: 'Calls a slow external API',\n * timeoutMs: 5000, // 5 second timeout\n * schema: z.object({\n * endpoint: z.string(),\n * }),\n * }) {\n * async execute(params: this['params']): Promise<string> {\n * // If this takes longer than 5 seconds, execution will be aborted\n * const response = await fetch(params.endpoint);\n * return await response.text();\n * }\n * }\n * ```\n */\nexport class TimeoutException extends Error {\n public readonly timeoutMs: number;\n public readonly gadgetName: string;\n\n constructor(gadgetName: string, timeoutMs: number) {\n super(`Gadget '${gadgetName}' execution exceeded timeout of ${timeoutMs}ms`);\n this.name = \"TimeoutException\";\n this.gadgetName = gadgetName;\n this.timeoutMs = timeoutMs;\n }\n}\n","import { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { StreamEvent } from \"./types.js\";\nimport { parseBlockParams } from \"./block-params.js\";\n\nexport type ParameterFormat = \"block\";\n\n\n/**\n * Strip markdown code fences from parameter content.\n * LLMs sometimes wrap their parameters in ```toml, ```yaml, ```json, or plain ``` blocks.\n * This function removes those fences to allow successful parsing.\n *\n * @internal Exported for testing only\n */\nexport function stripMarkdownFences(content: string): string {\n let cleaned = content.trim();\n\n // Pattern: ```toml, ```yaml, ```json, or just ``` at start (case-insensitive)\n const openingFence = /^```(?:toml|yaml|json)?\\s*\\n/i;\n // Pattern: ``` at end (with optional preceding newline)\n const closingFence = /\\n?```\\s*$/;\n\n // Strip opening fence if present\n cleaned = cleaned.replace(openingFence, \"\");\n // Strip closing fence if present\n cleaned = cleaned.replace(closingFence, \"\");\n\n return cleaned.trim();\n}\n\nexport interface StreamParserOptions {\n startPrefix?: string;\n endPrefix?: string;\n /** Prefix for block format arguments. Default: \"!!!ARG:\" */\n argPrefix?: string;\n}\n\n// Global counter for generating unique invocation IDs across all parser instances\nlet globalInvocationCounter = 0;\n\n/**\n * Reset the global invocation counter. Only use this in tests!\n * @internal\n */\nexport function resetGlobalInvocationCounter(): void {\n globalInvocationCounter = 0;\n}\n\nexport class StreamParser {\n private buffer = \"\";\n private lastReportedTextLength = 0;\n private readonly startPrefix: string;\n private readonly endPrefix: string;\n private readonly argPrefix: string;\n\n constructor(options: StreamParserOptions = {}) {\n this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;\n this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;\n this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;\n }\n\n private takeTextUntil(index: number): string | undefined {\n if (index <= this.lastReportedTextLength) {\n return undefined;\n }\n\n const segment = this.buffer.slice(this.lastReportedTextLength, index);\n this.lastReportedTextLength = index;\n\n return segment.trim().length > 0 ? segment : undefined;\n }\n\n /**\n * Parse gadget name, handling both old format (name:invocationId) and new format (just name).\n * For new format, generates a unique invocation ID.\n */\n private parseGadgetName(gadgetName: string): { actualName: string; invocationId: string } {\n if (gadgetName.includes(\":\")) {\n // Old format: gadgetName:invocationId - support for backward compatibility\n const parts = gadgetName.split(\":\");\n return { actualName: parts[0], invocationId: parts[1] };\n }\n // New format: just gadget name, generate unique ID\n return { actualName: gadgetName, invocationId: `gadget_${++globalInvocationCounter}` };\n }\n\n /**\n * Extract the error message from a parse error.\n * Preserves full message since the error formatter adds contextual help\n * that benefits from precise, detailed error information.\n */\n private extractParseError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n }\n\n /**\n * Parse parameter string using block format\n */\n private parseParameters(raw: string): {\n parameters?: Record<string, unknown>;\n parseError?: string;\n } {\n // Strip markdown code fences if LLM wrapped the parameters\n const cleaned = stripMarkdownFences(raw);\n\n try {\n return { parameters: parseBlockParams(cleaned, { argPrefix: this.argPrefix }) };\n } catch (error) {\n return { parseError: this.extractParseError(error) };\n }\n }\n\n // Feed a chunk of text and get parsed events\n *feed(chunk: string): Generator<StreamEvent> {\n this.buffer += chunk;\n\n let startIndex = 0;\n while (true) {\n // Find next gadget start marker\n const partStartIndex = this.buffer.indexOf(this.startPrefix, startIndex);\n if (partStartIndex === -1) break;\n\n // Yield any text before the gadget\n const textBefore = this.takeTextUntil(partStartIndex);\n if (textBefore !== undefined) {\n yield { type: \"text\", content: textBefore };\n }\n\n // Extract gadget name (no more invocation ID)\n const metadataStartIndex = partStartIndex + this.startPrefix.length;\n const metadataEndIndex = this.buffer.indexOf(\"\\n\", metadataStartIndex);\n if (metadataEndIndex === -1) break; // Wait for more data\n\n const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);\n\n const contentStartIndex = metadataEndIndex + 1;\n\n let partEndIndex: number;\n let endMarkerLength = 0;\n\n if (gadgetName.includes(\":\")) {\n // Old format - look for old format end marker\n const oldEndMarker = `${this.endPrefix + actualGadgetName}:${invocationId}`;\n partEndIndex = this.buffer.indexOf(oldEndMarker, contentStartIndex);\n if (partEndIndex === -1) break; // Wait for more data\n endMarkerLength = oldEndMarker.length;\n } else {\n // New format - look for end marker OR next start marker (implicit end)\n // If a next gadget starts BEFORE an end marker, use that as implicit terminator\n\n // Look for next gadget start (potential implicit end)\n const nextStartPos = this.buffer.indexOf(this.startPrefix, contentStartIndex);\n\n // Look for proper end marker\n let validEndPos = -1;\n let searchPos = contentStartIndex;\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const endPos = this.buffer.indexOf(this.endPrefix, searchPos);\n if (endPos === -1) break;\n\n // Check if this is a standalone end marker or part of old format\n const afterEnd = this.buffer.substring(endPos + this.endPrefix.length);\n if (\n afterEnd.startsWith(\"\\n\") ||\n afterEnd.startsWith(\"\\r\") ||\n afterEnd.startsWith(this.startPrefix) ||\n afterEnd.length === 0\n ) {\n // It's a standalone end marker\n validEndPos = endPos;\n break;\n } else {\n // It might be old format, skip this one\n searchPos = endPos + this.endPrefix.length;\n }\n }\n\n // Decide which terminator to use:\n // - If next start comes before end marker, use next start (implicit end)\n // - Otherwise use the end marker if found\n if (nextStartPos !== -1 && (validEndPos === -1 || nextStartPos < validEndPos)) {\n // Found next gadget start before any end marker - implicit end\n partEndIndex = nextStartPos;\n endMarkerLength = 0; // Don't consume the next start marker\n } else if (validEndPos !== -1) {\n // Found proper end marker\n partEndIndex = validEndPos;\n endMarkerLength = this.endPrefix.length;\n } else {\n // Neither end marker nor next start found - wait for more data\n break;\n }\n }\n\n // Extract parameters\n const parametersRaw = this.buffer.substring(contentStartIndex, partEndIndex).trim();\n\n // Parse parameters according to configured format\n const { parameters, parseError } = this.parseParameters(parametersRaw);\n\n yield {\n type: \"gadget_call\",\n call: {\n gadgetName: actualGadgetName,\n invocationId,\n parametersRaw,\n parameters,\n parseError,\n },\n };\n\n // Move past this gadget\n startIndex = partEndIndex + endMarkerLength;\n\n this.lastReportedTextLength = startIndex;\n }\n\n // Keep unprocessed data in buffer\n if (startIndex > 0) {\n this.buffer = this.buffer.substring(startIndex);\n this.lastReportedTextLength = 0;\n }\n }\n\n // Finalize parsing and return remaining text or incomplete gadgets\n *finalize(): Generator<StreamEvent> {\n // Check if there's an incomplete gadget in the buffer\n const startIndex = this.buffer.indexOf(this.startPrefix, this.lastReportedTextLength);\n\n if (startIndex !== -1) {\n // There's an incomplete gadget - try to parse it\n const textBefore = this.takeTextUntil(startIndex);\n if (textBefore !== undefined) {\n yield { type: \"text\", content: textBefore };\n }\n\n // Extract gadget name\n const metadataStartIndex = startIndex + this.startPrefix.length;\n const metadataEndIndex = this.buffer.indexOf(\"\\n\", metadataStartIndex);\n\n if (metadataEndIndex !== -1) {\n const gadgetName = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n const { actualName: actualGadgetName, invocationId } = this.parseGadgetName(gadgetName);\n const contentStartIndex = metadataEndIndex + 1;\n\n // Extract parameters (everything after the newline to end of buffer)\n const parametersRaw = this.buffer.substring(contentStartIndex).trim();\n\n const { parameters, parseError } = this.parseParameters(parametersRaw);\n\n yield {\n type: \"gadget_call\",\n call: {\n gadgetName: actualGadgetName,\n invocationId,\n parametersRaw: parametersRaw,\n parameters,\n parseError,\n },\n };\n\n return;\n }\n }\n\n // No incomplete gadget - just emit remaining text\n const remainingText = this.takeTextUntil(this.buffer.length);\n if (remainingText !== undefined) {\n yield { type: \"text\", content: remainingText };\n }\n }\n\n // Reset parser state (note: global invocation counter is NOT reset to ensure unique IDs)\n reset(): void {\n this.buffer = \"\";\n this.lastReportedTextLength = 0;\n }\n}\n","import type { ILogObj, Logger } from \"tslog\";\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { parseBlockParams } from \"./block-params.js\";\nimport { GadgetErrorFormatter, type ErrorFormatterOptions } from \"./error-formatter.js\";\nimport { BreakLoopException, HumanInputException, TimeoutException } from \"./exceptions.js\";\nimport { stripMarkdownFences } from \"./parser.js\";\nimport type { GadgetRegistry } from \"./registry.js\";\nimport type { GadgetExecutionResult, ParsedGadgetCall } from \"./types.js\";\n\nexport class GadgetExecutor {\n private readonly logger: Logger<ILogObj>;\n private readonly errorFormatter: GadgetErrorFormatter;\n private readonly argPrefix: string;\n\n constructor(\n private readonly registry: GadgetRegistry,\n private readonly onHumanInputRequired?: (question: string) => Promise<string>,\n logger?: Logger<ILogObj>,\n private readonly defaultGadgetTimeoutMs?: number,\n errorFormatterOptions?: ErrorFormatterOptions,\n ) {\n this.logger = logger ?? createLogger({ name: \"llmist:executor\" });\n this.errorFormatter = new GadgetErrorFormatter(errorFormatterOptions);\n this.argPrefix = errorFormatterOptions?.argPrefix ?? GADGET_ARG_PREFIX;\n }\n\n /**\n * Creates a promise that rejects with a TimeoutException after the specified timeout.\n */\n private createTimeoutPromise(gadgetName: string, timeoutMs: number): Promise<never> {\n return new Promise((_, reject) => {\n setTimeout(() => {\n reject(new TimeoutException(gadgetName, timeoutMs));\n }, timeoutMs);\n });\n }\n\n // Execute a gadget call asynchronously\n async execute(call: ParsedGadgetCall): Promise<GadgetExecutionResult> {\n const startTime = Date.now();\n\n this.logger.debug(\"Executing gadget\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters,\n });\n\n const rawParameters: Record<string, unknown> = call.parameters ?? {};\n let validatedParameters: Record<string, unknown> = rawParameters;\n\n try {\n // Check if gadget exists\n const gadget = this.registry.get(call.gadgetName);\n if (!gadget) {\n this.logger.error(\"Gadget not found\", { gadgetName: call.gadgetName });\n const availableGadgets = this.registry.getNames();\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n error: this.errorFormatter.formatRegistryError(call.gadgetName, availableGadgets),\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Check for parse errors\n if (call.parseError || !call.parameters) {\n this.logger.error(\"Gadget parameter parse error\", {\n gadgetName: call.gadgetName,\n parseError: call.parseError,\n rawParameters: call.parametersRaw,\n });\n const parseErrorMessage = call.parseError ?? \"Failed to parse parameters\";\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: {},\n error: this.errorFormatter.formatParseError(call.gadgetName, parseErrorMessage, gadget),\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Re-parse parameters with schema for type-aware coercion (Approach B)\n // This allows the parser to use the schema to determine correct types\n // (e.g., keeping \"1\" as string when schema expects z.string())\n // Only re-parse if:\n // 1. The raw content is in block format (contains configured arg prefix)\n // 2. Parameters weren't modified by an interceptor (compare with initial parse)\n let schemaAwareParameters: Record<string, unknown> = rawParameters;\n const hasBlockFormat = call.parametersRaw?.includes(this.argPrefix);\n if (gadget.parameterSchema && hasBlockFormat) {\n try {\n const cleanedRaw = stripMarkdownFences(call.parametersRaw);\n\n // First, parse without schema to get what initial parse would produce\n const initialParse = parseBlockParams(cleanedRaw, { argPrefix: this.argPrefix });\n\n // Check if parameters were modified by an interceptor\n // by comparing current parameters with what initial parse produces\n const parametersWereModified = !this.deepEquals(rawParameters, initialParse);\n\n if (parametersWereModified) {\n // Parameters were modified by an interceptor - keep the modifications\n this.logger.debug(\"Parameters modified by interceptor, skipping re-parse\", {\n gadgetName: call.gadgetName,\n });\n schemaAwareParameters = rawParameters;\n } else {\n // Re-parse with schema for type-aware coercion\n schemaAwareParameters = parseBlockParams(cleanedRaw, {\n argPrefix: this.argPrefix,\n schema: gadget.parameterSchema,\n });\n this.logger.debug(\"Re-parsed parameters with schema\", {\n gadgetName: call.gadgetName,\n original: rawParameters,\n schemaAware: schemaAwareParameters,\n });\n }\n } catch (error) {\n // If re-parsing fails, fall back to original parameters\n // This shouldn't happen if initial parse succeeded, but be safe\n this.logger.warn(\"Schema-aware re-parsing failed, using original parameters\", {\n gadgetName: call.gadgetName,\n error: error instanceof Error ? error.message : String(error),\n });\n schemaAwareParameters = rawParameters;\n }\n }\n\n if (gadget.parameterSchema) {\n const validationResult = gadget.parameterSchema.safeParse(schemaAwareParameters);\n if (!validationResult.success) {\n const validationError = this.errorFormatter.formatValidationError(\n call.gadgetName,\n validationResult.error,\n gadget,\n );\n this.logger.error(\"Gadget parameter validation failed\", {\n gadgetName: call.gadgetName,\n issueCount: validationResult.error.issues.length,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: schemaAwareParameters,\n error: validationError,\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n validatedParameters = validationResult.data as Record<string, unknown>;\n } else {\n // No schema - use the schema-aware parameters (which are same as raw if no schema)\n validatedParameters = schemaAwareParameters;\n }\n\n // Determine the timeout for this gadget\n // Priority: gadget's own timeoutMs > defaultGadgetTimeoutMs > no timeout\n const timeoutMs = gadget.timeoutMs ?? this.defaultGadgetTimeoutMs;\n\n // Execute gadget (handle both sync and async)\n let result: string;\n if (timeoutMs && timeoutMs > 0) {\n // Execute with timeout\n this.logger.debug(\"Executing gadget with timeout\", {\n gadgetName: call.gadgetName,\n timeoutMs,\n });\n result = await Promise.race([\n Promise.resolve(gadget.execute(validatedParameters)),\n this.createTimeoutPromise(call.gadgetName, timeoutMs),\n ]);\n } else {\n // Execute without timeout\n result = await Promise.resolve(gadget.execute(validatedParameters));\n }\n\n const executionTimeMs = Date.now() - startTime;\n this.logger.info(\"Gadget executed successfully\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n executionTimeMs,\n });\n\n this.logger.debug(\"Gadget result\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result,\n executionTimeMs,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result,\n executionTimeMs,\n };\n } catch (error) {\n // Check if this is a BreakLoopException\n if (error instanceof BreakLoopException) {\n this.logger.info(\"Gadget requested loop termination\", {\n gadgetName: call.gadgetName,\n message: error.message,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result: error.message,\n breaksLoop: true,\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Check if this is a TimeoutException\n if (error instanceof TimeoutException) {\n this.logger.error(\"Gadget execution timed out\", {\n gadgetName: call.gadgetName,\n timeoutMs: error.timeoutMs,\n executionTimeMs: Date.now() - startTime,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: error.message,\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n // Check if this is a HumanInputException\n if (error instanceof HumanInputException) {\n this.logger.info(\"Gadget requested human input\", {\n gadgetName: call.gadgetName,\n question: error.question,\n });\n\n // If callback is provided, call it and wait for answer\n if (this.onHumanInputRequired) {\n try {\n const answer = await this.onHumanInputRequired(error.question);\n this.logger.debug(\"Human input received\", {\n gadgetName: call.gadgetName,\n answerLength: answer.length,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result: answer,\n executionTimeMs: Date.now() - startTime,\n };\n } catch (inputError) {\n this.logger.error(\"Human input callback error\", {\n gadgetName: call.gadgetName,\n error: inputError instanceof Error ? inputError.message : String(inputError),\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: inputError instanceof Error ? inputError.message : String(inputError),\n executionTimeMs: Date.now() - startTime,\n };\n }\n }\n\n // No callback - return error since we can't get human input\n this.logger.warn(\"Human input required but no callback provided\", {\n gadgetName: call.gadgetName,\n });\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: \"Human input required but not available (stdin is not interactive)\",\n executionTimeMs: Date.now() - startTime,\n };\n }\n\n const executionTimeMs = Date.now() - startTime;\n this.logger.error(\"Gadget execution failed\", {\n gadgetName: call.gadgetName,\n error: error instanceof Error ? error.message : String(error),\n executionTimeMs,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n error: error instanceof Error ? error.message : String(error),\n executionTimeMs,\n };\n }\n }\n\n // Execute multiple gadget calls in parallel\n async executeAll(calls: ParsedGadgetCall[]): Promise<GadgetExecutionResult[]> {\n return Promise.all(calls.map((call) => this.execute(call)));\n }\n\n /**\n * Deep equality check for objects/arrays.\n * Used to detect if parameters were modified by an interceptor.\n */\n private deepEquals(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (a === null || b === null) return a === b;\n if (typeof a !== typeof b) return false;\n\n if (typeof a !== \"object\") return a === b;\n\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n return a.every((val, i) => this.deepEquals(val, b[i]));\n }\n\n const aObj = a as Record<string, unknown>;\n const bObj = b as Record<string, unknown>;\n\n const aKeys = Object.keys(aObj);\n const bKeys = Object.keys(bObj);\n\n if (aKeys.length !== bKeys.length) return false;\n\n return aKeys.every((key) => this.deepEquals(aObj[key], bObj[key]));\n }\n}\n","/**\n * StreamProcessor: The heart of the new hooks architecture.\n *\n * Replaces the complex wiring between Agent, ResponseProcessor, and GadgetRuntime.\n * Owns ALL stream processing and hook coordination with a clean, predictable flow.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMStreamChunk, TokenUsage } from \"../core/options.js\";\nimport { GadgetExecutor } from \"../gadgets/executor.js\";\nimport { StreamParser } from \"../gadgets/parser.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { GadgetExecutionResult, ParsedGadgetCall, StreamEvent } from \"../gadgets/types.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport {\n validateAfterGadgetExecutionAction,\n validateBeforeGadgetExecutionAction,\n} from \"./hook-validators.js\";\nimport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AgentHooks,\n BeforeGadgetExecutionAction,\n ChunkInterceptorContext,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetStartContext,\n} from \"./hooks.js\";\n\n/**\n * Configuration for the StreamProcessor.\n */\nexport interface StreamProcessorOptions {\n /** Current iteration number */\n iteration: number;\n\n /** Gadget registry for execution */\n registry: GadgetRegistry;\n\n /** Custom gadget start prefix */\n gadgetStartPrefix?: string;\n\n /** Custom gadget end prefix */\n gadgetEndPrefix?: string;\n\n /** Custom argument prefix for block format */\n gadgetArgPrefix?: string;\n\n /** Hooks for lifecycle events */\n hooks?: AgentHooks;\n\n /** Logger instance */\n logger?: Logger<ILogObj>;\n\n /** Callback for human input */\n onHumanInputRequired?: (question: string) => Promise<string>;\n\n /** Whether to stop on gadget errors */\n stopOnGadgetError?: boolean;\n\n /** Custom error continuation logic */\n shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n\n /** Default gadget timeout */\n defaultGadgetTimeoutMs?: number;\n}\n\n/**\n * Result of stream processing.\n */\nexport interface StreamProcessingResult {\n /** All emitted events */\n outputs: StreamEvent[];\n\n /** Whether the loop should break */\n shouldBreakLoop: boolean;\n\n /** Whether any gadgets were executed */\n didExecuteGadgets: boolean;\n\n /** LLM finish reason */\n finishReason: string | null;\n\n /** Token usage (including cached token counts when available) */\n usage?: TokenUsage;\n\n /** The raw accumulated response text */\n rawResponse: string;\n\n /** The final message (after interceptors) */\n finalMessage: string;\n}\n\n/**\n * StreamProcessor: Coordinates all stream processing and hook execution.\n *\n * Execution order:\n * 1. Raw chunk arrives from LLM\n * 2. Interceptor: interceptRawChunk (transform raw text)\n * 3. Observer: onStreamChunk (logging)\n * 4. Parse for gadgets\n * 5. If gadget found:\n * a. Interceptor: interceptGadgetParameters (transform params)\n * b. Controller: beforeGadgetExecution (can skip)\n * c. Observer: onGadgetExecutionStart\n * d. Execute gadget\n * e. Interceptor: interceptGadgetResult (transform result)\n * f. Controller: afterGadgetExecution (can provide fallback)\n * g. Observer: onGadgetExecutionComplete\n * 6. If text chunk:\n * a. Interceptor: interceptTextChunk (transform display text)\n * b. Yield to user\n * 7. Stream complete\n * 8. Interceptor: interceptAssistantMessage (transform final message)\n */\nexport class StreamProcessor {\n private readonly iteration: number;\n private readonly registry: GadgetRegistry;\n private readonly hooks: AgentHooks;\n private readonly logger: Logger<ILogObj>;\n private readonly parser: StreamParser;\n private readonly executor: GadgetExecutor;\n private readonly stopOnGadgetError: boolean;\n private readonly shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n\n private accumulatedText = \"\";\n private shouldStopExecution = false;\n private observerFailureCount = 0;\n\n constructor(options: StreamProcessorOptions) {\n this.iteration = options.iteration;\n this.registry = options.registry;\n this.hooks = options.hooks ?? {};\n this.logger = options.logger ?? createLogger({ name: \"llmist:stream-processor\" });\n this.stopOnGadgetError = options.stopOnGadgetError ?? true;\n this.shouldContinueAfterError = options.shouldContinueAfterError;\n\n this.parser = new StreamParser({\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n argPrefix: options.gadgetArgPrefix,\n });\n\n this.executor = new GadgetExecutor(\n options.registry,\n options.onHumanInputRequired,\n this.logger.getSubLogger({ name: \"executor\" }),\n options.defaultGadgetTimeoutMs,\n { argPrefix: options.gadgetArgPrefix },\n );\n }\n\n /**\n * Process an LLM stream and return structured results.\n */\n async process(stream: AsyncIterable<LLMStreamChunk>): Promise<StreamProcessingResult> {\n const outputs: StreamEvent[] = [];\n let finishReason: string | null = null;\n let usage: TokenUsage | undefined;\n let didExecuteGadgets = false;\n let shouldBreakLoop = false;\n\n // Process stream chunks\n for await (const chunk of stream) {\n // Capture metadata\n if (chunk.finishReason) finishReason = chunk.finishReason;\n if (chunk.usage) usage = chunk.usage;\n\n // Process text content if present\n let processedChunk = \"\";\n if (chunk.text) {\n // Step 1: Interceptor - Transform raw chunk\n processedChunk = chunk.text;\n if (this.hooks.interceptors?.interceptRawChunk) {\n const context: ChunkInterceptorContext = {\n iteration: this.iteration,\n accumulatedText: this.accumulatedText,\n logger: this.logger,\n };\n const intercepted = this.hooks.interceptors.interceptRawChunk(processedChunk, context);\n if (intercepted === null) {\n // Chunk suppressed\n processedChunk = \"\";\n } else {\n processedChunk = intercepted;\n }\n }\n\n // Accumulate text\n if (processedChunk) {\n this.accumulatedText += processedChunk;\n }\n }\n\n // Step 2: Observer - Observe chunk (called for text OR usage updates)\n if (this.hooks.observers?.onStreamChunk && (processedChunk || chunk.usage)) {\n const chunkObservers: Array<() => void | Promise<void>> = [];\n chunkObservers.push(async () => {\n const context: ObserveChunkContext = {\n iteration: this.iteration,\n rawChunk: processedChunk,\n accumulatedText: this.accumulatedText,\n usage,\n logger: this.logger,\n };\n await this.hooks.observers!.onStreamChunk!(context);\n });\n await this.runObserversInParallel(chunkObservers);\n }\n\n // Skip further processing if no text\n if (!processedChunk) {\n continue;\n }\n\n // Step 3: Parse and process events\n for (const event of this.parser.feed(processedChunk)) {\n const processedEvents = await this.processEvent(event);\n outputs.push(...processedEvents);\n\n // Check if any gadget was executed\n if (processedEvents.some((e) => e.type === \"gadget_result\")) {\n didExecuteGadgets = true;\n }\n\n // Check for loop termination signals\n for (const evt of processedEvents) {\n if (evt.type === \"gadget_result\" && evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n\n // Break if we should stop execution\n if (this.shouldStopExecution) {\n this.logger.info(\"Breaking from LLM stream due to gadget error\");\n break;\n }\n }\n\n // Finalize parsing\n if (!this.shouldStopExecution) {\n for (const event of this.parser.finalize()) {\n const processedEvents = await this.processEvent(event);\n outputs.push(...processedEvents);\n\n if (processedEvents.some((e) => e.type === \"gadget_result\")) {\n didExecuteGadgets = true;\n }\n\n for (const evt of processedEvents) {\n if (evt.type === \"gadget_result\" && evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n }\n\n // Step 4: Interceptor - Transform final message\n let finalMessage = this.accumulatedText;\n if (this.hooks.interceptors?.interceptAssistantMessage) {\n const context: MessageInterceptorContext = {\n iteration: this.iteration,\n rawResponse: this.accumulatedText,\n logger: this.logger,\n };\n finalMessage = this.hooks.interceptors.interceptAssistantMessage(finalMessage, context);\n }\n\n return {\n outputs,\n shouldBreakLoop,\n didExecuteGadgets,\n finishReason,\n usage,\n rawResponse: this.accumulatedText,\n finalMessage,\n };\n }\n\n /**\n * Process a single parsed event (text or gadget call).\n */\n private async processEvent(event: StreamEvent): Promise<StreamEvent[]> {\n if (event.type === \"text\") {\n return this.processTextEvent(event);\n } else if (event.type === \"gadget_call\") {\n return this.processGadgetCall(event.call);\n }\n return [event];\n }\n\n /**\n * Process a text event through interceptors.\n */\n private async processTextEvent(event: { type: \"text\"; content: string }): Promise<StreamEvent[]> {\n let content = event.content;\n\n // Interceptor: Transform text chunk\n if (this.hooks.interceptors?.interceptTextChunk) {\n const context: ChunkInterceptorContext = {\n iteration: this.iteration,\n accumulatedText: this.accumulatedText,\n logger: this.logger,\n };\n const intercepted = this.hooks.interceptors.interceptTextChunk(content, context);\n if (intercepted === null) {\n // Chunk suppressed\n return [];\n }\n content = intercepted;\n }\n\n return [{ type: \"text\", content }];\n }\n\n /**\n * Process a gadget call through the full lifecycle.\n */\n private async processGadgetCall(call: ParsedGadgetCall): Promise<StreamEvent[]> {\n // Check if we should skip due to previous error\n if (this.shouldStopExecution) {\n this.logger.debug(\"Skipping gadget execution due to previous error\", {\n gadgetName: call.gadgetName,\n });\n return [];\n }\n\n const events: StreamEvent[] = [];\n\n // Emit gadget call event\n events.push({ type: \"gadget_call\", call });\n\n // Check for parse errors\n if (call.parseError) {\n this.logger.warn(\"Gadget has parse error\", {\n gadgetName: call.gadgetName,\n error: call.parseError,\n rawParameters: call.parametersRaw,\n });\n\n const shouldContinue = await this.checkContinueAfterError(\n call.parseError,\n call.gadgetName,\n \"parse\",\n call.parameters,\n );\n\n if (!shouldContinue) {\n this.shouldStopExecution = true;\n }\n }\n\n // Step 1: Interceptor - Transform parameters\n let parameters = call.parameters ?? {};\n if (this.hooks.interceptors?.interceptGadgetParameters) {\n const context: GadgetParameterInterceptorContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n logger: this.logger,\n };\n parameters = this.hooks.interceptors.interceptGadgetParameters(parameters, context);\n }\n\n // Update call with intercepted parameters\n call.parameters = parameters;\n\n // Step 2: Controller - Before execution\n let shouldSkip = false;\n let syntheticResult: string | undefined;\n\n if (this.hooks.controllers?.beforeGadgetExecution) {\n const context: GadgetExecutionControllerContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters,\n logger: this.logger,\n };\n const action: BeforeGadgetExecutionAction =\n await this.hooks.controllers.beforeGadgetExecution(context);\n\n // Validate the action\n validateBeforeGadgetExecutionAction(action);\n\n if (action.action === \"skip\") {\n shouldSkip = true;\n syntheticResult = action.syntheticResult;\n this.logger.info(\"Controller skipped gadget execution\", {\n gadgetName: call.gadgetName,\n });\n }\n }\n\n // Step 3: Observer - Execution start\n const startObservers: Array<() => void | Promise<void>> = [];\n if (this.hooks.observers?.onGadgetExecutionStart) {\n startObservers.push(async () => {\n const context: ObserveGadgetStartContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters,\n logger: this.logger,\n };\n await this.hooks.observers!.onGadgetExecutionStart!(context);\n });\n }\n await this.runObserversInParallel(startObservers);\n\n // Step 4: Execute or use synthetic result\n let result: GadgetExecutionResult;\n if (shouldSkip) {\n result = {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters,\n result: syntheticResult ?? \"Execution skipped\",\n executionTimeMs: 0,\n };\n } else {\n result = await this.executor.execute(call);\n }\n\n const originalResult = result.result;\n\n // Step 5: Interceptor - Transform result\n if (result.result && this.hooks.interceptors?.interceptGadgetResult) {\n const context: GadgetResultInterceptorContext = {\n iteration: this.iteration,\n gadgetName: result.gadgetName,\n invocationId: result.invocationId,\n parameters,\n executionTimeMs: result.executionTimeMs,\n logger: this.logger,\n };\n result.result = this.hooks.interceptors.interceptGadgetResult(result.result, context);\n }\n\n // Step 6: Controller - After execution\n if (this.hooks.controllers?.afterGadgetExecution) {\n const context: AfterGadgetExecutionControllerContext = {\n iteration: this.iteration,\n gadgetName: result.gadgetName,\n invocationId: result.invocationId,\n parameters,\n result: result.result,\n error: result.error,\n executionTimeMs: result.executionTimeMs,\n logger: this.logger,\n };\n const action: AfterGadgetExecutionAction =\n await this.hooks.controllers.afterGadgetExecution(context);\n\n // Validate the action\n validateAfterGadgetExecutionAction(action);\n\n if (action.action === \"recover\" && result.error) {\n this.logger.info(\"Controller recovered from gadget error\", {\n gadgetName: result.gadgetName,\n originalError: result.error,\n });\n result = {\n ...result,\n error: undefined,\n result: action.fallbackResult,\n };\n }\n }\n\n // Step 7: Observer - Execution complete\n const completeObservers: Array<() => void | Promise<void>> = [];\n if (this.hooks.observers?.onGadgetExecutionComplete) {\n completeObservers.push(async () => {\n const context: ObserveGadgetCompleteContext = {\n iteration: this.iteration,\n gadgetName: result.gadgetName,\n invocationId: result.invocationId,\n parameters,\n originalResult,\n finalResult: result.result,\n error: result.error,\n executionTimeMs: result.executionTimeMs,\n breaksLoop: result.breaksLoop,\n logger: this.logger,\n };\n await this.hooks.observers!.onGadgetExecutionComplete!(context);\n });\n }\n await this.runObserversInParallel(completeObservers);\n\n // Emit result event\n events.push({ type: \"gadget_result\", result });\n\n // Check if we should stop after error\n if (result.error) {\n const errorType = this.determineErrorType(call, result);\n const shouldContinue = await this.checkContinueAfterError(\n result.error,\n result.gadgetName,\n errorType,\n result.parameters,\n );\n\n if (!shouldContinue) {\n this.shouldStopExecution = true;\n }\n }\n\n return events;\n }\n\n /**\n * Safely execute an observer, catching and logging any errors.\n * Observers are non-critical, so errors are logged but don't crash the system.\n */\n private async safeObserve(fn: () => void | Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (error) {\n this.observerFailureCount++;\n this.logger.error(\"Observer threw error (ignoring)\", {\n error: error instanceof Error ? error.message : String(error),\n failureCount: this.observerFailureCount,\n });\n }\n }\n\n /**\n * Execute multiple observers in parallel.\n * All observers run concurrently and failures are tracked but don't crash.\n */\n private async runObserversInParallel(\n observers: Array<() => void | Promise<void>>,\n ): Promise<void> {\n if (observers.length === 0) return;\n\n const results = await Promise.allSettled(\n observers.map((observer) => this.safeObserve(observer)),\n );\n\n // All errors are already logged in safeObserve, no need to handle rejected promises\n // This just ensures we wait for all observers to complete\n }\n\n /**\n * Check if execution should continue after an error.\n *\n * Returns true if we should continue processing subsequent gadgets, false if we should stop.\n *\n * Logic:\n * - If custom shouldContinueAfterError is provided, use it\n * - Otherwise, use stopOnGadgetError config:\n * - stopOnGadgetError=true → return false (stop execution)\n * - stopOnGadgetError=false → return true (continue execution)\n */\n private async checkContinueAfterError(\n error: string,\n gadgetName: string,\n errorType: \"parse\" | \"validation\" | \"execution\",\n parameters?: Record<string, unknown>,\n ): Promise<boolean> {\n // Custom error continuation logic takes precedence\n if (this.shouldContinueAfterError) {\n return await this.shouldContinueAfterError({\n error,\n gadgetName,\n errorType,\n parameters,\n });\n }\n\n // Default behavior based on stopOnGadgetError config\n // If stopOnGadgetError=true, we want to STOP (return false to stop continuing)\n // If stopOnGadgetError=false, we want to CONTINUE (return true to keep going)\n const shouldContinue = !this.stopOnGadgetError;\n\n this.logger.debug(\"Checking if should continue after error\", {\n error,\n gadgetName,\n errorType,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinue,\n });\n\n return shouldContinue;\n }\n\n /**\n * Determine the type of error from a gadget execution.\n */\n private determineErrorType(\n call: ParsedGadgetCall,\n result: GadgetExecutionResult,\n ): \"parse\" | \"validation\" | \"execution\" {\n if (call.parseError) {\n return \"parse\";\n }\n if (result.error?.includes(\"Invalid parameters:\")) {\n return \"validation\";\n }\n return \"execution\";\n }\n}\n","/**\n * Agent: Lean orchestrator using the clean hooks architecture.\n *\n * The Agent delegates ALL stream processing and hook coordination to StreamProcessor,\n * making it a simple loop orchestrator with clear responsibilities.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport {\n CHARS_PER_TOKEN,\n DEFAULT_GADGET_OUTPUT_LIMIT,\n DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT,\n FALLBACK_CONTEXT_WINDOW,\n} from \"../core/constants.js\";\nimport { LLMMessageBuilder } from \"../core/messages.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { LLMGenerationOptions } from \"../core/options.js\";\nimport type { PromptConfig } from \"../core/prompt-config.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { StreamEvent, TextOnlyHandler } from \"../gadgets/types.js\";\nimport { createGadgetOutputViewer } from \"../gadgets/output-viewer.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport type { CompactionConfig, CompactionEvent, CompactionStats } from \"./compaction/config.js\";\nimport { CompactionManager } from \"./compaction/manager.js\";\nimport { GadgetOutputStore } from \"./gadget-output-store.js\";\nimport type { GadgetResultInterceptorContext } from \"./hooks.js\";\nimport { type AGENT_INTERNAL_KEY, isValidAgentKey } from \"./agent-internal-key.js\";\nimport { ConversationManager } from \"./conversation-manager.js\";\nimport { type EventHandlers, runWithHandlers } from \"./event-handlers.js\";\nimport {\n validateAfterLLMCallAction,\n validateAfterLLMErrorAction,\n validateBeforeLLMCallAction,\n} from \"./hook-validators.js\";\nimport type {\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n BeforeLLMCallAction,\n LLMCallControllerContext,\n LLMErrorControllerContext,\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n} from \"./hooks.js\";\nimport { StreamProcessor } from \"./stream-processor.js\";\n\n/**\n * Configuration options for the Agent.\n */\nexport interface AgentOptions {\n /** The LLM client */\n client: LLMist;\n\n /** The model ID */\n model: string;\n\n /** System prompt */\n systemPrompt?: string;\n\n /** Initial user prompt (optional if using build()) */\n userPrompt?: string;\n\n /** Maximum iterations */\n maxIterations?: number;\n\n /** Temperature */\n temperature?: number;\n\n /** Gadget registry */\n registry: GadgetRegistry;\n\n /** Logger */\n logger?: Logger<ILogObj>;\n\n /** Clean hooks system */\n hooks?: AgentHooks;\n\n /** Callback for human input */\n onHumanInputRequired?: (question: string) => Promise<string>;\n\n /** Custom gadget start prefix */\n gadgetStartPrefix?: string;\n\n /** Custom gadget end prefix */\n gadgetEndPrefix?: string;\n\n /** Custom gadget argument prefix for block format parameters */\n gadgetArgPrefix?: string;\n\n /** Initial messages */\n initialMessages?: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>;\n\n /** Text-only handler */\n textOnlyHandler?: TextOnlyHandler;\n\n /**\n * Handler for text content that appears alongside gadget calls.\n * When set, text accompanying gadgets will be wrapped as a synthetic gadget call.\n */\n textWithGadgetsHandler?: {\n /** Name of the gadget to use for wrapping text */\n gadgetName: string;\n /** Maps text content to gadget parameters */\n parameterMapping: (text: string) => Record<string, unknown>;\n /** Maps text content to the result string (optional, defaults to text) */\n resultMapping?: (text: string) => string;\n };\n\n /** Stop on gadget error */\n stopOnGadgetError?: boolean;\n\n /** Custom error continuation logic */\n shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n\n /** Default gadget timeout */\n defaultGadgetTimeoutMs?: number;\n\n /** Custom prompt configuration for gadget system prompts */\n promptConfig?: PromptConfig;\n\n /** Enable gadget output limiting (default: true) */\n gadgetOutputLimit?: boolean;\n\n /** Max gadget output as % of model context window (default: 15) */\n gadgetOutputLimitPercent?: number;\n\n /** Context compaction configuration (enabled by default) */\n compactionConfig?: CompactionConfig;\n\n /** Optional abort signal for cancelling requests mid-flight */\n signal?: AbortSignal;\n}\n\n/**\n * Agent: Lean orchestrator that delegates to StreamProcessor.\n *\n * Responsibilities:\n * - Run the main agent loop\n * - Call LLM API\n * - Delegate stream processing to StreamProcessor\n * - Coordinate conversation management\n * - Execute top-level lifecycle controllers\n *\n * NOT responsible for:\n * - Stream parsing (StreamProcessor)\n * - Hook coordination (StreamProcessor)\n * - Gadget execution (StreamProcessor -> GadgetExecutor)\n */\nexport class Agent {\n private readonly client: LLMist;\n private readonly model: string;\n private readonly maxIterations: number;\n private readonly temperature?: number;\n private readonly logger: Logger<ILogObj>;\n private readonly hooks: AgentHooks;\n private readonly conversation: ConversationManager;\n private readonly registry: GadgetRegistry;\n private readonly gadgetStartPrefix?: string;\n private readonly gadgetEndPrefix?: string;\n private readonly gadgetArgPrefix?: string;\n private readonly onHumanInputRequired?: (question: string) => Promise<string>;\n private readonly textOnlyHandler: TextOnlyHandler;\n private readonly textWithGadgetsHandler?: {\n gadgetName: string;\n parameterMapping: (text: string) => Record<string, unknown>;\n resultMapping?: (text: string) => string;\n };\n private readonly stopOnGadgetError: boolean;\n private readonly shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n private readonly defaultGadgetTimeoutMs?: number;\n private readonly defaultMaxTokens?: number;\n private userPromptProvided: boolean;\n\n // Gadget output limiting\n private readonly outputStore: GadgetOutputStore;\n private readonly outputLimitEnabled: boolean;\n private readonly outputLimitCharLimit: number;\n\n // Context compaction\n private readonly compactionManager?: CompactionManager;\n\n // Cancellation\n private readonly signal?: AbortSignal;\n\n /**\n * Creates a new Agent instance.\n * @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.\n */\n constructor(key: typeof AGENT_INTERNAL_KEY, options: AgentOptions) {\n if (!isValidAgentKey(key)) {\n throw new Error(\n \"Agent cannot be instantiated directly. Use LLMist.createAgent() or new AgentBuilder() instead.\",\n );\n }\n\n this.client = options.client;\n this.model = resolveModel(options.model);\n this.maxIterations = options.maxIterations ?? 10;\n this.temperature = options.temperature;\n this.logger = options.logger ?? createLogger({ name: \"llmist:agent\" });\n this.registry = options.registry;\n this.gadgetStartPrefix = options.gadgetStartPrefix;\n this.gadgetEndPrefix = options.gadgetEndPrefix;\n this.gadgetArgPrefix = options.gadgetArgPrefix;\n this.onHumanInputRequired = options.onHumanInputRequired;\n this.textOnlyHandler = options.textOnlyHandler ?? \"terminate\";\n this.textWithGadgetsHandler = options.textWithGadgetsHandler;\n this.stopOnGadgetError = options.stopOnGadgetError ?? true;\n this.shouldContinueAfterError = options.shouldContinueAfterError;\n this.defaultGadgetTimeoutMs = options.defaultGadgetTimeoutMs;\n this.defaultMaxTokens = this.resolveMaxTokensFromCatalog(options.model);\n\n // Initialize gadget output limiting\n this.outputLimitEnabled = options.gadgetOutputLimit ?? DEFAULT_GADGET_OUTPUT_LIMIT;\n this.outputStore = new GadgetOutputStore();\n\n // Calculate character limit from model context window\n const limitPercent = options.gadgetOutputLimitPercent ?? DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT;\n const limits = this.client.modelRegistry.getModelLimits(this.model);\n const contextWindow = limits?.contextWindow ?? FALLBACK_CONTEXT_WINDOW;\n this.outputLimitCharLimit = Math.floor(contextWindow * (limitPercent / 100) * CHARS_PER_TOKEN);\n\n // Auto-register GadgetOutputViewer when limiting is enabled\n if (this.outputLimitEnabled) {\n this.registry.register(\"GadgetOutputViewer\", createGadgetOutputViewer(this.outputStore));\n }\n\n // Merge output limiter interceptor into hooks\n this.hooks = this.mergeOutputLimiterHook(options.hooks);\n\n // Build conversation\n const baseBuilder = new LLMMessageBuilder(options.promptConfig);\n if (options.systemPrompt) {\n baseBuilder.addSystem(options.systemPrompt);\n }\n\n baseBuilder.addGadgets(this.registry.getAll(), {\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n argPrefix: options.gadgetArgPrefix,\n });\n const baseMessages = baseBuilder.build();\n\n const initialMessages = (options.initialMessages ?? []).map((message) => ({\n role: message.role,\n content: message.content,\n }));\n\n this.conversation = new ConversationManager(baseMessages, initialMessages, {\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n argPrefix: options.gadgetArgPrefix,\n });\n this.userPromptProvided = !!options.userPrompt;\n if (options.userPrompt) {\n this.conversation.addUserMessage(options.userPrompt);\n }\n\n // Initialize context compaction (enabled by default)\n const compactionEnabled = options.compactionConfig?.enabled ?? true;\n if (compactionEnabled) {\n this.compactionManager = new CompactionManager(\n this.client,\n this.model,\n options.compactionConfig,\n );\n }\n\n // Store abort signal for cancellation\n this.signal = options.signal;\n }\n\n /**\n * Get the gadget registry for this agent.\n *\n * Useful for inspecting registered gadgets in tests or advanced use cases.\n *\n * @returns The GadgetRegistry instance\n *\n * @example\n * ```typescript\n * const agent = new AgentBuilder()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator, Weather)\n * .build();\n *\n * // Inspect registered gadgets\n * console.log(agent.getRegistry().getNames()); // ['Calculator', 'Weather']\n * ```\n */\n getRegistry(): GadgetRegistry {\n return this.registry;\n }\n\n /**\n * Manually trigger context compaction.\n *\n * Forces compaction regardless of threshold. Useful for:\n * - Pre-emptive context management before expected long operations\n * - Testing compaction behavior\n *\n * @returns CompactionEvent if compaction was performed, null if not configured or no history\n *\n * @example\n * ```typescript\n * const agent = await LLMist.createAgent()\n * .withModel('sonnet')\n * .withCompaction()\n * .ask('...');\n *\n * // Manually compact before a long operation\n * const event = await agent.compact();\n * if (event) {\n * console.log(`Saved ${event.tokensBefore - event.tokensAfter} tokens`);\n * }\n * ```\n */\n async compact(): Promise<CompactionEvent | null> {\n if (!this.compactionManager) {\n return null;\n }\n // Use -1 to indicate manual (out-of-band) compaction, not part of the normal iteration cycle\n return this.compactionManager.compact(this.conversation, -1);\n }\n\n /**\n * Get compaction statistics.\n *\n * @returns CompactionStats if compaction is enabled, null otherwise\n *\n * @example\n * ```typescript\n * const stats = agent.getCompactionStats();\n * if (stats) {\n * console.log(`Total compactions: ${stats.totalCompactions}`);\n * console.log(`Tokens saved: ${stats.totalTokensSaved}`);\n * console.log(`Current usage: ${stats.currentUsage.percent.toFixed(1)}%`);\n * }\n * ```\n */\n getCompactionStats(): CompactionStats | null {\n return this.compactionManager?.getStats() ?? null;\n }\n\n /**\n * Run the agent loop.\n * Clean, simple orchestration - all complexity is in StreamProcessor.\n *\n * @throws {Error} If no user prompt was provided (when using build() without ask())\n */\n async *run(): AsyncGenerator<StreamEvent> {\n if (!this.userPromptProvided) {\n throw new Error(\n \"No user prompt provided. Use .ask(prompt) instead of .build(), or call agent.run() after providing a prompt.\",\n );\n }\n\n let currentIteration = 0;\n\n this.logger.info(\"Starting agent loop\", {\n model: this.model,\n maxIterations: this.maxIterations,\n });\n\n while (currentIteration < this.maxIterations) {\n this.logger.debug(\"Starting iteration\", { iteration: currentIteration });\n\n try {\n // Check and perform context compaction if needed\n if (this.compactionManager) {\n const compactionEvent = await this.compactionManager.checkAndCompact(\n this.conversation,\n currentIteration,\n );\n if (compactionEvent) {\n this.logger.info(\"Context compacted\", {\n strategy: compactionEvent.strategy,\n tokensBefore: compactionEvent.tokensBefore,\n tokensAfter: compactionEvent.tokensAfter,\n });\n yield { type: \"compaction\", event: compactionEvent } as StreamEvent;\n\n // Observer: Compaction occurred\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onCompaction) {\n await this.hooks.observers.onCompaction({\n iteration: currentIteration,\n event: compactionEvent,\n stats: this.compactionManager!.getStats(),\n logger: this.logger,\n });\n }\n });\n }\n }\n\n // Prepare LLM call options\n let llmOptions: LLMGenerationOptions = {\n model: this.model,\n messages: this.conversation.getMessages(),\n temperature: this.temperature,\n maxTokens: this.defaultMaxTokens,\n signal: this.signal,\n };\n\n // Observer: LLM call start\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onLLMCallStart) {\n const context: ObserveLLMCallContext = {\n iteration: currentIteration,\n options: llmOptions,\n logger: this.logger,\n };\n await this.hooks.observers.onLLMCallStart(context);\n }\n });\n\n // Controller: Before LLM call\n if (this.hooks.controllers?.beforeLLMCall) {\n const context: LLMCallControllerContext = {\n iteration: currentIteration,\n maxIterations: this.maxIterations,\n options: llmOptions,\n logger: this.logger,\n };\n const action: BeforeLLMCallAction = await this.hooks.controllers.beforeLLMCall(context);\n\n // Validate the action\n validateBeforeLLMCallAction(action);\n\n if (action.action === \"skip\") {\n this.logger.info(\"Controller skipped LLM call, using synthetic response\");\n // Add synthetic response to conversation\n this.conversation.addAssistantMessage(action.syntheticResponse);\n // Yield as text event\n yield { type: \"text\", content: action.syntheticResponse };\n break;\n } else if (action.action === \"proceed\" && action.modifiedOptions) {\n llmOptions = { ...llmOptions, ...action.modifiedOptions };\n }\n }\n\n // Call LLM\n this.logger.info(\"Calling LLM\", { model: this.model });\n this.logger.silly(\"LLM request details\", {\n model: llmOptions.model,\n temperature: llmOptions.temperature,\n maxTokens: llmOptions.maxTokens,\n messageCount: llmOptions.messages.length,\n messages: llmOptions.messages,\n });\n const stream = this.client.stream(llmOptions);\n\n // Process stream - ALL complexity delegated to StreamProcessor\n const processor = new StreamProcessor({\n iteration: currentIteration,\n registry: this.registry,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n hooks: this.hooks,\n logger: this.logger.getSubLogger({ name: \"stream-processor\" }),\n onHumanInputRequired: this.onHumanInputRequired,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinueAfterError: this.shouldContinueAfterError,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n });\n\n const result = await processor.process(stream);\n\n // Yield all outputs to user\n for (const output of result.outputs) {\n yield output;\n }\n\n this.logger.info(\"LLM response completed\", {\n finishReason: result.finishReason,\n usage: result.usage,\n didExecuteGadgets: result.didExecuteGadgets,\n });\n this.logger.silly(\"LLM response details\", {\n rawResponse: result.rawResponse,\n });\n\n // Observer: LLM call complete\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onLLMCallComplete) {\n const context: ObserveLLMCompleteContext = {\n iteration: currentIteration,\n options: llmOptions,\n finishReason: result.finishReason,\n usage: result.usage,\n rawResponse: result.rawResponse,\n finalMessage: result.finalMessage,\n logger: this.logger,\n };\n await this.hooks.observers.onLLMCallComplete(context);\n }\n });\n\n // Controller: After LLM call\n let finalMessage = result.finalMessage;\n if (this.hooks.controllers?.afterLLMCall) {\n // Count gadget calls in this response\n const gadgetCallCount = result.outputs.filter(\n (output) => output.type === \"gadget_result\",\n ).length;\n\n const context: AfterLLMCallControllerContext = {\n iteration: currentIteration,\n maxIterations: this.maxIterations,\n options: llmOptions,\n finishReason: result.finishReason,\n usage: result.usage,\n finalMessage: result.finalMessage,\n gadgetCallCount,\n logger: this.logger,\n };\n const action: AfterLLMCallAction = await this.hooks.controllers.afterLLMCall(context);\n\n // Validate the action\n validateAfterLLMCallAction(action);\n\n if (action.action === \"modify_and_continue\" || action.action === \"append_and_modify\") {\n finalMessage = action.modifiedMessage;\n }\n\n if (action.action === \"append_messages\" || action.action === \"append_and_modify\") {\n for (const msg of action.messages) {\n if (msg.role === \"user\") {\n this.conversation.addUserMessage(msg.content);\n } else if (msg.role === \"assistant\") {\n this.conversation.addAssistantMessage(msg.content);\n } else if (msg.role === \"system\") {\n // System messages can't be added mid-conversation, treat as user\n this.conversation.addUserMessage(`[System] ${msg.content}`);\n }\n }\n }\n }\n\n // Add gadget results to conversation (if any were executed)\n if (result.didExecuteGadgets) {\n // If configured, wrap accompanying text as a synthetic gadget call (before actual gadgets)\n if (this.textWithGadgetsHandler) {\n const textContent = result.outputs\n .filter((output): output is { type: \"text\"; content: string } => output.type === \"text\")\n .map((output) => output.content)\n .join(\"\");\n\n if (textContent.trim()) {\n const { gadgetName, parameterMapping, resultMapping } = this.textWithGadgetsHandler;\n this.conversation.addGadgetCall(\n gadgetName,\n parameterMapping(textContent),\n resultMapping ? resultMapping(textContent) : textContent,\n );\n }\n }\n\n // Extract and add all gadget results to conversation\n for (const output of result.outputs) {\n if (output.type === \"gadget_result\") {\n const gadgetResult = output.result;\n this.conversation.addGadgetCall(\n gadgetResult.gadgetName,\n gadgetResult.parameters,\n gadgetResult.error ?? gadgetResult.result ?? \"\",\n );\n }\n }\n } else {\n // No gadgets executed - wrap text as synthetic TellUser result\n // This keeps conversation history consistent (gadget-oriented) and\n // helps LLMs stay in the \"gadget invocation\" mindset\n if (finalMessage.trim()) {\n this.conversation.addGadgetCall(\n \"TellUser\",\n { message: finalMessage, done: false, type: \"info\" },\n `ℹ️ ${finalMessage}`,\n );\n }\n // Empty responses: don't add anything, just check if we should continue\n\n // Handle text-only responses\n const shouldBreak = await this.handleTextOnlyResponse(finalMessage);\n if (shouldBreak) {\n break;\n }\n }\n\n // Check if loop should break\n if (result.shouldBreakLoop) {\n this.logger.info(\"Loop terminated by gadget or processor\");\n break;\n }\n } catch (error) {\n // Handle LLM error\n const errorHandled = await this.handleLLMError(error as Error, currentIteration);\n\n // Observer: LLM error\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onLLMCallError) {\n const context: ObserveLLMErrorContext = {\n iteration: currentIteration,\n options: {\n model: this.model,\n messages: this.conversation.getMessages(),\n temperature: this.temperature,\n maxTokens: this.defaultMaxTokens,\n },\n error: error as Error,\n recovered: errorHandled,\n logger: this.logger,\n };\n await this.hooks.observers.onLLMCallError(context);\n }\n });\n\n if (!errorHandled) {\n throw error;\n }\n }\n\n currentIteration++;\n }\n\n this.logger.info(\"Agent loop completed\", {\n totalIterations: currentIteration,\n reason: currentIteration >= this.maxIterations ? \"max_iterations\" : \"natural_completion\",\n });\n }\n\n /**\n * Handle LLM error through controller.\n */\n private async handleLLMError(error: Error, iteration: number): Promise<boolean> {\n this.logger.error(\"LLM call failed\", { error: error.message });\n\n if (this.hooks.controllers?.afterLLMError) {\n const context: LLMErrorControllerContext = {\n iteration,\n options: {\n model: this.model,\n messages: this.conversation.getMessages(),\n temperature: this.temperature,\n maxTokens: this.defaultMaxTokens,\n },\n error,\n logger: this.logger,\n };\n const action: AfterLLMErrorAction = await this.hooks.controllers.afterLLMError(context);\n\n // Validate the action\n validateAfterLLMErrorAction(action);\n\n if (action.action === \"recover\") {\n this.logger.info(\"Controller recovered from LLM error\");\n this.conversation.addAssistantMessage(action.fallbackResponse);\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Handle text-only response (no gadgets called).\n */\n private async handleTextOnlyResponse(_text: string): Promise<boolean> {\n const handler = this.textOnlyHandler;\n\n if (typeof handler === \"string\") {\n switch (handler) {\n case \"terminate\":\n this.logger.info(\"No gadgets called, ending loop\");\n return true;\n case \"acknowledge\":\n this.logger.info(\"No gadgets called, continuing loop\");\n return false;\n case \"wait_for_input\":\n this.logger.info(\"No gadgets called, waiting for input\");\n return true;\n default:\n this.logger.warn(`Unknown text-only strategy: ${handler}, defaulting to terminate`);\n return true;\n }\n }\n\n // For gadget and custom handlers, they would need to be implemented\n // This is simplified for now\n return true;\n }\n\n /**\n * Safely execute an observer, catching and logging any errors.\n */\n private async safeObserve(fn: () => void | Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (error) {\n this.logger.error(\"Observer threw error (ignoring)\", {\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n /**\n * Resolve max tokens from model catalog.\n */\n private resolveMaxTokensFromCatalog(modelId: string): number | undefined {\n const limits = this.client.modelRegistry.getModelLimits(modelId);\n if (limits?.maxOutputTokens !== undefined) {\n return limits.maxOutputTokens;\n }\n\n const separatorIndex = modelId.indexOf(\":\");\n if (separatorIndex === -1) {\n return undefined;\n }\n\n const unprefixedModelId = modelId.slice(separatorIndex + 1).trim();\n if (!unprefixedModelId) {\n return undefined;\n }\n\n return this.client.modelRegistry.getModelLimits(unprefixedModelId)?.maxOutputTokens;\n }\n\n /**\n * Merge the output limiter interceptor into user-provided hooks.\n * The limiter runs first, then chains to any user interceptor.\n */\n private mergeOutputLimiterHook(userHooks?: AgentHooks): AgentHooks {\n if (!this.outputLimitEnabled) {\n return userHooks ?? {};\n }\n\n const limiterInterceptor = (\n result: string,\n ctx: GadgetResultInterceptorContext,\n ): string => {\n // Skip limiting for GadgetOutputViewer itself to avoid recursion\n if (ctx.gadgetName === \"GadgetOutputViewer\") {\n return result;\n }\n\n if (result.length > this.outputLimitCharLimit) {\n const id = this.outputStore.store(ctx.gadgetName, result);\n const lines = result.split(\"\\n\").length;\n const bytes = new TextEncoder().encode(result).length;\n\n this.logger.info(\"Gadget output exceeded limit, stored for browsing\", {\n gadgetName: ctx.gadgetName,\n outputId: id,\n bytes,\n lines,\n charLimit: this.outputLimitCharLimit,\n });\n\n return (\n `[Gadget \"${ctx.gadgetName}\" returned too much data: ` +\n `${bytes.toLocaleString()} bytes, ${lines.toLocaleString()} lines. ` +\n `Use GadgetOutputViewer with id \"${id}\" to read it]`\n );\n }\n\n return result;\n };\n\n // Chain with any user-provided interceptor (limiter runs first)\n const userInterceptor = userHooks?.interceptors?.interceptGadgetResult;\n const chainedInterceptor = userInterceptor\n ? (result: string, ctx: GadgetResultInterceptorContext) =>\n userInterceptor(limiterInterceptor(result, ctx), ctx)\n : limiterInterceptor;\n\n return {\n ...userHooks,\n interceptors: {\n ...userHooks?.interceptors,\n interceptGadgetResult: chainedInterceptor,\n },\n };\n }\n\n /**\n * Run agent with named event handlers (syntactic sugar).\n *\n * Instead of verbose if/else chains, use named handlers for cleaner code.\n *\n * @param handlers - Named event handlers\n *\n * @example\n * ```typescript\n * await agent.runWith({\n * onText: (text) => console.log(\"LLM:\", text),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * onGadgetCall: (call) => console.log(\"Calling:\", call.gadgetName),\n * });\n * ```\n */\n async runWith(handlers: EventHandlers): Promise<void> {\n return runWithHandlers(this.run(), handlers);\n }\n}\n","/**\n * Fluent builder for creating agents with delightful DX.\n *\n * @example\n * ```typescript\n * const agent = await LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withSystem(\"You are a helpful assistant\")\n * .withGadgets(Calculator, Weather)\n * .withMaxIterations(10)\n * .ask(\"What's the weather in Paris?\");\n *\n * for await (const event of agent.run()) {\n * // process events\n * }\n * ```\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { PromptConfig } from \"../core/prompt-config.js\";\nimport type { GadgetOrClass } from \"../gadgets/registry.js\";\nimport { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { TextOnlyHandler } from \"../gadgets/types.js\";\nimport { Agent, type AgentOptions } from \"./agent.js\";\nimport { AGENT_INTERNAL_KEY } from \"./agent-internal-key.js\";\nimport type { CompactionConfig } from \"./compaction/config.js\";\nimport { collectText, type EventHandlers } from \"./event-handlers.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n/**\n * Message for conversation history.\n */\nexport type HistoryMessage = { user: string } | { assistant: string } | { system: string };\n\n/**\n * Fluent builder for creating agents.\n *\n * Provides a chainable API for configuring and creating agents,\n * making the code more expressive and easier to read.\n */\nexport class AgentBuilder {\n private client?: LLMist;\n private model?: string;\n private systemPrompt?: string;\n private temperature?: number;\n private maxIterations?: number;\n private logger?: Logger<ILogObj>;\n private hooks?: AgentHooks;\n private promptConfig?: PromptConfig;\n private gadgets: GadgetOrClass[] = [];\n private initialMessages: Array<{\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n }> = [];\n private onHumanInputRequired?: (question: string) => Promise<string>;\n private gadgetStartPrefix?: string;\n private gadgetEndPrefix?: string;\n private gadgetArgPrefix?: string;\n private textOnlyHandler?: TextOnlyHandler;\n private textWithGadgetsHandler?: {\n gadgetName: string;\n parameterMapping: (text: string) => Record<string, unknown>;\n resultMapping?: (text: string) => string;\n };\n private stopOnGadgetError?: boolean;\n private shouldContinueAfterError?: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>;\n private defaultGadgetTimeoutMs?: number;\n private gadgetOutputLimit?: boolean;\n private gadgetOutputLimitPercent?: number;\n private compactionConfig?: CompactionConfig;\n private signal?: AbortSignal;\n\n constructor(client?: LLMist) {\n this.client = client;\n }\n\n /**\n * Set the model to use.\n * Supports aliases like \"gpt4\", \"sonnet\", \"flash\".\n *\n * @param model - Model name or alias\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withModel(\"sonnet\") // Alias\n * .withModel(\"gpt-5-nano\") // Auto-detects provider\n * .withModel(\"openai:gpt-5\") // Explicit provider\n * ```\n */\n withModel(model: string): this {\n this.model = resolveModel(model);\n return this;\n }\n\n /**\n * Set the system prompt.\n *\n * @param prompt - System prompt\n * @returns This builder for chaining\n */\n withSystem(prompt: string): this {\n this.systemPrompt = prompt;\n return this;\n }\n\n /**\n * Set the temperature (0-1).\n *\n * @param temperature - Temperature value\n * @returns This builder for chaining\n */\n withTemperature(temperature: number): this {\n this.temperature = temperature;\n return this;\n }\n\n /**\n * Set maximum iterations.\n *\n * @param max - Maximum number of iterations\n * @returns This builder for chaining\n */\n withMaxIterations(max: number): this {\n this.maxIterations = max;\n return this;\n }\n\n /**\n * Set logger instance.\n *\n * @param logger - Logger instance\n * @returns This builder for chaining\n */\n withLogger(logger: Logger<ILogObj>): this {\n this.logger = logger;\n return this;\n }\n\n /**\n * Add hooks for agent lifecycle events.\n *\n * @param hooks - Agent hooks configuration\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * import { HookPresets } from 'llmist/hooks';\n *\n * .withHooks(HookPresets.logging())\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing()\n * ))\n * ```\n */\n withHooks(hooks: AgentHooks): this {\n this.hooks = hooks;\n return this;\n }\n\n /**\n * Configure custom prompts for gadget system messages.\n *\n * @param config - Prompt configuration object\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withPromptConfig({\n * mainInstruction: \"Use the gadget markers below:\",\n * rules: [\"Always use markers\", \"Never use function calling\"]\n * })\n * ```\n */\n withPromptConfig(config: PromptConfig): this {\n this.promptConfig = config;\n return this;\n }\n\n /**\n * Add gadgets (classes or instances).\n * Can be called multiple times to add more gadgets.\n *\n * @param gadgets - Gadget classes or instances\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgets(Calculator, Weather, Email)\n * .withGadgets(new Calculator(), new Weather())\n * .withGadgets(createGadget({ ... }))\n * ```\n */\n withGadgets(...gadgets: GadgetOrClass[]): this {\n this.gadgets.push(...gadgets);\n return this;\n }\n\n /**\n * Add conversation history messages.\n * Useful for continuing previous conversations.\n *\n * @param messages - Array of history messages\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withHistory([\n * { user: \"Hello\" },\n * { assistant: \"Hi there!\" },\n * { user: \"How are you?\" },\n * { assistant: \"I'm doing well, thanks!\" }\n * ])\n * ```\n */\n withHistory(messages: HistoryMessage[]): this {\n for (const msg of messages) {\n if (\"user\" in msg) {\n this.initialMessages.push({ role: \"user\", content: msg.user });\n } else if (\"assistant\" in msg) {\n this.initialMessages.push({ role: \"assistant\", content: msg.assistant });\n } else if (\"system\" in msg) {\n this.initialMessages.push({ role: \"system\", content: msg.system });\n }\n }\n return this;\n }\n\n /**\n * Add a single message to the conversation history.\n *\n * @param message - Single history message\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .addMessage({ user: \"Hello\" })\n * .addMessage({ assistant: \"Hi there!\" })\n * ```\n */\n addMessage(message: HistoryMessage): this {\n return this.withHistory([message]);\n }\n\n /**\n * Set the human input handler for interactive conversations.\n *\n * @param handler - Function to handle human input requests\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .onHumanInput(async (question) => {\n * return await promptUser(question);\n * })\n * ```\n */\n onHumanInput(handler: (question: string) => Promise<string>): this {\n this.onHumanInputRequired = handler;\n return this;\n }\n\n /**\n * Set custom gadget marker prefix.\n *\n * @param prefix - Custom start prefix for gadget markers\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetStartPrefix(\"<<GADGET_START>>\")\n * ```\n */\n withGadgetStartPrefix(prefix: string): this {\n this.gadgetStartPrefix = prefix;\n return this;\n }\n\n /**\n * Set custom gadget marker suffix.\n *\n * @param suffix - Custom end suffix for gadget markers\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetEndPrefix(\"<<GADGET_END>>\")\n * ```\n */\n withGadgetEndPrefix(suffix: string): this {\n this.gadgetEndPrefix = suffix;\n return this;\n }\n\n /**\n * Set custom argument prefix for block format parameters.\n *\n * @param prefix - Custom prefix for argument markers (default: \"!!!ARG:\")\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetArgPrefix(\"<<ARG>>\")\n * ```\n */\n withGadgetArgPrefix(prefix: string): this {\n this.gadgetArgPrefix = prefix;\n return this;\n }\n\n /**\n * Set the text-only handler strategy.\n *\n * Controls what happens when the LLM returns text without calling any gadgets:\n * - \"terminate\": End the agent loop (default)\n * - \"acknowledge\": Continue the loop for another iteration\n * - \"wait_for_input\": Wait for human input\n * - Custom handler: Provide a function for dynamic behavior\n *\n * @param handler - Text-only handler strategy or custom handler\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Simple strategy\n * .withTextOnlyHandler(\"acknowledge\")\n *\n * // Custom handler\n * .withTextOnlyHandler({\n * type: \"custom\",\n * handler: async (context) => {\n * if (context.text.includes(\"?\")) {\n * return { action: \"wait_for_input\", question: context.text };\n * }\n * return { action: \"continue\" };\n * }\n * })\n * ```\n */\n withTextOnlyHandler(handler: TextOnlyHandler): this {\n this.textOnlyHandler = handler;\n return this;\n }\n\n /**\n * Set the handler for text content that appears alongside gadget calls.\n *\n * When set, text accompanying gadget responses will be wrapped as a\n * synthetic gadget call before the actual gadget results in the\n * conversation history.\n *\n * @param handler - Configuration for wrapping text\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Wrap text as TellUser gadget\n * .withTextWithGadgetsHandler({\n * gadgetName: \"TellUser\",\n * parameterMapping: (text) => ({ message: text, done: false, type: \"info\" }),\n * resultMapping: (text) => `ℹ️ ${text}`,\n * })\n * ```\n */\n withTextWithGadgetsHandler(handler: {\n gadgetName: string;\n parameterMapping: (text: string) => Record<string, unknown>;\n resultMapping?: (text: string) => string;\n }): this {\n this.textWithGadgetsHandler = handler;\n return this;\n }\n\n /**\n * Set whether to stop gadget execution on first error.\n *\n * When true (default), if a gadget fails:\n * - Subsequent gadgets in the same response are skipped\n * - LLM stream is cancelled to save costs\n * - Agent loop continues with error in context\n *\n * When false:\n * - All gadgets in the response still execute\n * - LLM stream continues to completion\n *\n * @param stop - Whether to stop on gadget error\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withStopOnGadgetError(false)\n * ```\n */\n withStopOnGadgetError(stop: boolean): this {\n this.stopOnGadgetError = stop;\n return this;\n }\n\n /**\n * Set custom error handling logic.\n *\n * Provides fine-grained control over whether to continue after different types of errors.\n * Overrides `stopOnGadgetError` when provided.\n *\n * **Note:** This builder method configures the underlying `shouldContinueAfterError` option\n * in `AgentOptions`. The method is named `withErrorHandler` for better developer experience,\n * but maps to the `shouldContinueAfterError` property internally.\n *\n * @param handler - Function that decides whether to continue after an error.\n * Return `true` to continue execution, `false` to stop.\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withErrorHandler((context) => {\n * // Stop on parse errors, continue on validation/execution errors\n * if (context.errorType === \"parse\") {\n * return false;\n * }\n * if (context.error.includes(\"CRITICAL\")) {\n * return false;\n * }\n * return true;\n * })\n * ```\n */\n withErrorHandler(\n handler: (context: {\n error: string;\n gadgetName: string;\n errorType: \"parse\" | \"validation\" | \"execution\";\n parameters?: Record<string, unknown>;\n }) => boolean | Promise<boolean>,\n ): this {\n this.shouldContinueAfterError = handler;\n return this;\n }\n\n /**\n * Set default timeout for gadget execution.\n *\n * @param timeoutMs - Timeout in milliseconds (must be non-negative)\n * @returns This builder for chaining\n * @throws {Error} If timeout is negative\n *\n * @example\n * ```typescript\n * .withDefaultGadgetTimeout(5000) // 5 second timeout\n * ```\n */\n withDefaultGadgetTimeout(timeoutMs: number): this {\n if (timeoutMs < 0) {\n throw new Error(\"Timeout must be a non-negative number\");\n }\n this.defaultGadgetTimeoutMs = timeoutMs;\n return this;\n }\n\n /**\n * Enable or disable gadget output limiting.\n *\n * When enabled, gadget outputs exceeding the configured limit are stored\n * and can be browsed using the GadgetOutputViewer gadget.\n *\n * @param enabled - Whether to enable output limiting (default: true)\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withGadgetOutputLimit(false) // Disable output limiting\n * ```\n */\n withGadgetOutputLimit(enabled: boolean): this {\n this.gadgetOutputLimit = enabled;\n return this;\n }\n\n /**\n * Set the maximum gadget output as a percentage of the model's context window.\n *\n * Outputs exceeding this limit are stored for later browsing with GadgetOutputViewer.\n *\n * @param percent - Percentage of context window (1-100, default: 15)\n * @returns This builder for chaining\n * @throws {Error} If percent is not between 1 and 100\n *\n * @example\n * ```typescript\n * .withGadgetOutputLimitPercent(25) // 25% of context window\n * ```\n */\n withGadgetOutputLimitPercent(percent: number): this {\n if (percent < 1 || percent > 100) {\n throw new Error(\"Output limit percent must be between 1 and 100\");\n }\n this.gadgetOutputLimitPercent = percent;\n return this;\n }\n\n /**\n * Configure context compaction.\n *\n * Context compaction automatically manages conversation history to prevent\n * context window overflow in long-running agent conversations.\n *\n * @param config - Compaction configuration options\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Custom thresholds\n * .withCompaction({\n * triggerThresholdPercent: 70,\n * targetPercent: 40,\n * preserveRecentTurns: 10,\n * })\n *\n * // Different strategy\n * .withCompaction({\n * strategy: 'sliding-window',\n * })\n *\n * // With callback\n * .withCompaction({\n * onCompaction: (event) => {\n * console.log(`Saved ${event.tokensBefore - event.tokensAfter} tokens`);\n * }\n * })\n * ```\n */\n withCompaction(config: CompactionConfig): this {\n this.compactionConfig = { ...config, enabled: config.enabled ?? true };\n return this;\n }\n\n /**\n * Disable context compaction.\n *\n * By default, compaction is enabled. Use this method to explicitly disable it.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withoutCompaction() // Disable automatic compaction\n * ```\n */\n withoutCompaction(): this {\n this.compactionConfig = { enabled: false };\n return this;\n }\n\n /**\n * Set an abort signal for cancelling requests mid-flight.\n *\n * When the signal is aborted, the current LLM request will be cancelled\n * and the agent loop will exit gracefully.\n *\n * @param signal - AbortSignal from an AbortController\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n *\n * // Cancel after 30 seconds\n * setTimeout(() => controller.abort(), 30000);\n *\n * const agent = LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withSignal(controller.signal)\n * .ask(\"Write a long story\");\n *\n * // Or cancel on user action\n * document.getElementById(\"cancel\").onclick = () => controller.abort();\n * ```\n */\n withSignal(signal: AbortSignal): this {\n this.signal = signal;\n return this;\n }\n\n /**\n * Add a synthetic gadget call to the conversation history.\n *\n * This is useful for in-context learning - showing the LLM what \"past self\"\n * did correctly so it mimics the pattern. The call is formatted with proper\n * markers and parameter format.\n *\n * @param gadgetName - Name of the gadget\n * @param parameters - Parameters passed to the gadget\n * @param result - Result returned by the gadget\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withSyntheticGadgetCall(\n * 'TellUser',\n * {\n * message: '👋 Hello!\\n\\nHere\\'s what I can do:\\n- Analyze code\\n- Run commands',\n * done: false,\n * type: 'info'\n * },\n * 'ℹ️ 👋 Hello!\\n\\nHere\\'s what I can do:\\n- Analyze code\\n- Run commands'\n * )\n * ```\n */\n withSyntheticGadgetCall(\n gadgetName: string,\n parameters: Record<string, unknown>,\n result: string,\n ): this {\n const startPrefix = this.gadgetStartPrefix ?? GADGET_START_PREFIX;\n const endPrefix = this.gadgetEndPrefix ?? GADGET_END_PREFIX;\n\n const paramStr = this.formatBlockParameters(parameters, \"\");\n\n // Assistant message with gadget call\n this.initialMessages.push({\n role: \"assistant\",\n content: `${startPrefix}${gadgetName}\\n${paramStr}\\n${endPrefix}`,\n });\n\n // User message with result\n this.initialMessages.push({\n role: \"user\",\n content: `Result: ${result}`,\n });\n\n return this;\n }\n\n /**\n * Format parameters as block format with JSON Pointer paths.\n */\n private formatBlockParameters(params: Record<string, unknown>, prefix: string): string {\n const lines: string[] = [];\n const argPrefix = this.gadgetArgPrefix ?? GADGET_ARG_PREFIX;\n\n for (const [key, value] of Object.entries(params)) {\n const fullPath = prefix ? `${prefix}/${key}` : key;\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n const itemPath = `${fullPath}/${index}`;\n if (typeof item === \"object\" && item !== null) {\n lines.push(this.formatBlockParameters(item as Record<string, unknown>, itemPath));\n } else {\n lines.push(`${argPrefix}${itemPath}`);\n lines.push(String(item));\n }\n });\n } else if (typeof value === \"object\" && value !== null) {\n lines.push(this.formatBlockParameters(value as Record<string, unknown>, fullPath));\n } else {\n lines.push(`${argPrefix}${fullPath}`);\n lines.push(String(value));\n }\n }\n\n return lines.join(\"\\n\");\n }\n\n /**\n * Build and create the agent with the given user prompt.\n * Returns the Agent instance ready to run.\n *\n * @param userPrompt - User's question or request\n * @returns Configured Agent instance\n *\n * @example\n * ```typescript\n * const agent = await LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator)\n * .ask(\"What is 2+2?\");\n *\n * for await (const event of agent.run()) {\n * // handle events\n * }\n * ```\n */\n ask(userPrompt: string): Agent {\n // Lazy import to avoid circular dependency\n if (!this.client) {\n const { LLMist: LLMistClass } =\n require(\"../core/client.js\") as typeof import(\"../core/client.js\");\n this.client = new LLMistClass();\n }\n const registry = GadgetRegistry.from(this.gadgets);\n\n const options: AgentOptions = {\n client: this.client,\n model: this.model ?? \"openai:gpt-5-nano\",\n systemPrompt: this.systemPrompt,\n userPrompt,\n registry,\n maxIterations: this.maxIterations,\n temperature: this.temperature,\n logger: this.logger,\n hooks: this.hooks,\n promptConfig: this.promptConfig,\n initialMessages: this.initialMessages,\n onHumanInputRequired: this.onHumanInputRequired,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n textOnlyHandler: this.textOnlyHandler,\n textWithGadgetsHandler: this.textWithGadgetsHandler,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinueAfterError: this.shouldContinueAfterError,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n gadgetOutputLimit: this.gadgetOutputLimit,\n gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,\n compactionConfig: this.compactionConfig,\n signal: this.signal,\n };\n\n return new Agent(AGENT_INTERNAL_KEY, options);\n }\n\n /**\n * Build, run, and collect only the text response.\n * Convenient for simple queries where you just want the final answer.\n *\n * @param userPrompt - User's question or request\n * @returns Promise resolving to the complete text response\n *\n * @example\n * ```typescript\n * const answer = await LLMist.createAgent()\n * .withModel(\"gpt4-mini\")\n * .withGadgets(Calculator)\n * .askAndCollect(\"What is 42 * 7?\");\n *\n * console.log(answer); // \"294\"\n * ```\n */\n async askAndCollect(userPrompt: string): Promise<string> {\n const agent = this.ask(userPrompt);\n return collectText(agent.run());\n }\n\n /**\n * Build and run with event handlers.\n * Combines agent creation and event handling in one call.\n *\n * @param userPrompt - User's question or request\n * @param handlers - Event handlers\n *\n * @example\n * ```typescript\n * await LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator)\n * .askWith(\"What is 2+2?\", {\n * onText: (text) => console.log(\"LLM:\", text),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\n async askWith(userPrompt: string, handlers: EventHandlers): Promise<void> {\n const agent = this.ask(userPrompt);\n await agent.runWith(handlers);\n }\n\n /**\n * Build the agent without a user prompt.\n *\n * Returns an Agent instance that can be inspected (e.g., check registered gadgets)\n * but cannot be run without first calling .ask(prompt).\n *\n * This is useful for:\n * - Testing: Inspect the registry, configuration, etc.\n * - Advanced use cases: Build agent configuration separately from execution\n *\n * @returns Configured Agent instance (without user prompt)\n *\n * @example\n * ```typescript\n * // Build agent for inspection\n * const agent = new AgentBuilder()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator, Weather)\n * .build();\n *\n * // Inspect registered gadgets\n * console.log(agent.getRegistry().getNames()); // ['Calculator', 'Weather']\n *\n * // Note: Calling agent.run() will throw an error\n * // Use .ask(prompt) instead if you want to run the agent\n * ```\n */\n build(): Agent {\n // Lazy import to avoid circular dependency\n if (!this.client) {\n const { LLMist: LLMistClass } =\n require(\"../core/client.js\") as typeof import(\"../core/client.js\");\n this.client = new LLMistClass();\n }\n const registry = GadgetRegistry.from(this.gadgets);\n\n const options: AgentOptions = {\n client: this.client,\n model: this.model ?? \"openai:gpt-5-nano\",\n systemPrompt: this.systemPrompt,\n // No userPrompt - agent.run() will throw if called directly\n registry,\n maxIterations: this.maxIterations,\n temperature: this.temperature,\n logger: this.logger,\n hooks: this.hooks,\n promptConfig: this.promptConfig,\n initialMessages: this.initialMessages,\n onHumanInputRequired: this.onHumanInputRequired,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n textOnlyHandler: this.textOnlyHandler,\n textWithGadgetsHandler: this.textWithGadgetsHandler,\n stopOnGadgetError: this.stopOnGadgetError,\n shouldContinueAfterError: this.shouldContinueAfterError,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n gadgetOutputLimit: this.gadgetOutputLimit,\n gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,\n compactionConfig: this.compactionConfig,\n signal: this.signal,\n };\n\n return new Agent(AGENT_INTERNAL_KEY, options);\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 (with optional abort signal)\n const rawStream = await this.executeStreamRequest(payload, options.signal);\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 * @param signal - Optional abort signal for cancelling the request\n * @returns An async iterable of provider-specific chunks\n */\n protected abstract executeStreamRequest(\n payload: unknown,\n signal?: AbortSignal,\n ): 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 signal?: AbortSignal,\n ): Promise<AsyncIterable<MessageStreamEvent>> {\n const client = this.client as Anthropic;\n // Pass abort signal to SDK via request options\n const stream = await client.messages.create(payload, signal ? { signal } : undefined);\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(\n payload: {\n model: string;\n contents: Array<{ role: string; parts: Array<{ text: string }> }>;\n config: Record<string, unknown>;\n },\n signal?: AbortSignal,\n ): Promise<AsyncIterable<GeminiChunk>> {\n const client = this.client as GoogleGenAI;\n // Gemini SDK uses abortSignal in the config object\n const streamResponse = await client.models.generateContentStream({\n ...payload,\n config: {\n ...payload.config,\n ...(signal ? { abortSignal: signal } : {}),\n },\n });\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 signal?: AbortSignal,\n ): Promise<AsyncIterable<ChatCompletionChunk>> {\n const client = this.client as OpenAI;\n // Pass abort signal to SDK via request options\n const stream = await client.chat.completions.create(payload, signal ? { signal } : undefined);\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 * Optional abort signal for cancelling the request mid-flight.\n *\n * When the signal is aborted, the provider will attempt to cancel\n * the underlying HTTP request and the stream will terminate with\n * an abort error. Use `isAbortError()` from `@/core/errors` to\n * detect cancellation in error handling.\n *\n * @example\n * ```typescript\n * const controller = new AbortController();\n *\n * const stream = client.stream({\n * model: \"claude-3-5-sonnet-20241022\",\n * messages: [{ role: \"user\", content: \"Tell me a long story\" }],\n * signal: controller.signal,\n * });\n *\n * // Cancel after 5 seconds\n * setTimeout(() => controller.abort(), 5000);\n *\n * try {\n * for await (const chunk of stream) {\n * process.stdout.write(chunk.text);\n * }\n * } catch (error) {\n * if (isAbortError(error)) {\n * console.log(\"\\nRequest was cancelled\");\n * } else {\n * throw error;\n * }\n * }\n * ```\n */\n signal?: AbortSignal;\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 * 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","/**\n * Testing utilities for gadgets.\n *\n * Provides helpers for testing gadgets with schema validation without\n * requiring full executor setup.\n *\n * @module testing/gadget-testing\n */\n\nimport type { BaseGadget } from \"../gadgets/gadget.js\";\nimport { type ValidationResult, validateGadgetParams } from \"../gadgets/validation.js\";\n\n/**\n * Result of testing a gadget.\n */\nexport interface TestGadgetResult {\n /** Result string if execution succeeded */\n result?: string;\n /** Error message if validation or execution failed */\n error?: string;\n /** Parameters after validation and default application */\n validatedParams?: Record<string, unknown>;\n}\n\n/**\n * Options for testGadget.\n */\nexport interface TestGadgetOptions {\n /**\n * If true, skip schema validation.\n * Useful for testing gadget behavior with invalid parameters.\n */\n skipValidation?: boolean;\n}\n\n/**\n * Test a gadget with schema validation and default application.\n *\n * This helper replicates the validation behavior from GadgetExecutor.execute(),\n * making it easy to test gadgets in isolation without setting up a full\n * registry and executor.\n *\n * @param gadget - Gadget instance to test\n * @param params - Raw parameters (before validation)\n * @param options - Test options\n * @returns Promise resolving to test result\n *\n * @example\n * ```typescript\n * import { testGadget } from 'llmist/testing';\n * import { 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 * // Test with defaults applied\n * const result = await testGadget(calculator, { a: 5 });\n * expect(result.result).toBe('5');\n * expect(result.validatedParams).toEqual({ a: 5, b: 0 });\n *\n * // Test validation errors\n * const invalid = await testGadget(calculator, { a: 'not a number' });\n * expect(invalid.error).toContain('Invalid parameters');\n *\n * // Test with validation skipped\n * const skipped = await testGadget(calculator, { a: 5 }, { skipValidation: true });\n * expect(skipped.validatedParams).toEqual({ a: 5 }); // No defaults applied\n * ```\n */\nexport async function testGadget(\n gadget: BaseGadget,\n params: Record<string, unknown>,\n options?: TestGadgetOptions,\n): Promise<TestGadgetResult> {\n let validatedParams = params;\n\n // Apply validation if schema exists and not skipped\n if (!options?.skipValidation) {\n const validationResult: ValidationResult = validateGadgetParams(gadget, params);\n\n if (!validationResult.success) {\n return {\n error: validationResult.error,\n validatedParams: params,\n };\n }\n\n validatedParams = validationResult.data;\n }\n\n // Execute the gadget\n try {\n const result = await Promise.resolve(gadget.execute(validatedParams));\n return {\n result,\n validatedParams,\n };\n } catch (error) {\n return {\n error: error instanceof Error ? error.message : String(error),\n validatedParams,\n };\n }\n}\n\n/**\n * Test multiple parameter sets against a gadget.\n *\n * Convenience helper for running the same gadget with different inputs.\n *\n * @param gadget - Gadget instance to test\n * @param paramSets - Array of parameter sets to test\n * @param options - Test options applied to all tests\n * @returns Promise resolving to array of test results\n *\n * @example\n * ```typescript\n * const results = await testGadgetBatch(calculator, [\n * { a: 1, b: 2 },\n * { a: 5 },\n * { a: 'invalid' },\n * ]);\n *\n * expect(results[0].result).toBe('3');\n * expect(results[1].result).toBe('5');\n * expect(results[2].error).toBeDefined();\n * ```\n */\nexport async function testGadgetBatch(\n gadget: BaseGadget,\n paramSets: Record<string, unknown>[],\n options?: TestGadgetOptions,\n): Promise<TestGadgetResult[]> {\n return Promise.all(paramSets.map((params) => testGadget(gadget, params, options)));\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","/**\n * Stream testing utilities for llmist.\n * Provides helpers for creating and consuming test streams.\n */\n\nimport type { LLMStream, LLMStreamChunk } from \"../core/options.js\";\n\n/**\n * Create an async iterable stream from an array of chunks.\n * Useful for creating deterministic test streams.\n *\n * @param chunks - Array of chunks to yield\n * @returns An async iterable that yields the chunks in order\n *\n * @example\n * ```typescript\n * const stream = createTestStream([\n * { text: \"Hello \" },\n * { text: \"world\", finishReason: \"stop\", usage: { inputTokens: 10, outputTokens: 5 } }\n * ]);\n * ```\n */\nexport function createTestStream(chunks: LLMStreamChunk[]): LLMStream {\n return (async function* () {\n for (const chunk of chunks) {\n yield chunk;\n }\n })();\n}\n\n/**\n * Create a stream that yields text in specified chunks.\n * Automatically adds finishReason and usage to the final chunk.\n *\n * @param text - The full text to stream\n * @param options - Configuration options\n * @returns An async iterable stream\n *\n * @example\n * ```typescript\n * const stream = createTextStream(\"Hello, world!\", { chunkSize: 5 });\n * // Yields: \"Hello\", \", wor\", \"ld!\"\n * ```\n */\nexport function createTextStream(\n text: string,\n options?: {\n /** Size of each chunk (default: entire text as one chunk) */\n chunkSize?: number;\n /** Delay before starting the stream in ms */\n delayMs?: number;\n /** Delay between chunks in ms */\n chunkDelayMs?: number;\n /** Custom usage stats */\n usage?: { inputTokens: number; outputTokens: number; totalTokens: number };\n /** Custom finish reason (default: \"stop\") */\n finishReason?: string;\n },\n): LLMStream {\n return (async function* () {\n if (options?.delayMs) {\n await sleep(options.delayMs);\n }\n\n const chunkSize = options?.chunkSize ?? text.length;\n const chunks: string[] = [];\n\n for (let i = 0; i < text.length; i += chunkSize) {\n chunks.push(text.slice(i, i + chunkSize));\n }\n\n for (let i = 0; i < chunks.length; i++) {\n const isLast = i === chunks.length - 1;\n\n const chunk: LLMStreamChunk = { text: chunks[i] };\n\n if (isLast) {\n chunk.finishReason = options?.finishReason ?? \"stop\";\n // Simplified token estimation heuristic (~4 chars per token) for testing only.\n // For accurate token counts, provide explicit usage in options.\n const inputTokens = Math.ceil(text.length / 4);\n const outputTokens = Math.ceil(text.length / 4);\n chunk.usage = options?.usage ?? {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n };\n }\n\n yield chunk;\n\n if (options?.chunkDelayMs && !isLast) {\n await sleep(options.chunkDelayMs);\n }\n }\n })();\n}\n\n/**\n * Collect all chunks from a stream into an array.\n * Useful for asserting on stream output in tests.\n *\n * @param stream - The stream to collect from\n * @returns Array of all chunks from the stream\n *\n * @example\n * ```typescript\n * const chunks = await collectStream(myStream);\n * expect(chunks).toHaveLength(3);\n * expect(chunks[2].finishReason).toBe(\"stop\");\n * ```\n */\nexport async function collectStream(stream: LLMStream): Promise<LLMStreamChunk[]> {\n const chunks: LLMStreamChunk[] = [];\n for await (const chunk of stream) {\n chunks.push(chunk);\n }\n return chunks;\n}\n\n/**\n * Collect all text from a stream into a single string.\n *\n * @param stream - The stream to collect from\n * @returns Concatenated text from all chunks\n *\n * @example\n * ```typescript\n * const text = await collectStreamText(myStream);\n * expect(text).toBe(\"Hello, world!\");\n * ```\n */\nexport async function collectStreamText(stream: LLMStream): Promise<string> {\n let text = \"\";\n for await (const chunk of stream) {\n text += chunk.text ?? \"\";\n }\n return text;\n}\n\n/**\n * Get the final chunk from a stream (containing finishReason and usage).\n *\n * @param stream - The stream to consume\n * @returns The final chunk from the stream\n */\nexport async function getStreamFinalChunk(stream: LLMStream): Promise<LLMStreamChunk | undefined> {\n let lastChunk: LLMStreamChunk | undefined;\n for await (const chunk of stream) {\n lastChunk = chunk;\n }\n return lastChunk;\n}\n\n/**\n * Create an empty stream that yields nothing.\n * Useful for testing edge cases.\n */\nexport function createEmptyStream(): LLMStream {\n return (async function* () {\n // Empty stream\n })();\n}\n\n/**\n * Create a stream that throws an error after yielding some chunks.\n * Useful for testing error handling.\n *\n * @param chunksBeforeError - Chunks to yield before throwing\n * @param error - The error to throw\n */\nexport function createErrorStream(\n chunksBeforeError: LLMStreamChunk[],\n error: Error,\n): LLMStream {\n return (async function* () {\n for (const chunk of chunksBeforeError) {\n yield chunk;\n }\n throw error;\n })();\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * Conversation fixture generators for testing.\n * Provides utilities for creating test conversation data.\n */\n\nimport type { LLMMessage } from \"../core/messages.js\";\n\n/**\n * Create a conversation with a specified number of turns.\n * Each turn consists of a user message and an assistant response.\n *\n * @param turnCount - Number of conversation turns to generate\n * @param options - Configuration options\n * @returns Array of LLMMessages representing the conversation\n *\n * @example\n * ```typescript\n * const messages = createConversation(5);\n * // Creates 10 messages: 5 user + 5 assistant\n * ```\n */\nexport function createConversation(\n turnCount: number,\n options?: {\n /** Prefix for user messages (default: \"User message\") */\n userPrefix?: string;\n /** Prefix for assistant messages (default: \"Assistant response\") */\n assistantPrefix?: string;\n /** Base content length per message (default: 100 chars) */\n contentLength?: number;\n },\n): LLMMessage[] {\n const messages: LLMMessage[] = [];\n const userPrefix = options?.userPrefix ?? \"User message\";\n const assistantPrefix = options?.assistantPrefix ?? \"Assistant response\";\n const contentLength = options?.contentLength ?? 100;\n\n for (let i = 0; i < turnCount; i++) {\n // Generate content to fill approximate length\n const padding = \" \".repeat(Math.max(0, contentLength - 30));\n\n messages.push({\n role: \"user\",\n content: `${userPrefix} ${i + 1}: This is turn ${i + 1} of the conversation.${padding}`,\n });\n\n messages.push({\n role: \"assistant\",\n content: `${assistantPrefix} ${i + 1}: I acknowledge turn ${i + 1}.${padding}`,\n });\n }\n\n return messages;\n}\n\n/**\n * Create a conversation with gadget calls interspersed.\n * Simulates an agent conversation with tool usage.\n *\n * @param turnCount - Number of conversation turns\n * @param gadgetCallsPerTurn - Number of gadget calls per assistant turn\n * @returns Array of LLMMessages including gadget call/result pairs\n *\n * @example\n * ```typescript\n * const messages = createConversationWithGadgets(3, 2);\n * // Creates: user, assistant+gadget, gadget-result, assistant+gadget, gadget-result, assistant (per turn)\n * ```\n */\nexport function createConversationWithGadgets(\n turnCount: number,\n gadgetCallsPerTurn: number = 1,\n options?: {\n /** Gadget names to cycle through (default: [\"search\", \"calculate\", \"read\"]) */\n gadgetNames?: string[];\n /** Content length for messages */\n contentLength?: number;\n },\n): LLMMessage[] {\n const messages: LLMMessage[] = [];\n const gadgetNames = options?.gadgetNames ?? [\"search\", \"calculate\", \"read\"];\n const contentLength = options?.contentLength ?? 50;\n let gadgetIndex = 0;\n\n for (let turn = 0; turn < turnCount; turn++) {\n // User message\n messages.push({\n role: \"user\",\n content: `User request ${turn + 1}${\"x\".repeat(contentLength)}`,\n });\n\n // Assistant with gadget calls\n for (let g = 0; g < gadgetCallsPerTurn; g++) {\n const gadgetName = gadgetNames[gadgetIndex % gadgetNames.length];\n gadgetIndex++;\n\n // Gadget call (assistant message)\n messages.push({\n role: \"assistant\",\n content: `!!!GADGET_START:${gadgetName}\\n!!!ARG:query\\ntest query ${turn}-${g}\\n!!!GADGET_END`,\n });\n\n // Gadget result (user message)\n messages.push({\n role: \"user\",\n content: `Result: Gadget ${gadgetName} returned result for query ${turn}-${g}`,\n });\n }\n\n // Final assistant response for this turn\n messages.push({\n role: \"assistant\",\n content: `Final response for turn ${turn + 1}${\"y\".repeat(contentLength)}`,\n });\n }\n\n return messages;\n}\n\n/**\n * Estimate token count for a message array.\n * Uses a simple 4-characters-per-token heuristic.\n *\n * @param messages - Messages to estimate tokens for\n * @returns Estimated token count\n *\n * @example\n * ```typescript\n * const messages = createConversation(10);\n * const tokens = estimateTokens(messages);\n * // Returns approximate token count\n * ```\n */\nexport function estimateTokens(messages: LLMMessage[]): number {\n return Math.ceil(\n messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4,\n );\n}\n\n/**\n * Create a single user message.\n */\nexport function createUserMessage(content: string): LLMMessage {\n return { role: \"user\", content };\n}\n\n/**\n * Create a single assistant message.\n */\nexport function createAssistantMessage(content: string): LLMMessage {\n return { role: \"assistant\", content };\n}\n\n/**\n * Create a system message.\n */\nexport function createSystemMessage(content: string): LLMMessage {\n return { role: \"system\", content };\n}\n\n/**\n * Create a minimal conversation for quick tests.\n * Returns a single turn: one user message and one assistant response.\n */\nexport function createMinimalConversation(): LLMMessage[] {\n return [\n { role: \"user\", content: \"Hello\" },\n { role: \"assistant\", content: \"Hi there!\" },\n ];\n}\n\n/**\n * Create a conversation that exceeds a target token count.\n * Useful for testing compaction triggers.\n *\n * @param targetTokens - Minimum token count to exceed\n * @param options - Configuration options\n * @returns Conversation with at least targetTokens tokens\n */\nexport function createLargeConversation(\n targetTokens: number,\n options?: {\n /** Average tokens per turn (default: 200) */\n tokensPerTurn?: number;\n },\n): LLMMessage[] {\n const tokensPerTurn = options?.tokensPerTurn ?? 200;\n const turnsNeeded = Math.ceil(targetTokens / tokensPerTurn);\n\n // Each character is ~0.25 tokens, so multiply by 4 for chars\n const charsPerMessage = Math.floor((tokensPerTurn * 4) / 2); // Divide by 2 for user + assistant\n\n return createConversation(turnsNeeded, {\n contentLength: charsPerMessage,\n });\n}\n","/**\n * Mock ConversationManager for testing compaction and agent components.\n * Implements IConversationManager interface with test-friendly features.\n */\n\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { IConversationManager } from \"../agent/interfaces.js\";\n\n/**\n * A mock implementation of IConversationManager for testing.\n * Tracks all operations and allows inspection of state changes.\n *\n * @example\n * ```typescript\n * const mockConvo = new MockConversationManager([\n * { role: \"user\", content: \"Hello\" },\n * { role: \"assistant\", content: \"Hi!\" }\n * ]);\n *\n * // Use in compaction tests\n * compactionManager.checkAndCompact(mockConvo, 1);\n *\n * // Assert on state changes\n * expect(mockConvo.wasReplaceHistoryCalled()).toBe(true);\n * expect(mockConvo.getReplacementHistory()).toHaveLength(2);\n * ```\n */\nexport class MockConversationManager implements IConversationManager {\n private history: LLMMessage[];\n private readonly baseMessages: LLMMessage[];\n private replacementHistory: LLMMessage[] | undefined;\n private replaceHistoryCallCount = 0;\n private addedMessages: LLMMessage[] = [];\n\n constructor(\n history: LLMMessage[] = [],\n baseMessages: LLMMessage[] = [],\n ) {\n this.history = [...history];\n this.baseMessages = [...baseMessages];\n }\n\n addUserMessage(content: string): void {\n const msg: LLMMessage = { role: \"user\", content };\n this.history.push(msg);\n this.addedMessages.push(msg);\n }\n\n addAssistantMessage(content: string): void {\n const msg: LLMMessage = { role: \"assistant\", content };\n this.history.push(msg);\n this.addedMessages.push(msg);\n }\n\n addGadgetCall(gadgetName: string, parameters: Record<string, unknown>, result: string): void {\n // Simplified gadget call format for testing\n const assistantMsg: LLMMessage = {\n role: \"assistant\",\n content: `!!!GADGET_START:${gadgetName}\\n${JSON.stringify(parameters)}\\n!!!GADGET_END`,\n };\n const resultMsg: LLMMessage = {\n role: \"user\",\n content: `Result: ${result}`,\n };\n\n this.history.push(assistantMsg);\n this.history.push(resultMsg);\n this.addedMessages.push(assistantMsg);\n this.addedMessages.push(resultMsg);\n }\n\n getMessages(): LLMMessage[] {\n return [...this.baseMessages, ...this.history];\n }\n\n getHistoryMessages(): LLMMessage[] {\n return [...this.history];\n }\n\n getBaseMessages(): LLMMessage[] {\n return [...this.baseMessages];\n }\n\n replaceHistory(newHistory: LLMMessage[]): void {\n this.replacementHistory = [...newHistory];\n this.history = [...newHistory];\n this.replaceHistoryCallCount++;\n }\n\n // ============================================\n // Test Helper Methods\n // ============================================\n\n /**\n * Check if replaceHistory was called.\n */\n wasReplaceHistoryCalled(): boolean {\n return this.replaceHistoryCallCount > 0;\n }\n\n /**\n * Get the number of times replaceHistory was called.\n */\n getReplaceHistoryCallCount(): number {\n return this.replaceHistoryCallCount;\n }\n\n /**\n * Get the most recent history passed to replaceHistory.\n * Returns undefined if replaceHistory was never called.\n */\n getReplacementHistory(): LLMMessage[] | undefined {\n return this.replacementHistory;\n }\n\n /**\n * Get all messages that were added via add* methods.\n */\n getAddedMessages(): LLMMessage[] {\n return [...this.addedMessages];\n }\n\n /**\n * Reset all tracking state while preserving the conversation.\n */\n resetTracking(): void {\n this.replacementHistory = undefined;\n this.replaceHistoryCallCount = 0;\n this.addedMessages = [];\n }\n\n /**\n * Completely reset the mock to initial state.\n * Note: baseMessages cannot be changed after construction.\n */\n reset(history: LLMMessage[] = []): void {\n this.history = [...history];\n this.resetTracking();\n }\n\n /**\n * Set the history directly (for test setup).\n */\n setHistory(messages: LLMMessage[]): void {\n this.history = [...messages];\n }\n\n /**\n * Get the current history length.\n */\n getHistoryLength(): number {\n return this.history.length;\n }\n\n /**\n * Get total message count (base + history).\n */\n getTotalMessageCount(): number {\n return this.baseMessages.length + this.history.length;\n }\n}\n\n/**\n * Create a mock conversation manager with a pre-populated conversation.\n *\n * @param turnCount - Number of conversation turns\n * @param baseMessages - Optional base messages (system prompts)\n * @returns Configured MockConversationManager\n */\nexport function createMockConversationManager(\n turnCount: number,\n baseMessages: LLMMessage[] = [],\n): MockConversationManager {\n const history: LLMMessage[] = [];\n\n for (let i = 0; i < turnCount; i++) {\n history.push({\n role: \"user\",\n content: `User message ${i + 1}: This is turn ${i + 1} of the conversation.`,\n });\n history.push({\n role: \"assistant\",\n content: `Assistant response ${i + 1}: I acknowledge turn ${i + 1}.`,\n });\n }\n\n return new MockConversationManager(history, baseMessages);\n}\n","/**\n * CLI testing utilities for llmist.\n * Provides helpers for testing CLI commands without real I/O.\n */\n\nimport { PassThrough, Readable, Writable } from \"node:stream\";\n\n/**\n * Options for creating a test environment.\n */\nexport interface TestEnvironmentOptions {\n /** Input to provide via stdin (string or line array) */\n stdin?: string | string[];\n /** Whether stdin is a TTY (default: false) */\n isTTY?: boolean;\n /** Environment variables to set */\n env?: Record<string, string>;\n /** Command line arguments (default: [\"node\", \"llmist\"]) */\n argv?: string[];\n}\n\n/**\n * A test environment with captured I/O streams.\n */\nexport interface TestEnvironment {\n /** Stdin readable stream */\n stdin: Readable;\n /** Stdout writable stream (PassThrough for capturing) */\n stdout: PassThrough;\n /** Stderr writable stream (PassThrough for capturing) */\n stderr: PassThrough;\n /** Whether stdin is TTY */\n isTTY: boolean;\n /** Command line arguments */\n argv: string[];\n /** Environment variables */\n env: Record<string, string>;\n /** Exit code if set */\n exitCode?: number;\n /** Function to set exit code */\n setExitCode: (code: number) => void;\n}\n\n/**\n * Create a test environment with mocked I/O streams.\n *\n * @param options - Configuration options\n * @returns A test environment with captured streams\n *\n * @example\n * ```typescript\n * const env = createTestEnvironment({\n * stdin: '{\"param\": \"value\"}',\n * isTTY: false\n * });\n *\n * // Pass to CLI command\n * await executeCommand(env);\n *\n * // Check output\n * const output = await collectOutput(env.stdout);\n * expect(output).toContain(\"Success\");\n * ```\n */\nexport function createTestEnvironment(options: TestEnvironmentOptions = {}): TestEnvironment {\n const stdin = createMockReadable(options.stdin);\n const stdout = new PassThrough();\n const stderr = new PassThrough();\n\n let exitCode: number | undefined;\n\n return {\n stdin,\n stdout,\n stderr,\n isTTY: options.isTTY ?? false,\n argv: options.argv ?? [\"node\", \"llmist\"],\n env: { ...filterDefinedEnv(process.env), ...options.env },\n get exitCode() {\n return exitCode;\n },\n setExitCode: (code: number) => {\n exitCode = code;\n },\n };\n}\n\n/**\n * Create a readable stream from a string or array of lines.\n *\n * @param input - String content or array of lines\n * @returns A Readable stream\n *\n * @example\n * ```typescript\n * const stream = createMockReadable(\"line1\\nline2\\n\");\n * // or\n * const stream = createMockReadable([\"line1\", \"line2\"]);\n * ```\n */\nexport function createMockReadable(input?: string | string[]): Readable {\n if (!input) {\n // Empty stream that ends immediately\n const stream = new Readable({ read() {} });\n stream.push(null);\n return stream;\n }\n\n const content = Array.isArray(input) ? `${input.join(\"\\n\")}\\n` : input;\n\n const stream = new Readable({ read() {} });\n stream.push(content);\n stream.push(null);\n return stream;\n}\n\n/**\n * Create a writable stream that collects all written data.\n *\n * @returns A writable stream with getData() method\n */\nexport function createMockWritable(): Writable & { getData(): string } {\n const chunks: Buffer[] = [];\n\n const stream = new Writable({\n write(chunk, _encoding, callback) {\n chunks.push(Buffer.from(chunk));\n callback();\n },\n }) as Writable & { getData(): string };\n\n stream.getData = () => Buffer.concat(chunks).toString(\"utf8\");\n\n return stream;\n}\n\n/**\n * Collect all output from a PassThrough stream.\n * Waits for the stream to end before returning.\n *\n * @param stream - The stream to collect from\n * @param timeout - Maximum time to wait in ms (default: 5000)\n * @returns All data written to the stream\n *\n * @example\n * ```typescript\n * const output = await collectOutput(env.stdout);\n * expect(output).toContain(\"Expected text\");\n * ```\n */\nexport async function collectOutput(stream: PassThrough, timeout = 5000): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n\n const timeoutId = setTimeout(() => {\n // Return what we have so far if timeout\n resolve(Buffer.concat(chunks).toString(\"utf8\"));\n }, timeout);\n\n stream.on(\"data\", (chunk) => {\n chunks.push(Buffer.from(chunk));\n });\n\n stream.on(\"end\", () => {\n clearTimeout(timeoutId);\n resolve(Buffer.concat(chunks).toString(\"utf8\"));\n });\n\n stream.on(\"error\", (err) => {\n clearTimeout(timeoutId);\n reject(err);\n });\n });\n}\n\n/**\n * Collect output without waiting for stream end.\n * Returns immediately with whatever has been written.\n *\n * @param stream - The stream to read from\n * @returns Currently buffered data\n */\nexport function getBufferedOutput(stream: PassThrough): string {\n const chunks: Buffer[] = [];\n\n // Read all available data\n for (;;) {\n const chunk = stream.read() as Buffer | null;\n if (chunk === null) break;\n chunks.push(chunk);\n }\n\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\n/**\n * Create a mock prompt function for testing interactive input.\n *\n * @param responses - Array of responses to return in order\n * @returns A prompt function that returns the next response\n *\n * @example\n * ```typescript\n * const prompt = createMockPrompt([\"yes\", \"no\", \"maybe\"]);\n * expect(await prompt(\"Question 1?\")).toBe(\"yes\");\n * expect(await prompt(\"Question 2?\")).toBe(\"no\");\n * ```\n */\nexport function createMockPrompt(\n responses: string[],\n): (question: string) => Promise<string> {\n let index = 0;\n\n return async (_question: string): Promise<string> => {\n if (index >= responses.length) {\n throw new Error(`Mock prompt exhausted: no response for question ${index + 1}`);\n }\n return responses[index++];\n };\n}\n\n/**\n * Mock prompt that records questions and returns configured responses.\n */\nexport class MockPromptRecorder {\n private responses: string[];\n private index = 0;\n private questions: string[] = [];\n\n constructor(responses: string[]) {\n this.responses = responses;\n }\n\n /**\n * The prompt function to use in tests.\n */\n prompt = async (question: string): Promise<string> => {\n this.questions.push(question);\n if (this.index >= this.responses.length) {\n throw new Error(`Mock prompt exhausted after ${this.index} questions`);\n }\n return this.responses[this.index++];\n };\n\n /**\n * Get all questions that were asked.\n */\n getQuestions(): string[] {\n return [...this.questions];\n }\n\n /**\n * Get the number of questions asked.\n */\n getQuestionCount(): number {\n return this.questions.length;\n }\n\n /**\n * Reset the recorder state.\n */\n reset(newResponses?: string[]): void {\n this.index = 0;\n this.questions = [];\n if (newResponses) {\n this.responses = newResponses;\n }\n }\n}\n\n/**\n * Wait for a condition to be true, with timeout.\n * Useful for async testing scenarios.\n *\n * @param condition - Function that returns true when condition is met\n * @param timeout - Maximum time to wait in ms (default: 5000)\n * @param interval - Check interval in ms (default: 50)\n */\nexport async function waitFor(\n condition: () => boolean,\n timeout = 5000,\n interval = 50,\n): Promise<void> {\n const startTime = Date.now();\n\n while (!condition()) {\n if (Date.now() - startTime > timeout) {\n throw new Error(`waitFor timed out after ${timeout}ms`);\n }\n await sleep(interval);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction filterDefinedEnv(env: NodeJS.ProcessEnv): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(env)) {\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n"],"mappings":"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","names":["z","z","pointer","stream","stream","init_constants","init_constants","stream","init_constants","stream","init_constants","stream","providerSpecs","sleep","stream","stream","sleep"]}
|