llmist 10.0.0 → 10.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/constants.ts","../src/providers/constants.ts","../src/core/input-content.ts","../src/core/model-shortcuts.ts","../src/gadgets/schema-validator.ts","../src/gadgets/registry.ts","../src/core/execution-tree.ts","../src/core/prompt-config.ts","../src/core/messages.ts","../src/gadgets/media-store.ts","../src/gadgets/exceptions.ts","../src/logging/logger.ts","../src/gadgets/schema-to-json.ts","../src/gadgets/gadget.ts","../src/gadgets/create-gadget.ts","../src/gadgets/output-viewer.ts","../src/agent/agent-internal-key.ts","../src/core/retry.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/conversation-manager.ts","../src/agent/event-handlers.ts","../src/agent/gadget-output-store.ts","../src/agent/hook-validators.ts","../src/providers/anthropic-models.ts","../src/providers/base-provider.ts","../src/providers/utils.ts","../src/providers/anthropic.ts","../src/providers/gemini-image-models.ts","../src/providers/gemini-models.ts","../src/providers/gemini-speech-models.ts","../src/providers/gemini.ts","../src/providers/openai-image-models.ts","../src/providers/openai-models.ts","../src/providers/openai-speech-models.ts","../src/providers/openai.ts","../src/providers/discovery.ts","../src/core/model-registry.ts","../src/core/namespaces/image.ts","../src/core/namespaces/speech.ts","../src/core/quick-methods.ts","../src/core/namespaces/text.ts","../src/core/namespaces/vision.ts","../src/core/options.ts","../src/core/client.ts","../src/gadgets/schema-introspector.ts","../src/gadgets/block-params.ts","../src/gadgets/cost-reporting-client.ts","../src/gadgets/error-formatter.ts","../src/gadgets/parser.ts","../src/gadgets/typed-gadget.ts","../src/gadgets/executor.ts","../src/agent/stream-processor.ts","../src/agent/agent.ts","../src/agent/builder.ts","../src/index.ts","../src/agent/hook-presets.ts","../src/agent/compaction/index.ts","../src/agent/index.ts","../src/agent/hints.ts","../src/core/errors.ts","../src/core/execution-events.ts","../src/gadgets/helpers.ts","../src/gadgets/validation.ts","../src/utils/config-resolver.ts","../src/utils/format.ts","../src/utils/timing.ts","../src/session/manager.ts","../src/agent/subagent.ts","../src/package/manifest.ts"],"sourcesContent":["// Gadget marker constants\nexport const GADGET_START_PREFIX = \"!!!GADGET_START:\";\nexport const GADGET_END_PREFIX = \"!!!GADGET_END\";\nexport const GADGET_ARG_PREFIX = \"!!!ARG:\";\n\n// Default configuration values\nexport const DEFAULT_MAX_TOKENS = 1024;\nexport const DEFAULT_MAX_ITERATIONS = 10;\n\n// Gadget output limiting defaults\n/** Default: gadget output limiting is enabled */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT = true;\n\n/** Default: limit gadget output to 15% of context window */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;\n\n/** Approximate characters per token for limit calculation */\nexport const CHARS_PER_TOKEN = 4;\n\n/** Fallback context window size if model is not in registry */\nexport const FALLBACK_CONTEXT_WINDOW = 128_000;\n","/**\n * 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 * Types and interfaces for multimodal input content.\n *\n * These types define the structure for sending images, audio, and other\n * media alongside text in LLM messages. They complement the output types\n * in media-types.ts.\n */\n\n// ============================================================================\n// MIME Types\n// ============================================================================\n\n/**\n * Supported image MIME types for input.\n * All major providers support these formats.\n */\nexport type ImageMimeType = \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\";\n\n/**\n * Supported audio MIME types for input.\n * Currently only Gemini supports audio input.\n */\nexport type AudioMimeType =\n | \"audio/mp3\"\n | \"audio/mpeg\"\n | \"audio/wav\"\n | \"audio/webm\"\n | \"audio/ogg\"\n | \"audio/flac\";\n\n// ============================================================================\n// Content Part Types\n// ============================================================================\n\n/**\n * Base interface for all content parts.\n */\nexport interface BaseContentPart {\n type: string;\n}\n\n/**\n * Text content part.\n */\nexport interface TextContentPart extends BaseContentPart {\n type: \"text\";\n text: string;\n}\n\n/**\n * Image content part.\n */\nexport interface ImageContentPart extends BaseContentPart {\n type: \"image\";\n source: ImageSource;\n}\n\n/**\n * Audio content part.\n * Currently only supported by Gemini.\n */\nexport interface AudioContentPart extends BaseContentPart {\n type: \"audio\";\n source: AudioSource;\n}\n\n/**\n * Union of all supported content part types.\n */\nexport type ContentPart = TextContentPart | ImageContentPart | AudioContentPart;\n\n// ============================================================================\n// Source Types\n// ============================================================================\n\n/**\n * Image can come from base64 data or a URL.\n */\nexport type ImageSource = ImageBase64Source | ImageUrlSource;\n\n/**\n * Base64-encoded image data.\n * Supported by all providers.\n */\nexport interface ImageBase64Source {\n type: \"base64\";\n mediaType: ImageMimeType;\n data: string;\n}\n\n/**\n * Image URL reference.\n * Only supported by OpenAI.\n */\nexport interface ImageUrlSource {\n type: \"url\";\n url: string;\n}\n\n/**\n * Audio source (base64 only).\n * URL sources are not currently supported for audio.\n */\nexport interface AudioSource {\n type: \"base64\";\n mediaType: AudioMimeType;\n data: string;\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Check if a content part is a text part.\n */\nexport function isTextPart(part: ContentPart): part is TextContentPart {\n return part.type === \"text\";\n}\n\n/**\n * Check if a content part is an image part.\n */\nexport function isImagePart(part: ContentPart): part is ImageContentPart {\n return part.type === \"image\";\n}\n\n/**\n * Check if a content part is an audio part.\n */\nexport function isAudioPart(part: ContentPart): part is AudioContentPart {\n return part.type === \"audio\";\n}\n\n/**\n * Check if an image source is base64.\n */\nexport function isBase64ImageSource(source: ImageSource): source is ImageBase64Source {\n return source.type === \"base64\";\n}\n\n/**\n * Check if an image source is a URL.\n */\nexport function isUrlImageSource(source: ImageSource): source is ImageUrlSource {\n return source.type === \"url\";\n}\n\n// ============================================================================\n// Helper Functions - Content Part Creation\n// ============================================================================\n\n/**\n * Create a text content part.\n *\n * @example\n * ```typescript\n * const part = text(\"What's in this image?\");\n * ```\n */\nexport function text(content: string): TextContentPart {\n return { type: \"text\", text: content };\n}\n\n/**\n * Create an image content part from base64-encoded data.\n *\n * @param data - Base64-encoded image data\n * @param mediaType - MIME type of the image\n *\n * @example\n * ```typescript\n * const part = imageFromBase64(base64Data, \"image/jpeg\");\n * ```\n */\nexport function imageFromBase64(data: string, mediaType: ImageMimeType): ImageContentPart {\n return {\n type: \"image\",\n source: { type: \"base64\", mediaType, data },\n };\n}\n\n/**\n * Create an image content part from a URL.\n * Note: Only supported by OpenAI.\n *\n * @param url - URL to the image (must be accessible)\n *\n * @example\n * ```typescript\n * const part = imageFromUrl(\"https://example.com/image.jpg\");\n * ```\n */\nexport function imageFromUrl(url: string): ImageContentPart {\n return {\n type: \"image\",\n source: { type: \"url\", url },\n };\n}\n\n/**\n * Magic bytes for detecting image MIME types.\n */\nconst IMAGE_MAGIC_BYTES: Array<{ bytes: number[]; mimeType: ImageMimeType }> = [\n { bytes: [0xff, 0xd8, 0xff], mimeType: \"image/jpeg\" },\n { bytes: [0x89, 0x50, 0x4e, 0x47], mimeType: \"image/png\" },\n { bytes: [0x47, 0x49, 0x46, 0x38], mimeType: \"image/gif\" },\n // WebP starts with RIFF....WEBP\n { bytes: [0x52, 0x49, 0x46, 0x46], mimeType: \"image/webp\" },\n];\n\n/**\n * Magic bytes for detecting audio MIME types.\n */\nconst AUDIO_MAGIC_BYTES: Array<{ bytes: number[]; mimeType: AudioMimeType }> = [\n // MP3 frame sync\n { bytes: [0xff, 0xfb], mimeType: \"audio/mp3\" },\n { bytes: [0xff, 0xfa], mimeType: \"audio/mp3\" },\n // ID3 tag (MP3)\n { bytes: [0x49, 0x44, 0x33], mimeType: \"audio/mp3\" },\n // OGG\n { bytes: [0x4f, 0x67, 0x67, 0x53], mimeType: \"audio/ogg\" },\n // WAV (RIFF)\n { bytes: [0x52, 0x49, 0x46, 0x46], mimeType: \"audio/wav\" },\n // WebM\n { bytes: [0x1a, 0x45, 0xdf, 0xa3], mimeType: \"audio/webm\" },\n // FLAC (fLaC)\n { bytes: [0x66, 0x4c, 0x61, 0x43], mimeType: \"audio/flac\" },\n];\n\n/**\n * Detect the MIME type of image data from magic bytes.\n *\n * @param data - Raw image data\n * @returns Detected MIME type or null if unknown\n */\nexport function detectImageMimeType(data: Buffer | Uint8Array): ImageMimeType | null {\n const bytes = data instanceof Buffer ? data : Buffer.from(data);\n\n for (const { bytes: magic, mimeType } of IMAGE_MAGIC_BYTES) {\n if (bytes.length >= magic.length) {\n let matches = true;\n for (let i = 0; i < magic.length; i++) {\n if (bytes[i] !== magic[i]) {\n matches = false;\n break;\n }\n }\n if (matches) {\n // Special case: RIFF could be WebP or WAV, check for WEBP marker\n if (mimeType === \"image/webp\") {\n // RIFF....WEBP - check bytes 8-11\n if (bytes.length >= 12) {\n const webpMarker =\n bytes[8] === 0x57 && bytes[9] === 0x45 && bytes[10] === 0x42 && bytes[11] === 0x50;\n if (!webpMarker) continue; // Not WebP, try next pattern\n }\n }\n return mimeType;\n }\n }\n }\n return null;\n}\n\n/**\n * Detect the MIME type of audio data from magic bytes.\n *\n * @param data - Raw audio data\n * @returns Detected MIME type or null if unknown\n */\nexport function detectAudioMimeType(data: Buffer | Uint8Array): AudioMimeType | null {\n const bytes = data instanceof Buffer ? data : Buffer.from(data);\n\n for (const { bytes: magic, mimeType } of AUDIO_MAGIC_BYTES) {\n if (bytes.length >= magic.length) {\n let matches = true;\n for (let i = 0; i < magic.length; i++) {\n if (bytes[i] !== magic[i]) {\n matches = false;\n break;\n }\n }\n if (matches) {\n // Special case: RIFF could be WAV or WebP, check for WAVE marker\n if (mimeType === \"audio/wav\") {\n // RIFF....WAVE - check bytes 8-11\n if (bytes.length >= 12) {\n const waveMarker =\n bytes[8] === 0x57 && bytes[9] === 0x41 && bytes[10] === 0x56 && bytes[11] === 0x45;\n if (!waveMarker) continue; // Not WAV, try next pattern\n }\n }\n return mimeType;\n }\n }\n }\n return null;\n}\n\n/**\n * Convert data to base64 string.\n *\n * @param data - Data to encode (Buffer, Uint8Array, or already base64 string)\n * @returns Base64-encoded string\n */\nexport function toBase64(data: Buffer | Uint8Array | string): string {\n if (typeof data === \"string\") {\n return data; // Assume already base64\n }\n return Buffer.from(data).toString(\"base64\");\n}\n\n/**\n * Create an image content part from a Buffer or Uint8Array.\n * Automatically detects the MIME type if not provided.\n *\n * @param buffer - Image data\n * @param mediaType - Optional MIME type (auto-detected if not provided)\n *\n * @example\n * ```typescript\n * const imageData = await fs.readFile(\"photo.jpg\");\n * const part = imageFromBuffer(imageData); // Auto-detects JPEG\n * ```\n */\nexport function imageFromBuffer(\n buffer: Buffer | Uint8Array,\n mediaType?: ImageMimeType,\n): ImageContentPart {\n const detectedType = mediaType ?? detectImageMimeType(buffer);\n if (!detectedType) {\n throw new Error(\n \"Could not detect image MIME type. Please provide the mediaType parameter explicitly.\",\n );\n }\n return {\n type: \"image\",\n source: {\n type: \"base64\",\n mediaType: detectedType,\n data: toBase64(buffer),\n },\n };\n}\n\n/**\n * Create an audio content part from base64-encoded data.\n *\n * @param data - Base64-encoded audio data\n * @param mediaType - MIME type of the audio\n *\n * @example\n * ```typescript\n * const part = audioFromBase64(base64Audio, \"audio/mp3\");\n * ```\n */\nexport function audioFromBase64(data: string, mediaType: AudioMimeType): AudioContentPart {\n return {\n type: \"audio\",\n source: { type: \"base64\", mediaType, data },\n };\n}\n\n/**\n * Create an audio content part from a Buffer or Uint8Array.\n * Automatically detects the MIME type if not provided.\n *\n * @param buffer - Audio data\n * @param mediaType - Optional MIME type (auto-detected if not provided)\n *\n * @example\n * ```typescript\n * const audioData = await fs.readFile(\"audio.mp3\");\n * const part = audioFromBuffer(audioData); // Auto-detects MP3\n * ```\n */\nexport function audioFromBuffer(\n buffer: Buffer | Uint8Array,\n mediaType?: AudioMimeType,\n): AudioContentPart {\n const detectedType = mediaType ?? detectAudioMimeType(buffer);\n if (!detectedType) {\n throw new Error(\n \"Could not detect audio MIME type. Please provide the mediaType parameter explicitly.\",\n );\n }\n return {\n type: \"audio\",\n source: {\n type: \"base64\",\n mediaType: detectedType,\n data: toBase64(buffer),\n },\n };\n}\n\n// ============================================================================\n// Data URL Utilities\n// ============================================================================\n\n/**\n * Check if a string is a data URL.\n *\n * @param input - String to check\n * @returns True if it's a data URL\n */\nexport function isDataUrl(input: string): boolean {\n return input.startsWith(\"data:\");\n}\n\n/**\n * Parse a data URL into its components.\n *\n * @param url - Data URL to parse\n * @returns Parsed components or null if invalid\n *\n * @example\n * ```typescript\n * const result = parseDataUrl(\"data:image/jpeg;base64,/9j/4AAQ...\");\n * // { mimeType: \"image/jpeg\", data: \"/9j/4AAQ...\" }\n * ```\n */\nexport function parseDataUrl(url: string): { mimeType: string; data: string } | null {\n const match = url.match(/^data:([^;]+);base64,(.+)$/);\n if (!match) return null;\n return { mimeType: match[1], data: match[2] };\n}\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 *\n * Updated: 2025-12-20\n */\nexport const MODEL_ALIASES: Record<string, string> = {\n // OpenAI aliases - GPT-5.2 is the latest flagship\n gpt4: \"openai:gpt-4o\",\n gpt4o: \"openai:gpt-4o\",\n \"gpt4o-mini\": \"openai:gpt-4o-mini\",\n gpt5: \"openai:gpt-5.2\", // Latest flagship\n \"gpt5.2\": \"openai:gpt-5.2\",\n \"gpt5.1\": \"openai:gpt-5.1\",\n \"gpt5-mini\": \"openai:gpt-5-mini\",\n \"gpt5-nano\": \"openai:gpt-5-nano\",\n \"gpt5-codex\": \"openai:gpt-5-codex\",\n o1: \"openai:o1\",\n o3: \"openai:o3\",\n \"o4-mini\": \"openai:o4-mini\",\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 - 2.5 Flash is the recommended fast model\n flash: \"gemini:gemini-2.5-flash\",\n \"gemini-flash\": \"gemini:gemini-2.5-flash\",\n \"flash-lite\": \"gemini:gemini-2.5-flash-lite\",\n \"gemini-pro\": \"gemini:gemini-3-pro-preview\",\n pro: \"gemini:gemini-3-pro-preview\",\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 { AbstractGadget } from \"./gadget.js\";\nimport { validateGadgetSchema } from \"./schema-validator.js\";\n\n// Type for gadget constructor\nexport type GadgetClass = new (...args: unknown[]) => AbstractGadget;\n\n// Type for gadget or gadget class\nexport type GadgetOrClass = AbstractGadget | GadgetClass;\n\nexport class GadgetRegistry {\n private readonly gadgets = new Map<string, AbstractGadget>();\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: AbstractGadget): 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: AbstractGadget): 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): AbstractGadget | 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(): AbstractGadget[] {\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 * First-class Execution Tree model for nested subagent support.\n *\n * The ExecutionTree is THE single source of truth for execution state.\n * All nodes (including nested subagent nodes) live in one tree.\n * Events are projections of tree changes.\n *\n * @module core/execution-tree\n */\n\nimport type { GadgetMediaOutput } from \"../gadgets/types.js\";\nimport type { LLMMessage } from \"./messages.js\";\nimport type { TokenUsage } from \"./options.js\";\n\n// =============================================================================\n// Node Identifiers\n// =============================================================================\n\n/**\n * Unique identifier for any execution node.\n * Format examples: \"llm_1\", \"gadget_abc123\", \"llm_1_2\" (nested)\n */\nexport type NodeId = string;\n\n/**\n * Node type discriminator.\n */\nexport type ExecutionNodeType = \"llm_call\" | \"gadget\";\n\n// =============================================================================\n// Execution Node Types\n// =============================================================================\n\n/**\n * Base properties shared by all execution nodes.\n */\ninterface BaseExecutionNode {\n /** Unique identifier for this node */\n id: NodeId;\n /** Node type discriminator */\n type: ExecutionNodeType;\n /** Parent node ID (null for root nodes) */\n parentId: NodeId | null;\n /** Nesting depth (0 = root, 1 = child of gadget, etc.) */\n depth: number;\n /** Path from root to this node: [\"llm_1\", \"gadget_abc\", \"llm_1_1\"] */\n path: NodeId[];\n /** Creation timestamp */\n createdAt: number;\n /** Completion timestamp (null if in progress) */\n completedAt: number | null;\n}\n\n/**\n * LLM call execution node.\n */\nexport interface LLMCallNode extends BaseExecutionNode {\n type: \"llm_call\";\n /** Iteration number within the agent loop (1-indexed for display) */\n iteration: number;\n /** Model identifier */\n model: string;\n /** Request messages (set when call starts) */\n request?: LLMMessage[];\n /** Accumulated response text */\n response: string;\n /** Token usage (set on completion) */\n usage?: TokenUsage;\n /** Finish reason from LLM */\n finishReason?: string | null;\n /** Cost in USD */\n cost?: number;\n /** Child node IDs (gadgets spawned by this LLM call) */\n children: NodeId[];\n}\n\n/**\n * Gadget execution state.\n */\nexport type GadgetState = \"pending\" | \"running\" | \"completed\" | \"failed\" | \"skipped\";\n\n/**\n * Gadget execution node.\n */\nexport interface GadgetNode extends BaseExecutionNode {\n type: \"gadget\";\n /** Invocation ID (LLM-generated or auto) */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Parameters passed to the gadget */\n parameters: Record<string, unknown>;\n /** Dependencies (other invocation IDs this gadget waits for) */\n dependencies: string[];\n /** Execution state */\n state: GadgetState;\n /** Result string (if completed successfully) */\n result?: string;\n /** Error message (if failed or skipped) */\n error?: string;\n /** Failed dependency invocation ID (if skipped due to dependency) */\n failedDependency?: string;\n /** Execution time in milliseconds */\n executionTimeMs?: number;\n /** Cost in USD */\n cost?: number;\n /** Media outputs from this gadget */\n media?: GadgetMediaOutput[];\n /** Child node IDs (nested LLM calls for subagent gadgets) */\n children: NodeId[];\n /** Whether this gadget is a subagent (has nested LLM calls) */\n isSubagent: boolean;\n}\n\n/**\n * Union of all execution node types.\n */\nexport type ExecutionNode = LLMCallNode | GadgetNode;\n\n// =============================================================================\n// Node Creation Parameters\n// =============================================================================\n\nexport interface AddLLMCallParams {\n /** Iteration number (1-indexed) */\n iteration: number;\n /** Model identifier */\n model: string;\n /** Request messages */\n request?: LLMMessage[];\n /** Parent node ID (for subagent LLM calls) */\n parentId?: NodeId | null;\n}\n\nexport interface AddGadgetParams {\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Parameters */\n parameters: Record<string, unknown>;\n /** Dependencies */\n dependencies?: string[];\n /** Parent LLM call node ID */\n parentId?: NodeId | null;\n}\n\nexport interface CompleteLLMCallParams {\n /** Accumulated response text */\n response?: string;\n /** Token usage */\n usage?: TokenUsage;\n /** Finish reason */\n finishReason?: string | null;\n /** Cost in USD */\n cost?: number;\n}\n\nexport interface CompleteGadgetParams {\n /** Result string */\n result?: string;\n /** Error message */\n error?: string;\n /** Failed dependency (for skipped gadgets) */\n failedDependency?: string;\n /** Execution time in ms */\n executionTimeMs?: number;\n /** Cost in USD */\n cost?: number;\n /** Media outputs */\n media?: GadgetMediaOutput[];\n}\n\n// =============================================================================\n// Event Types (imported from execution-events.ts)\n// =============================================================================\n\n// Forward declaration - actual types in execution-events.ts\nimport type { ExecutionEvent, ExecutionEventType } from \"./execution-events.js\";\n\nexport type { ExecutionEvent, ExecutionEventType };\n\n// =============================================================================\n// Event Listener Types\n// =============================================================================\n\n/** Event listener function type */\ntype EventListener = (event: ExecutionEvent) => void;\n\n// =============================================================================\n// ExecutionTree Class\n// =============================================================================\n\n/**\n * The Execution Tree - single source of truth for all execution state.\n *\n * Features:\n * - Stores all nodes (LLM calls, gadgets) in a hierarchical structure\n * - Emits events on mutations\n * - Provides query methods for aggregation (costs, media, descendants)\n * - Supports single shared tree model for nested subagents\n *\n * @example\n * ```typescript\n * const tree = new ExecutionTree();\n *\n * // Add root LLM call\n * const llmNode = tree.addLLMCall({ iteration: 1, model: \"sonnet\" });\n *\n * // Add gadget under the LLM call\n * const gadgetNode = tree.addGadget({\n * invocationId: \"gc_1\",\n * name: \"ReadFile\",\n * parameters: { path: \"/foo.txt\" },\n * parentId: llmNode.id,\n * });\n *\n * // Complete the gadget\n * tree.completeGadget(gadgetNode.id, { result: \"file contents\", executionTimeMs: 50 });\n *\n * // Query total cost\n * console.log(tree.getTotalCost());\n * ```\n */\nexport class ExecutionTree {\n private nodes = new Map<NodeId, ExecutionNode>();\n private rootIds: NodeId[] = [];\n private eventListeners = new Map<ExecutionEventType, Set<EventListener>>();\n private eventIdCounter = 0;\n private invocationIdToNodeId = new Map<string, NodeId>();\n\n // For async event streaming\n private eventQueue: ExecutionEvent[] = [];\n private eventWaiters: Array<(event: ExecutionEvent) => void> = [];\n private isCompleted = false;\n\n /**\n * Base depth for all nodes in this tree.\n * Used when this tree is a subagent's view into a parent tree.\n */\n public readonly baseDepth: number;\n\n /**\n * Parent node ID for subagent trees.\n * All root nodes in this tree will have this as their parentId.\n */\n public readonly parentNodeId: NodeId | null;\n\n constructor(options?: { baseDepth?: number; parentNodeId?: NodeId | null }) {\n this.baseDepth = options?.baseDepth ?? 0;\n this.parentNodeId = options?.parentNodeId ?? null;\n }\n\n // ===========================================================================\n // Node ID Generation\n // ===========================================================================\n\n private generateLLMCallId(iteration: number, parentId: NodeId | null): NodeId {\n if (parentId) {\n // Subagent LLM call: include parent info for uniqueness\n return `llm_${parentId}_${iteration}`;\n }\n return `llm_${iteration}`;\n }\n\n private gadgetIdCounter = 0;\n private generateGadgetId(invocationId: string): NodeId {\n return `gadget_${invocationId}_${++this.gadgetIdCounter}`;\n }\n\n // ===========================================================================\n // Event Emission\n // ===========================================================================\n\n private emit(event: ExecutionEvent): void {\n // Notify sync listeners\n const listeners = this.eventListeners.get(event.type);\n if (listeners) {\n for (const listener of listeners) {\n try {\n listener(event);\n } catch (error) {\n console.error(`Error in event listener for ${event.type}:`, error);\n }\n }\n }\n\n // Also emit to \"all\" listeners\n const allListeners = this.eventListeners.get(\"*\");\n if (allListeners) {\n for (const listener of allListeners) {\n try {\n listener(event);\n } catch (error) {\n console.error(\"Error in wildcard event listener:\", error);\n }\n }\n }\n\n // Push to async queue\n if (this.eventWaiters.length > 0) {\n const waiter = this.eventWaiters.shift();\n if (waiter) waiter(event);\n } else {\n this.eventQueue.push(event);\n }\n }\n\n private createBaseEventProps(node: ExecutionNode): {\n eventId: number;\n timestamp: number;\n nodeId: NodeId;\n parentId: NodeId | null;\n depth: number;\n path: NodeId[];\n } {\n return {\n eventId: ++this.eventIdCounter,\n timestamp: Date.now(),\n nodeId: node.id,\n parentId: node.parentId,\n depth: node.depth,\n path: node.path,\n };\n }\n\n // ===========================================================================\n // Node Creation\n // ===========================================================================\n\n /**\n * Add a new LLM call node to the tree.\n */\n addLLMCall(params: AddLLMCallParams): LLMCallNode {\n const parentId = params.parentId ?? this.parentNodeId;\n const parent = parentId ? this.nodes.get(parentId) : null;\n\n const depth = parent ? parent.depth + 1 : this.baseDepth;\n const path = parent ? [...parent.path] : [];\n\n const id = this.generateLLMCallId(params.iteration, parentId);\n path.push(id);\n\n const node: LLMCallNode = {\n id,\n type: \"llm_call\",\n parentId,\n depth,\n path,\n createdAt: Date.now(),\n completedAt: null,\n iteration: params.iteration,\n model: params.model,\n request: params.request,\n response: \"\",\n children: [],\n };\n\n this.nodes.set(id, node);\n\n if (!parentId) {\n this.rootIds.push(id);\n } else if (parent) {\n parent.children.push(id);\n }\n\n this.emit({\n type: \"llm_call_start\",\n ...this.createBaseEventProps(node),\n iteration: node.iteration,\n model: node.model,\n request: node.request,\n });\n\n return node;\n }\n\n /**\n * Add text to an LLM call's response (for streaming).\n */\n appendLLMResponse(nodeId: NodeId, chunk: string): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"llm_call\") {\n throw new Error(`LLM call node not found: ${nodeId}`);\n }\n\n (node as LLMCallNode).response += chunk;\n\n this.emit({\n type: \"llm_call_stream\",\n ...this.createBaseEventProps(node),\n chunk,\n });\n }\n\n /**\n * Complete an LLM call node.\n */\n completeLLMCall(nodeId: NodeId, params: CompleteLLMCallParams): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"llm_call\") {\n throw new Error(`LLM call node not found: ${nodeId}`);\n }\n\n const llmNode = node as LLMCallNode;\n llmNode.completedAt = Date.now();\n if (params.response !== undefined) llmNode.response = params.response;\n if (params.usage) llmNode.usage = params.usage;\n if (params.finishReason !== undefined) llmNode.finishReason = params.finishReason;\n if (params.cost !== undefined) llmNode.cost = params.cost;\n\n this.emit({\n type: \"llm_call_complete\",\n ...this.createBaseEventProps(node),\n response: llmNode.response,\n usage: llmNode.usage,\n finishReason: llmNode.finishReason,\n cost: llmNode.cost,\n });\n }\n\n /**\n * Mark an LLM call as failed.\n */\n failLLMCall(nodeId: NodeId, error: Error, recovered: boolean): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"llm_call\") {\n throw new Error(`LLM call node not found: ${nodeId}`);\n }\n\n const llmNode = node as LLMCallNode;\n llmNode.completedAt = Date.now();\n\n this.emit({\n type: \"llm_call_error\",\n ...this.createBaseEventProps(node),\n error,\n recovered,\n });\n }\n\n /**\n * Add a new gadget node to the tree.\n */\n addGadget(params: AddGadgetParams): GadgetNode {\n const parentId = params.parentId ?? this.getCurrentLLMCallId() ?? this.parentNodeId;\n const parent = parentId ? this.nodes.get(parentId) : null;\n\n const depth = parent ? parent.depth + 1 : this.baseDepth;\n const path = parent ? [...parent.path] : [];\n\n const id = this.generateGadgetId(params.invocationId);\n path.push(id);\n\n const node: GadgetNode = {\n id,\n type: \"gadget\",\n parentId,\n depth,\n path,\n createdAt: Date.now(),\n completedAt: null,\n invocationId: params.invocationId,\n name: params.name,\n parameters: params.parameters,\n dependencies: params.dependencies ?? [],\n state: \"pending\",\n children: [],\n isSubagent: false,\n };\n\n this.nodes.set(id, node);\n this.invocationIdToNodeId.set(params.invocationId, id);\n\n if (parent) {\n parent.children.push(id);\n }\n\n this.emit({\n type: \"gadget_call\",\n ...this.createBaseEventProps(node),\n invocationId: node.invocationId,\n name: node.name,\n parameters: node.parameters,\n dependencies: node.dependencies,\n });\n\n return node;\n }\n\n /**\n * Mark a gadget as started (running).\n */\n startGadget(nodeId: NodeId): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"gadget\") {\n throw new Error(`Gadget node not found: ${nodeId}`);\n }\n\n const gadgetNode = node as GadgetNode;\n gadgetNode.state = \"running\";\n\n this.emit({\n type: \"gadget_start\",\n ...this.createBaseEventProps(node),\n invocationId: gadgetNode.invocationId,\n name: gadgetNode.name,\n });\n }\n\n /**\n * Complete a gadget node successfully.\n */\n completeGadget(nodeId: NodeId, params: CompleteGadgetParams): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"gadget\") {\n throw new Error(`Gadget node not found: ${nodeId}`);\n }\n\n const gadgetNode = node as GadgetNode;\n gadgetNode.completedAt = Date.now();\n gadgetNode.state = params.error ? \"failed\" : \"completed\";\n if (params.result !== undefined) gadgetNode.result = params.result;\n if (params.error) gadgetNode.error = params.error;\n if (params.executionTimeMs !== undefined) gadgetNode.executionTimeMs = params.executionTimeMs;\n if (params.cost !== undefined) gadgetNode.cost = params.cost;\n if (params.media) gadgetNode.media = params.media;\n\n // Mark as subagent if it has child LLM calls\n gadgetNode.isSubagent = gadgetNode.children.some((childId) => {\n const child = this.nodes.get(childId);\n return child?.type === \"llm_call\";\n });\n\n if (params.error) {\n this.emit({\n type: \"gadget_error\",\n ...this.createBaseEventProps(node),\n invocationId: gadgetNode.invocationId,\n name: gadgetNode.name,\n error: params.error,\n executionTimeMs: params.executionTimeMs ?? 0,\n });\n } else {\n this.emit({\n type: \"gadget_complete\",\n ...this.createBaseEventProps(node),\n invocationId: gadgetNode.invocationId,\n name: gadgetNode.name,\n result: params.result ?? \"\",\n executionTimeMs: params.executionTimeMs ?? 0,\n cost: params.cost,\n media: params.media,\n });\n }\n }\n\n /**\n * Mark a gadget as skipped due to dependency failure.\n */\n skipGadget(\n nodeId: NodeId,\n failedDependency: string,\n failedDependencyError: string,\n reason: \"dependency_failed\" | \"controller_skip\",\n ): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"gadget\") {\n throw new Error(`Gadget node not found: ${nodeId}`);\n }\n\n const gadgetNode = node as GadgetNode;\n gadgetNode.completedAt = Date.now();\n gadgetNode.state = \"skipped\";\n gadgetNode.failedDependency = failedDependency;\n gadgetNode.error = failedDependencyError;\n\n // Build error message combining reason and dependency error\n const error =\n reason === \"controller_skip\"\n ? \"Skipped by controller\"\n : `Dependency ${failedDependency} failed: ${failedDependencyError}`;\n\n this.emit({\n type: \"gadget_skipped\",\n ...this.createBaseEventProps(node),\n invocationId: gadgetNode.invocationId,\n name: gadgetNode.name,\n reason,\n error,\n failedDependency,\n failedDependencyError,\n });\n }\n\n // ===========================================================================\n // Text Events (pure notifications, not tree nodes)\n // ===========================================================================\n\n /**\n * Emit a text event (notification only, not stored in tree).\n */\n emitText(content: string, llmCallNodeId: NodeId): void {\n const node = this.nodes.get(llmCallNodeId);\n if (!node) {\n throw new Error(`Node not found: ${llmCallNodeId}`);\n }\n\n this.emit({\n type: \"text\",\n ...this.createBaseEventProps(node),\n content,\n });\n }\n\n // ===========================================================================\n // Query Methods\n // ===========================================================================\n\n /**\n * Get a node by ID.\n */\n getNode(id: NodeId): ExecutionNode | undefined {\n return this.nodes.get(id);\n }\n\n /**\n * Get a gadget node by invocation ID.\n */\n getNodeByInvocationId(invocationId: string): GadgetNode | undefined {\n const nodeId = this.invocationIdToNodeId.get(invocationId);\n if (!nodeId) return undefined;\n const node = this.nodes.get(nodeId);\n return node?.type === \"gadget\" ? (node as GadgetNode) : undefined;\n }\n\n /**\n * Get all root nodes (depth 0 for this tree).\n */\n getRoots(): ExecutionNode[] {\n return this.rootIds\n .map((id) => this.nodes.get(id))\n .filter((node): node is ExecutionNode => node !== undefined);\n }\n\n /**\n * Get children of a node.\n */\n getChildren(id: NodeId): ExecutionNode[] {\n const node = this.nodes.get(id);\n if (!node) return [];\n return node.children\n .map((childId) => this.nodes.get(childId))\n .filter((child): child is ExecutionNode => child !== undefined);\n }\n\n /**\n * Get ancestors of a node (from root to parent).\n */\n getAncestors(id: NodeId): ExecutionNode[] {\n const node = this.nodes.get(id);\n if (!node) return [];\n\n const ancestors: ExecutionNode[] = [];\n let currentId = node.parentId;\n while (currentId) {\n const ancestor = this.nodes.get(currentId);\n if (ancestor) {\n ancestors.unshift(ancestor);\n currentId = ancestor.parentId;\n } else {\n break;\n }\n }\n return ancestors;\n }\n\n /**\n * Get all descendants of a node.\n */\n getDescendants(id: NodeId, type?: ExecutionNodeType): ExecutionNode[] {\n const node = this.nodes.get(id);\n if (!node) return [];\n\n const descendants: ExecutionNode[] = [];\n const stack = [...node.children];\n\n while (stack.length > 0) {\n const childId = stack.pop()!;\n const child = this.nodes.get(childId);\n if (child) {\n if (!type || child.type === type) {\n descendants.push(child);\n }\n stack.push(...child.children);\n }\n }\n\n return descendants;\n }\n\n /**\n * Get the current (most recent incomplete) LLM call node.\n */\n getCurrentLLMCallId(): NodeId | undefined {\n // Find the most recent root LLM call that's not complete\n for (let i = this.rootIds.length - 1; i >= 0; i--) {\n const node = this.nodes.get(this.rootIds[i]);\n if (node?.type === \"llm_call\" && !node.completedAt) {\n return node.id;\n }\n }\n return undefined;\n }\n\n // ===========================================================================\n // Aggregation Methods (for subagent support)\n // ===========================================================================\n\n /**\n * Get total cost for entire tree.\n */\n getTotalCost(): number {\n let total = 0;\n for (const node of this.nodes.values()) {\n if (node.type === \"llm_call\" && (node as LLMCallNode).cost) {\n total += (node as LLMCallNode).cost!;\n } else if (node.type === \"gadget\" && (node as GadgetNode).cost) {\n total += (node as GadgetNode).cost!;\n }\n }\n return total;\n }\n\n /**\n * Get total cost for a subtree (node and all descendants).\n */\n getSubtreeCost(nodeId: NodeId): number {\n const node = this.nodes.get(nodeId);\n if (!node) return 0;\n\n let total = 0;\n\n // Add node's own cost\n if (node.type === \"llm_call\" && (node as LLMCallNode).cost) {\n total += (node as LLMCallNode).cost!;\n } else if (node.type === \"gadget\" && (node as GadgetNode).cost) {\n total += (node as GadgetNode).cost!;\n }\n\n // Add descendants' costs\n for (const descendant of this.getDescendants(nodeId)) {\n if (descendant.type === \"llm_call\" && (descendant as LLMCallNode).cost) {\n total += (descendant as LLMCallNode).cost!;\n } else if (descendant.type === \"gadget\" && (descendant as GadgetNode).cost) {\n total += (descendant as GadgetNode).cost!;\n }\n }\n\n return total;\n }\n\n /**\n * Get token usage for entire tree.\n */\n getTotalTokens(): { input: number; output: number; cached: number } {\n let input = 0;\n let output = 0;\n let cached = 0;\n\n for (const node of this.nodes.values()) {\n if (node.type === \"llm_call\") {\n const llmNode = node as LLMCallNode;\n if (llmNode.usage) {\n input += llmNode.usage.inputTokens;\n output += llmNode.usage.outputTokens;\n cached += llmNode.usage.cachedInputTokens ?? 0;\n }\n }\n }\n\n return { input, output, cached };\n }\n\n /**\n * Get token usage for a subtree.\n */\n getSubtreeTokens(nodeId: NodeId): { input: number; output: number; cached: number } {\n const node = this.nodes.get(nodeId);\n if (!node) return { input: 0, output: 0, cached: 0 };\n\n let input = 0;\n let output = 0;\n let cached = 0;\n\n const nodesToProcess = [node, ...this.getDescendants(nodeId)];\n\n for (const n of nodesToProcess) {\n if (n.type === \"llm_call\") {\n const llmNode = n as LLMCallNode;\n if (llmNode.usage) {\n input += llmNode.usage.inputTokens;\n output += llmNode.usage.outputTokens;\n cached += llmNode.usage.cachedInputTokens ?? 0;\n }\n }\n }\n\n return { input, output, cached };\n }\n\n /**\n * Collect all media from a subtree.\n */\n getSubtreeMedia(nodeId: NodeId): GadgetMediaOutput[] {\n const node = this.nodes.get(nodeId);\n if (!node) return [];\n\n const media: GadgetMediaOutput[] = [];\n const nodesToProcess: ExecutionNode[] = node.type === \"gadget\" ? [node] : [];\n nodesToProcess.push(...this.getDescendants(nodeId, \"gadget\"));\n\n for (const n of nodesToProcess) {\n if (n.type === \"gadget\") {\n const gadgetNode = n as GadgetNode;\n if (gadgetNode.media) {\n media.push(...gadgetNode.media);\n }\n }\n }\n\n return media;\n }\n\n /**\n * Check if a subtree is complete (all nodes finished).\n */\n isSubtreeComplete(nodeId: NodeId): boolean {\n const node = this.nodes.get(nodeId);\n if (!node) return true;\n if (!node.completedAt) return false;\n\n for (const descendant of this.getDescendants(nodeId)) {\n if (!descendant.completedAt) return false;\n }\n\n return true;\n }\n\n /**\n * Get node counts.\n */\n getNodeCount(): { llmCalls: number; gadgets: number } {\n let llmCalls = 0;\n let gadgets = 0;\n\n for (const node of this.nodes.values()) {\n if (node.type === \"llm_call\") llmCalls++;\n else if (node.type === \"gadget\") gadgets++;\n }\n\n return { llmCalls, gadgets };\n }\n\n // ===========================================================================\n // Event Subscription\n // ===========================================================================\n\n /**\n * Subscribe to events of a specific type.\n * Returns unsubscribe function.\n *\n * @param type - Event type to subscribe to (use \"*\" for all events)\n * @param listener - Callback function that receives matching events\n * @returns Unsubscribe function\n *\n * @example\n * ```typescript\n * const unsubscribe = tree.on(\"gadget_complete\", (event) => {\n * if (event.type === \"gadget_complete\") {\n * console.log(`Gadget ${event.name} completed`);\n * }\n * });\n * ```\n */\n on(type: ExecutionEventType, listener: EventListener): () => void {\n if (!this.eventListeners.has(type)) {\n this.eventListeners.set(type, new Set());\n }\n const listeners = this.eventListeners.get(type)!;\n listeners.add(listener);\n\n return () => {\n listeners.delete(listener);\n };\n }\n\n /**\n * Subscribe to all events.\n */\n onAll(listener: EventListener): () => void {\n return this.on(\"*\", listener);\n }\n\n /**\n * Get async iterable of all events.\n * Events are yielded as they occur.\n */\n async *events(): AsyncGenerator<ExecutionEvent> {\n while (!this.isCompleted) {\n // Drain queue first\n while (this.eventQueue.length > 0) {\n yield this.eventQueue.shift()!;\n }\n\n if (this.isCompleted) break;\n\n // Wait for next event\n const event = await new Promise<ExecutionEvent>((resolve) => {\n // Check queue again in case events arrived while setting up\n if (this.eventQueue.length > 0) {\n resolve(this.eventQueue.shift()!);\n } else {\n this.eventWaiters.push(resolve);\n }\n });\n\n yield event;\n }\n\n // Drain remaining events\n while (this.eventQueue.length > 0) {\n yield this.eventQueue.shift()!;\n }\n }\n\n /**\n * Mark the tree as complete (no more events will be emitted).\n */\n complete(): void {\n this.isCompleted = true;\n // Wake up any waiters with a dummy event that signals completion\n for (const waiter of this.eventWaiters) {\n // Push a completion marker so waiters can exit\n }\n this.eventWaiters = [];\n }\n\n /**\n * Check if the tree is complete.\n */\n isComplete(): boolean {\n return this.isCompleted;\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: PromptTemplateConfig = {\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 PromptTemplateConfig {\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: \"Tip: You can call multiple gadgets in a single response for efficiency.\",\n\n iterationProgressHint: \"[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<\n PromptTemplateConfig,\n \"rules\" | \"customExamples\" | \"parallelGadgetsHint\" | \"iterationProgressHint\"\n > & {\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 \"Gadgets without dependencies execute immediately (in parallel if multiple)\",\n \"Use :invocation_id:dep1,dep2 syntax when a gadget needs results from prior gadgets\",\n \"If any dependency fails, dependent gadgets are automatically skipped\",\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: PromptTemplateConfig[\"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 { AbstractGadget } from \"../gadgets/gadget.js\";\nimport type { GadgetMediaOutput } from \"../gadgets/types.js\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"./constants.js\";\nimport type {\n AudioMimeType,\n ContentPart,\n ImageMimeType,\n TextContentPart,\n} from \"./input-content.js\";\nimport {\n audioFromBase64,\n audioFromBuffer,\n detectImageMimeType,\n imageFromBase64,\n imageFromBuffer,\n imageFromUrl,\n text,\n toBase64,\n} from \"./input-content.js\";\nimport type { PromptTemplateConfig } from \"./prompt-config.js\";\nimport { DEFAULT_PROMPTS, resolvePromptTemplate, resolveRulesTemplate } from \"./prompt-config.js\";\n\nexport type MessageRole = \"system\" | \"user\" | \"assistant\";\n\n/**\n * Message content can be a simple string (text only) or an array of content parts (multimodal).\n * Using a string is simpler for text-only messages, while arrays support images and audio.\n */\nexport type MessageContent = string | ContentPart[];\n\nexport interface LLMMessage {\n role: MessageRole;\n content: MessageContent;\n name?: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Normalize message content to an array of content parts.\n * Converts string content to a single text part.\n *\n * @param content - Message content (string or ContentPart[])\n * @returns Array of content parts\n */\nexport function normalizeMessageContent(content: MessageContent): ContentPart[] {\n if (typeof content === \"string\") {\n return [{ type: \"text\", text: content }];\n }\n return content;\n}\n\n/**\n * Extract text from message content.\n * Concatenates all text parts in the content.\n *\n * @param content - Message content (string or ContentPart[])\n * @returns Combined text from all text parts\n */\nexport function extractMessageText(content: MessageContent): string {\n if (typeof content === \"string\") {\n return content;\n }\n return content\n .filter((part): part is TextContentPart => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\");\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: PromptTemplateConfig;\n\n constructor(promptConfig?: PromptTemplateConfig) {\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: AbstractGadget[],\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: AbstractGadget[]): 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({\n argPrefix: this.argPrefix,\n startPrefix: this.startPrefix,\n endPrefix: this.endPrefix,\n });\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 With ID: ${this.startPrefix}gadget_name:my_id`);\n parts.push(`\\n With dependencies: ${this.startPrefix}gadget_name:my_id:dep1,dep2`);\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 // Dependency example\n const dependencyExample = `${this.startPrefix}fetch_data:fetch_1\n${this.argPrefix}url\nhttps://api.example.com/users\n${this.endPrefix}\n${this.startPrefix}fetch_data:fetch_2\n${this.argPrefix}url\nhttps://api.example.com/orders\n${this.endPrefix}\n${this.startPrefix}merge_data:merge_1:fetch_1,fetch_2\n${this.argPrefix}format\njson\n${this.endPrefix}`;\n\n parts.push(`\\n\\nEXAMPLE (With Dependencies):\nmerge_1 waits for fetch_1 AND fetch_2 to complete.\nIf either fails, merge_1 is automatically skipped.\n\n${dependencyExample}`);\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 /**\n * Add a user message.\n * Content can be a string (text only) or an array of content parts (multimodal).\n *\n * @param content - Message content\n * @param metadata - Optional metadata\n *\n * @example\n * ```typescript\n * // Text only\n * builder.addUser(\"Hello!\");\n *\n * // Multimodal\n * builder.addUser([\n * text(\"What's in this image?\"),\n * imageFromBuffer(imageData),\n * ]);\n * ```\n */\n addUser(content: MessageContent, 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 /**\n * Add a user message with an image attachment.\n *\n * @param textContent - Text prompt\n * @param imageData - Image data (Buffer, Uint8Array, or base64 string)\n * @param mimeType - Optional MIME type (auto-detected if not provided)\n *\n * @example\n * ```typescript\n * builder.addUserWithImage(\n * \"What's in this image?\",\n * await fs.readFile(\"photo.jpg\"),\n * \"image/jpeg\" // Optional - auto-detected\n * );\n * ```\n */\n addUserWithImage(\n textContent: string,\n imageData: Buffer | Uint8Array | string,\n mimeType?: ImageMimeType,\n ): this {\n const imageBuffer =\n typeof imageData === \"string\" ? Buffer.from(imageData, \"base64\") : imageData;\n const detectedMime = mimeType ?? detectImageMimeType(imageBuffer);\n\n if (!detectedMime) {\n throw new Error(\n \"Could not detect image MIME type. Please provide the mimeType parameter explicitly.\",\n );\n }\n\n const content: ContentPart[] = [\n text(textContent),\n {\n type: \"image\",\n source: {\n type: \"base64\",\n mediaType: detectedMime,\n data: toBase64(imageBuffer),\n },\n },\n ];\n\n this.messages.push({ role: \"user\", content });\n return this;\n }\n\n /**\n * Add a user message with an image URL (OpenAI only).\n *\n * @param textContent - Text prompt\n * @param imageUrl - URL to the image\n *\n * @example\n * ```typescript\n * builder.addUserWithImageUrl(\n * \"What's in this image?\",\n * \"https://example.com/image.jpg\"\n * );\n * ```\n */\n addUserWithImageUrl(textContent: string, imageUrl: string): this {\n const content: ContentPart[] = [text(textContent), imageFromUrl(imageUrl)];\n this.messages.push({ role: \"user\", content });\n return this;\n }\n\n /**\n * Add a user message with an audio attachment (Gemini only).\n *\n * @param textContent - Text prompt\n * @param audioData - Audio data (Buffer, Uint8Array, or base64 string)\n * @param mimeType - Optional MIME type (auto-detected if not provided)\n *\n * @example\n * ```typescript\n * builder.addUserWithAudio(\n * \"Transcribe this audio\",\n * await fs.readFile(\"recording.mp3\"),\n * \"audio/mp3\" // Optional - auto-detected\n * );\n * ```\n */\n addUserWithAudio(\n textContent: string,\n audioData: Buffer | Uint8Array | string,\n mimeType?: AudioMimeType,\n ): this {\n const audioBuffer =\n typeof audioData === \"string\" ? Buffer.from(audioData, \"base64\") : audioData;\n\n const content: ContentPart[] = [text(textContent), audioFromBuffer(audioBuffer, mimeType)];\n this.messages.push({ role: \"user\", content });\n return this;\n }\n\n /**\n * Add a user message with multiple content parts.\n * Provides full flexibility for complex multimodal messages.\n *\n * @param parts - Array of content parts\n *\n * @example\n * ```typescript\n * builder.addUserMultimodal([\n * text(\"Compare these images:\"),\n * imageFromBuffer(image1),\n * imageFromBuffer(image2),\n * ]);\n * ```\n */\n addUserMultimodal(parts: ContentPart[]): this {\n this.messages.push({ role: \"user\", content: parts });\n return this;\n }\n\n /**\n * Record a gadget execution result in the message history.\n * Creates an assistant message with the gadget invocation and a user message with the result.\n *\n * The invocationId is shown to the LLM so it can reference previous calls when building dependencies.\n *\n * @param gadget - Name of the gadget that was executed\n * @param parameters - Parameters that were passed to the gadget\n * @param result - Text result from the gadget execution\n * @param invocationId - Invocation ID (shown to LLM so it can reference for dependencies)\n * @param media - Optional media outputs from the gadget\n * @param mediaIds - Optional IDs for the media outputs\n */\n addGadgetCallResult(\n gadget: string,\n parameters: Record<string, unknown>,\n result: string,\n invocationId: string,\n media?: GadgetMediaOutput[],\n mediaIds?: string[],\n ) {\n const paramStr = this.formatBlockParameters(parameters, \"\");\n\n // Assistant message with gadget markers and invocation ID\n this.messages.push({\n role: \"assistant\",\n content: `${this.startPrefix}${gadget}:${invocationId}\\n${paramStr}\\n${this.endPrefix}`,\n });\n\n // User message with result, including invocation ID so LLM can reference it\n if (media && media.length > 0 && mediaIds && mediaIds.length > 0) {\n // Build text with ID references (include kind for clarity)\n const idRefs = media.map((m, i) => `[Media: ${mediaIds[i]} (${m.kind})]`).join(\"\\n\");\n const textWithIds = `Result (${invocationId}): ${result}\\n${idRefs}`;\n\n // Build multimodal content: text + media content parts\n const parts: ContentPart[] = [text(textWithIds)];\n for (const item of media) {\n // Convert based on media kind\n if (item.kind === \"image\") {\n parts.push(imageFromBase64(item.data, item.mimeType as ImageMimeType));\n } else if (item.kind === \"audio\") {\n parts.push(audioFromBase64(item.data, item.mimeType as AudioMimeType));\n }\n // Note: video and file types are stored but not included in LLM context\n // as most providers don't support them yet\n }\n this.messages.push({ role: \"user\", content: parts });\n } else {\n // Simple text result\n this.messages.push({\n role: \"user\",\n content: `Result (${invocationId}): ${result}`,\n });\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(params: Record<string, unknown>, prefix: string): 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 const validRole =\n message.role === \"system\" || message.role === \"user\" || message.role === \"assistant\";\n const validContent = typeof message.content === \"string\" || Array.isArray(message.content);\n\n return validRole && validContent;\n};\n","/**\n * MediaStore: Session-scoped storage for gadget media outputs.\n *\n * This module provides an abstraction layer between gadgets and the filesystem.\n * Instead of exposing raw file paths, it assigns unique IDs to stored media\n * that can be shared with the LLM and user.\n *\n * @example\n * ```typescript\n * const store = new MediaStore();\n *\n * // Store an image, get back ID\n * const stored = await store.store({\n * kind: \"image\",\n * data: base64EncodedPng,\n * mimeType: \"image/png\",\n * description: \"Screenshot\"\n * }, \"Screenshot\");\n *\n * console.log(stored.id); // \"media_a1b2c3\"\n * console.log(stored.path); // \"/tmp/llmist-media-xxx/Screenshot_001.png\"\n *\n * // Later: retrieve by ID\n * const retrieved = store.get(\"media_a1b2c3\");\n * ```\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { GadgetMediaOutput, MediaKind, StoredMedia } from \"./types.js\";\n\n// Re-export StoredMedia for convenience\nexport type { StoredMedia };\n\n/**\n * Get the llmist temp directory path.\n * Uses ~/.llmist/tmp for user-scoped storage.\n */\nfunction getLlmistTmpDir(): string {\n return join(homedir(), \".llmist\", \"tmp\");\n}\n\n/**\n * Common MIME type to file extension mapping.\n */\nconst MIME_TO_EXTENSION: Record<string, string> = {\n // Images\n \"image/png\": \".png\",\n \"image/jpeg\": \".jpg\",\n \"image/gif\": \".gif\",\n \"image/webp\": \".webp\",\n \"image/svg+xml\": \".svg\",\n \"image/bmp\": \".bmp\",\n \"image/tiff\": \".tiff\",\n // Audio\n \"audio/mp3\": \".mp3\",\n \"audio/mpeg\": \".mp3\",\n \"audio/wav\": \".wav\",\n \"audio/webm\": \".webm\",\n \"audio/ogg\": \".ogg\",\n \"audio/flac\": \".flac\",\n \"audio/aac\": \".aac\",\n // Video\n \"video/mp4\": \".mp4\",\n \"video/webm\": \".webm\",\n \"video/ogg\": \".ogv\",\n \"video/quicktime\": \".mov\",\n \"video/x-msvideo\": \".avi\",\n // Documents\n \"application/pdf\": \".pdf\",\n \"application/json\": \".json\",\n \"text/plain\": \".txt\",\n \"text/html\": \".html\",\n \"text/css\": \".css\",\n \"text/javascript\": \".js\",\n};\n\n/**\n * Session-scoped media storage with ID abstraction.\n *\n * Each MediaStore instance manages media for a single agent session.\n * Media files are stored in a temporary directory and referenced by\n * short, unique IDs rather than file paths.\n */\nexport class MediaStore {\n private readonly items = new Map<string, StoredMedia>();\n private readonly outputDir: string;\n private counter = 0;\n private initialized = false;\n\n /**\n * Create a new MediaStore.\n *\n * @param sessionId - Optional session ID for the output directory.\n * If not provided, a random ID is generated.\n */\n constructor(sessionId?: string) {\n const id = sessionId ?? randomBytes(8).toString(\"hex\");\n this.outputDir = join(getLlmistTmpDir(), `media-${id}`);\n }\n\n /**\n * Get the output directory path.\n */\n getOutputDir(): string {\n return this.outputDir;\n }\n\n /**\n * Ensure the output directory exists.\n * @throws Error if directory creation fails\n */\n private async ensureDir(): Promise<void> {\n if (this.initialized) return;\n\n try {\n await mkdir(this.outputDir, { recursive: true });\n this.initialized = true;\n } catch (error) {\n throw new Error(\n `MediaStore: Failed to create directory ${this.outputDir}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Generate a unique media ID.\n * Format: \"media_\" + 6 random alphanumeric characters\n */\n private generateId(): string {\n const chars = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n let id = \"media_\";\n const bytes = randomBytes(6);\n for (let i = 0; i < 6; i++) {\n id += chars[bytes[i] % chars.length];\n }\n return id;\n }\n\n /**\n * Get file extension from MIME type.\n */\n private getExtension(mimeType: string): string {\n return MIME_TO_EXTENSION[mimeType] ?? \".bin\";\n }\n\n /**\n * Store media and return stored metadata with ID.\n *\n * @param media - The media output from a gadget\n * @param gadgetName - Name of the gadget that created this media\n * @returns Stored media information including generated ID\n * @throws Error if file write fails\n */\n async store(media: GadgetMediaOutput, gadgetName: string): Promise<StoredMedia> {\n await this.ensureDir();\n\n const id = this.generateId();\n const ext = this.getExtension(media.mimeType);\n // Use provided fileName or generate one\n const filename =\n media.fileName ?? `${gadgetName}_${String(++this.counter).padStart(3, \"0\")}${ext}`;\n const filePath = join(this.outputDir, filename);\n\n // Decode base64 and write to file\n const buffer = Buffer.from(media.data, \"base64\");\n\n try {\n await writeFile(filePath, buffer);\n } catch (error) {\n throw new Error(\n `MediaStore: Failed to write media file ${filePath}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n const stored: StoredMedia = {\n id,\n kind: media.kind,\n path: filePath,\n mimeType: media.mimeType,\n sizeBytes: buffer.length,\n description: media.description,\n metadata: media.metadata,\n gadgetName,\n createdAt: new Date(),\n };\n\n this.items.set(id, stored);\n return stored;\n }\n\n /**\n * Get stored media by ID.\n *\n * @param id - The media ID (e.g., \"media_a1b2c3\")\n * @returns The stored media or undefined if not found\n */\n get(id: string): StoredMedia | undefined {\n return this.items.get(id);\n }\n\n /**\n * Get the actual file path for a media ID.\n * Convenience method for gadgets that need the raw path.\n *\n * @param id - The media ID\n * @returns The file path or undefined if not found\n */\n getPath(id: string): string | undefined {\n return this.items.get(id)?.path;\n }\n\n /**\n * List all stored media, optionally filtered by kind.\n *\n * @param kind - Optional media kind to filter by\n * @returns Array of stored media items\n */\n list(kind?: MediaKind): StoredMedia[] {\n const all = Array.from(this.items.values());\n if (kind) {\n return all.filter((item) => item.kind === kind);\n }\n return all;\n }\n\n /**\n * Get the count of stored media items.\n */\n get size(): number {\n return this.items.size;\n }\n\n /**\n * Check if a media ID exists.\n */\n has(id: string): boolean {\n return this.items.has(id);\n }\n\n /**\n * Clear in-memory store without deleting files.\n * Resets the counter but leaves files on disk.\n */\n clear(): void {\n this.items.clear();\n this.counter = 0;\n }\n\n /**\n * Delete all stored files and clear memory.\n * Removes the entire session directory.\n */\n async cleanup(): Promise<void> {\n if (this.initialized) {\n try {\n await rm(this.outputDir, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors (directory may already be deleted)\n }\n this.initialized = false;\n }\n this.clear();\n }\n}\n","/**\n * Signal that a gadget throws to indicate task completion and agent termination.\n *\n * When a gadget throws this signal, the agent loop will:\n * 1. Complete the current iteration\n * 2. Return the signal 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 TaskCompletionSignal(message);\n * }\n * }\n * ```\n */\nexport class TaskCompletionSignal extends Error {\n constructor(message?: string) {\n super(message ?? \"Agent loop terminated by gadget\");\n this.name = \"TaskCompletionSignal\";\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 `requestHumanInput` 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 HumanInputRequiredException(params.question);\n * }\n * }\n * ```\n */\nexport class HumanInputRequiredException extends Error {\n public readonly question: string;\n\n constructor(question: string) {\n super(`Human input required: ${question}`);\n this.name = \"HumanInputRequiredException\";\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\n/**\n * Exception thrown when gadget execution is aborted.\n *\n * Gadgets can throw this exception when they detect the abort signal has been\n * triggered. This is typically used via the `throwIfAborted()` helper method\n * on the Gadget base class.\n *\n * @example\n * ```typescript\n * class LongRunningGadget extends Gadget({\n * name: 'LongRunning',\n * description: 'Performs a long operation with checkpoints',\n * schema: z.object({ data: z.string() }),\n * }) {\n * async execute(params: this['params'], ctx: ExecutionContext): Promise<string> {\n * // Check at key points - throws AbortException if aborted\n * this.throwIfAborted(ctx);\n *\n * await this.doPartOne(params.data);\n *\n * this.throwIfAborted(ctx);\n *\n * await this.doPartTwo(params.data);\n *\n * return 'completed';\n * }\n * }\n * ```\n */\nexport class AbortException extends Error {\n constructor(message?: string) {\n super(message || \"Gadget execution was aborted\");\n this.name = \"AbortException\";\n }\n}\n\n","import { createWriteStream, mkdirSync, type WriteStream } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { type ILogObj, Logger } from \"tslog\";\n\nconst LEVEL_NAME_TO_ID: Record<string, number> = {\n silly: 0,\n trace: 1,\n debug: 2,\n info: 3,\n warn: 4,\n error: 5,\n fatal: 6,\n};\n\nfunction parseLogLevel(value?: string): number | undefined {\n if (!value) {\n return undefined;\n }\n\n const normalized = value.trim().toLowerCase();\n\n if (normalized === \"\") {\n return undefined;\n }\n\n const numericLevel = Number(normalized);\n if (Number.isFinite(numericLevel)) {\n return Math.max(0, Math.min(6, Math.floor(numericLevel)));\n }\n\n return LEVEL_NAME_TO_ID[normalized];\n}\n\n/**\n * Logger configuration options for the library.\n */\nexport interface LoggerOptions {\n /**\n * Log level: 0=silly, 1=trace, 2=debug, 3=info, 4=warn, 5=error, 6=fatal\n * @default 4 (warn)\n */\n minLevel?: number;\n\n /**\n * Output type: 'pretty' for development, 'json' for production\n * @default 'pretty'\n */\n type?: \"pretty\" | \"json\" | \"hidden\";\n\n /**\n * Logger name (appears in logs)\n */\n name?: string;\n\n /**\n * When true, reset (truncate) the log file instead of appending.\n * Useful for getting clean logs per session.\n * @default false\n */\n logReset?: boolean;\n}\n\n/**\n * Parses a boolean environment variable.\n */\nfunction parseEnvBoolean(value?: string): boolean | undefined {\n if (!value) return undefined;\n const normalized = value.trim().toLowerCase();\n if (normalized === \"true\" || normalized === \"1\") return true;\n if (normalized === \"false\" || normalized === \"0\") return false;\n return undefined;\n}\n\n// Singleton state for file logging - ensures all loggers share one WriteStream\nlet sharedLogFilePath: string | undefined;\nlet sharedLogFileStream: WriteStream | undefined;\nlet logFileInitialized = false;\nlet writeErrorCount = 0;\nlet writeErrorReported = false;\nconst MAX_WRITE_ERRORS_BEFORE_DISABLE = 5;\n\n// Standard log line template for both console and file output\nconst LOG_TEMPLATE =\n \"{{yyyy}}-{{mm}}-{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}}\\t{{logLevelName}}\\t[{{name}}]\\t\";\n\n/**\n * Strips ANSI color codes from a string.\n */\nexport function stripAnsi(str: string): string {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape codes use control characters\n return str.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n}\n\n/**\n * Resets the shared file logging state. Used for testing.\n * @internal\n */\nexport function _resetFileLoggingState(): void {\n if (sharedLogFileStream) {\n sharedLogFileStream.end();\n sharedLogFileStream = undefined;\n }\n sharedLogFilePath = undefined;\n logFileInitialized = false;\n writeErrorCount = 0;\n writeErrorReported = false;\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 // Initialize log file and WriteStream (only once per path)\n if (envLogFile && (!logFileInitialized || sharedLogFilePath !== envLogFile)) {\n try {\n // Close previous stream if path changed\n if (sharedLogFileStream) {\n sharedLogFileStream.end();\n sharedLogFileStream = undefined;\n }\n\n mkdirSync(dirname(envLogFile), { recursive: true });\n\n // Use \"w\" (write/truncate) when logReset is true, \"a\" (append) otherwise\n const flags = logReset ? \"w\" : \"a\";\n sharedLogFileStream = createWriteStream(envLogFile, { flags });\n sharedLogFilePath = envLogFile;\n logFileInitialized = true;\n writeErrorCount = 0;\n writeErrorReported = false;\n\n // Handle stream errors\n sharedLogFileStream.on(\"error\", (error) => {\n writeErrorCount++;\n if (!writeErrorReported) {\n console.error(`[llmist] Log file write error: ${error.message}`);\n writeErrorReported = true;\n }\n if (writeErrorCount >= MAX_WRITE_ERRORS_BEFORE_DISABLE) {\n console.error(\n `[llmist] Too many log file errors (${writeErrorCount}), disabling file logging`,\n );\n sharedLogFileStream?.end();\n sharedLogFileStream = undefined;\n }\n });\n } catch (error) {\n console.error(\"Failed to initialize LLMIST_LOG_FILE output:\", error);\n }\n }\n\n // When file logging is enabled, use \"pretty\" type with overwrite to redirect to file\n // This lets tslog handle all formatting via prettyLogTemplate\n const useFileLogging = Boolean(sharedLogFileStream);\n\n const logger = new Logger<ILogObj>({\n name,\n minLevel,\n type: useFileLogging ? \"pretty\" : defaultType,\n // Hide log position for file logging and non-pretty types\n hideLogPositionForProduction: useFileLogging || defaultType !== \"pretty\",\n prettyLogTemplate: LOG_TEMPLATE,\n // Use overwrite to redirect tslog's formatted output to file instead of console\n overwrite: useFileLogging\n ? {\n transportFormatted: (\n logMetaMarkup: string,\n logArgs: unknown[],\n _logErrors: string[],\n ) => {\n // Skip if stream was disabled due to errors\n if (!sharedLogFileStream) return;\n\n // tslog provides formatted meta (timestamp, level, name) and args separately\n // Strip ANSI colors for clean file output\n const meta = stripAnsi(logMetaMarkup);\n const args = logArgs.map((arg) =>\n typeof arg === \"string\" ? stripAnsi(arg) : JSON.stringify(arg),\n );\n const line = `${meta}${args.join(\" \")}\\n`;\n\n // Use async stream.write() - non-blocking and buffered\n sharedLogFileStream.write(line);\n },\n }\n : undefined,\n });\n\n return logger;\n}\n\n/**\n * Default logger instance for the library.\n * Users can replace this with their own configured logger.\n */\nexport const defaultLogger = createLogger();\n","/**\n * Zod schema to JSON Schema conversion with instance mismatch detection.\n *\n * When consumers use their own `import { z } from \"zod\"` instead of\n * `import { z } from \"llmist\"`, the `.describe()` metadata can be lost\n * because Zod stores metadata on schema instances and `toJSONSchema()`\n * only reads from schemas created by the same Zod module instance.\n *\n * This module provides a `schemaToJSONSchema()` function that:\n * 1. Converts Zod schema to JSON Schema using the standard API\n * 2. Detects if descriptions were lost due to instance mismatch\n * 3. Logs a warning recommending `import { z } from \"llmist\"`\n * 4. Falls back to extracting descriptions from `schema._def`\n *\n * @module gadgets/schema-to-json\n */\n\nimport type { ZodTypeAny } from \"zod\";\nimport * as z from \"zod\";\nimport { defaultLogger } from \"../logging/logger.js\";\n\n/**\n * Convert a Zod schema to JSON Schema with description fallback.\n *\n * If descriptions exist in schema._def but are missing from the generated\n * JSON Schema (indicating a Zod instance mismatch), this function:\n * 1. Logs a warning recommending `import { z } from \"llmist\"`\n * 2. Extracts descriptions from _def and merges them into the JSON Schema\n *\n * @param schema - Zod schema to convert\n * @param options - Conversion options (target JSON Schema version)\n * @returns JSON Schema object with descriptions preserved\n *\n * @example\n * ```typescript\n * import { schemaToJSONSchema } from './schema-to-json.js';\n * import { z } from 'zod';\n *\n * const schema = z.object({\n * name: z.string().describe('User name'),\n * });\n *\n * const jsonSchema = schemaToJSONSchema(schema);\n * // { type: 'object', properties: { name: { type: 'string', description: 'User name' } } }\n * ```\n */\nexport function schemaToJSONSchema(\n schema: ZodTypeAny,\n options?: { target?: \"draft-7\" | \"draft-2020-12\" },\n): Record<string, unknown> {\n const jsonSchema = z.toJSONSchema(schema, options ?? { target: \"draft-7\" });\n\n // Check for instance mismatch by comparing _def descriptions with JSON schema\n const mismatches = detectDescriptionMismatch(schema, jsonSchema);\n\n if (mismatches.length > 0) {\n defaultLogger.warn(\n `Zod instance mismatch detected: ${mismatches.length} description(s) lost. ` +\n `For best results, use: import { z } from \"llmist\"`,\n );\n\n // Merge descriptions from _def into JSON schema\n return mergeDescriptions(schema, jsonSchema);\n }\n\n return jsonSchema;\n}\n\n/**\n * Detect if schema._def contains descriptions that are missing from JSON schema.\n * Returns array of paths where descriptions were lost.\n */\nfunction detectDescriptionMismatch(\n schema: ZodTypeAny,\n jsonSchema: Record<string, unknown>,\n): string[] {\n const mismatches: string[] = [];\n\n function checkSchema(zodSchema: ZodTypeAny, json: unknown, path: string): void {\n if (!zodSchema || typeof zodSchema !== \"object\") return;\n\n const def = zodSchema._def as unknown as Record<string, unknown> | undefined;\n const jsonObj = json as Record<string, unknown> | undefined;\n\n // Check if _def has description but JSON schema doesn't\n if (def?.description && !jsonObj?.description) {\n mismatches.push(path || \"root\");\n }\n\n // Recursively check object properties\n if (def?.typeName === \"ZodObject\" && def?.shape) {\n const shape =\n typeof def.shape === \"function\"\n ? (def.shape as () => Record<string, ZodTypeAny>)()\n : def.shape;\n for (const [key, fieldSchema] of Object.entries(shape as Record<string, ZodTypeAny>)) {\n const properties = jsonObj?.properties as Record<string, unknown> | undefined;\n const jsonProp = properties?.[key];\n checkSchema(fieldSchema, jsonProp, path ? `${path}.${key}` : key);\n }\n }\n\n // Check array items\n if (def?.typeName === \"ZodArray\" && def?.type) {\n checkSchema(def.type as ZodTypeAny, jsonObj?.items, path ? `${path}[]` : \"[]\");\n }\n\n // Check optional/nullable wrapped types\n if ((def?.typeName === \"ZodOptional\" || def?.typeName === \"ZodNullable\") && def?.innerType) {\n checkSchema(def.innerType as ZodTypeAny, json, path);\n }\n\n // Check default wrapped types\n if (def?.typeName === \"ZodDefault\" && def?.innerType) {\n checkSchema(def.innerType as ZodTypeAny, json, path);\n }\n }\n\n checkSchema(schema, jsonSchema, \"\");\n return mismatches;\n}\n\n/**\n * Merge descriptions from schema._def into JSON schema.\n * Returns a new JSON schema object with descriptions filled in from _def.\n */\nfunction mergeDescriptions(\n schema: ZodTypeAny,\n jsonSchema: Record<string, unknown>,\n): Record<string, unknown> {\n function merge(zodSchema: ZodTypeAny, json: unknown): unknown {\n if (!json || typeof json !== \"object\") return json;\n\n const def = zodSchema._def as unknown as Record<string, unknown> | undefined;\n const jsonObj = json as Record<string, unknown>;\n const merged: Record<string, unknown> = { ...jsonObj };\n\n // Copy description from _def if missing in JSON\n if (def?.description && !jsonObj.description) {\n merged.description = def.description;\n }\n\n // Recursively merge object properties\n if (def?.typeName === \"ZodObject\" && def?.shape && jsonObj.properties) {\n const shape =\n typeof def.shape === \"function\"\n ? (def.shape as () => Record<string, ZodTypeAny>)()\n : def.shape;\n const properties = jsonObj.properties as Record<string, unknown>;\n merged.properties = { ...properties };\n for (const [key, fieldSchema] of Object.entries(shape as Record<string, ZodTypeAny>)) {\n if (properties[key]) {\n (merged.properties as Record<string, unknown>)[key] = merge(fieldSchema, properties[key]);\n }\n }\n }\n\n // Merge array items\n if (def?.typeName === \"ZodArray\" && def?.type && jsonObj.items) {\n merged.items = merge(def.type as ZodTypeAny, jsonObj.items);\n }\n\n // Handle optional/nullable wrapped types\n if ((def?.typeName === \"ZodOptional\" || def?.typeName === \"ZodNullable\") && def?.innerType) {\n return merge(def.innerType as ZodTypeAny, json);\n }\n\n // Handle default wrapped types\n if (def?.typeName === \"ZodDefault\" && def?.innerType) {\n return merge(def.innerType as ZodTypeAny, json);\n }\n\n return merged;\n }\n\n return merge(schema, jsonSchema) as Record<string, unknown>;\n}\n","import type { ZodTypeAny } from \"zod\";\n\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport { AbortException } from \"./exceptions.js\";\nimport { schemaToJSONSchema } from \"./schema-to-json.js\";\nimport { validateGadgetSchema } from \"./schema-validator.js\";\nimport type { ExecutionContext, GadgetExample, GadgetExecuteReturn } from \"./types.js\";\n\n/**\n * Format parameters object as Block format for use in examples.\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 formatParamsForBlockExample(\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(formatParamsForBlockExample(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(formatParamsForBlockExample(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(\n schema: Record<string, unknown>,\n indent = \"\",\n atRoot = true,\n): 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 * Abstract base class for gadgets. Most users should use the `Gadget()` factory\n * or `createGadget()` function instead, as they provide better type safety\n * and simpler APIs.\n *\n * Extend this class directly only when you need advanced control over gadget behavior.\n */\nexport abstract class AbstractGadget {\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 * @param ctx - Optional execution context for cost reporting and LLM access\n * @returns Result as a string, or an object with result and optional cost\n *\n * @example\n * ```typescript\n * // Simple string return (free gadget)\n * execute(params) {\n * return \"result\";\n * }\n *\n * // Object return with cost tracking\n * execute(params) {\n * return { result: \"data\", cost: 0.001 };\n * }\n *\n * // Using context for callback-based cost reporting\n * execute(params, ctx) {\n * ctx.reportCost(0.001);\n * return \"result\";\n * }\n *\n * // Using wrapped LLMist for automatic cost tracking\n * async execute(params, ctx) {\n * const summary = await ctx.llmist.complete('Summarize: ' + params.text);\n * return summary;\n * }\n * ```\n */\n abstract execute(\n params: Record<string, unknown>,\n ctx?: ExecutionContext,\n ): GadgetExecuteReturn | Promise<GadgetExecuteReturn>;\n\n /**\n * Throws an AbortException if the execution has been aborted.\n *\n * Call this at key checkpoints in long-running gadgets to allow early exit\n * when the gadget has been cancelled (e.g., due to timeout). This enables\n * resource cleanup and prevents unnecessary work after cancellation.\n *\n * @param ctx - The execution context containing the abort signal\n * @throws AbortException if ctx.signal.aborted is true\n *\n * @example\n * ```typescript\n * class DataProcessor extends Gadget({\n * description: 'Processes data in multiple steps',\n * schema: z.object({ items: z.array(z.string()) }),\n * }) {\n * async execute(params: this['params'], ctx?: ExecutionContext): Promise<string> {\n * const results: string[] = [];\n *\n * for (const item of params.items) {\n * // Check before each expensive operation\n * this.throwIfAborted(ctx);\n *\n * results.push(await this.processItem(item));\n * }\n *\n * return results.join(', ');\n * }\n * }\n * ```\n */\n throwIfAborted(ctx?: ExecutionContext): void {\n if (ctx?.signal?.aborted) {\n throw new AbortException();\n }\n }\n\n /**\n * Register a cleanup function to run when execution is aborted (timeout or cancellation).\n * The cleanup function is called immediately if the signal is already aborted.\n * Errors thrown by the cleanup function are silently ignored.\n *\n * Use this to clean up resources like browser instances, database connections,\n * or child processes when the gadget is cancelled due to timeout.\n *\n * @param ctx - The execution context containing the abort signal\n * @param cleanup - Function to run on abort (can be sync or async)\n *\n * @example\n * ```typescript\n * class BrowserGadget extends Gadget({\n * description: 'Fetches web page content',\n * schema: z.object({ url: z.string() }),\n * }) {\n * async execute(params: this['params'], ctx?: ExecutionContext): Promise<string> {\n * const browser = await chromium.launch();\n * this.onAbort(ctx, () => browser.close());\n *\n * const page = await browser.newPage();\n * this.onAbort(ctx, () => page.close());\n *\n * await page.goto(params.url);\n * const content = await page.content();\n *\n * await browser.close();\n * return content;\n * }\n * }\n * ```\n */\n onAbort(ctx: ExecutionContext | undefined, cleanup: () => void | Promise<void>): void {\n if (!ctx?.signal) return;\n\n const safeCleanup = () => {\n try {\n const result = cleanup();\n if (result && typeof result === \"object\" && \"catch\" in result) {\n (result as Promise<void>).catch(() => {});\n }\n } catch {\n // Swallow synchronous errors\n }\n };\n\n if (ctx.signal.aborted) {\n // Already aborted, run cleanup immediately\n safeCleanup();\n return;\n }\n\n ctx.signal.addEventListener(\"abort\", safeCleanup, { once: true });\n }\n\n /**\n * Create an AbortController linked to the execution context's signal.\n * When the parent signal aborts, the returned controller also aborts with the same reason.\n *\n * Useful for passing abort signals to child operations like fetch() while still\n * being able to abort them independently if needed.\n *\n * @param ctx - The execution context containing the parent abort signal\n * @returns A new AbortController linked to the parent signal\n *\n * @example\n * ```typescript\n * class FetchGadget extends Gadget({\n * description: 'Fetches data from URL',\n * schema: z.object({ url: z.string() }),\n * }) {\n * async execute(params: this['params'], ctx?: ExecutionContext): Promise<string> {\n * const controller = this.createLinkedAbortController(ctx);\n *\n * // fetch() will automatically abort when parent times out\n * const response = await fetch(params.url, { signal: controller.signal });\n * return response.text();\n * }\n * }\n * ```\n */\n createLinkedAbortController(ctx?: ExecutionContext): AbortController {\n const controller = new AbortController();\n\n if (ctx?.signal) {\n if (ctx.signal.aborted) {\n controller.abort(ctx.signal.reason);\n } else {\n ctx.signal.addEventListener(\n \"abort\",\n () => {\n controller.abort(ctx.signal.reason);\n },\n { once: true },\n );\n }\n }\n\n return controller;\n }\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(\n optionsOrArgPrefix?: string | { argPrefix?: string; startPrefix?: string; endPrefix?: string },\n ): string {\n // Handle backwards compatibility: if string is passed, treat it as argPrefix\n const options =\n 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(\n formatParamsForBlockExample(example.params as Record<string, unknown>, \"\", effectiveArgPrefix),\n );\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","/**\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 { AbstractGadget } from \"./gadget.js\";\nimport type { ExecutionContext, GadgetExample, GadgetExecuteReturn } 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 /**\n * Execution function with typed parameters.\n * Can return string or { result, cost? }.\n * Optionally receives ExecutionContext for callback-based cost reporting.\n */\n execute: (\n params: InferSchema<TSchema>,\n ctx?: ExecutionContext,\n ) => GadgetExecuteReturn | Promise<GadgetExecuteReturn>;\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): AbstractGadget {\n class DynamicGadget extends AbstractGadget {\n name = config.name;\n description = config.description;\n parameterSchema = config.schema;\n timeoutMs = config.timeoutMs;\n examples = config.examples;\n\n execute(\n params: Record<string, unknown>,\n ctx?: ExecutionContext,\n ): GadgetExecuteReturn | Promise<GadgetExecuteReturn> {\n // Cast to inferred type and call user's function with context\n return config.execute(params as InferSchema<TSchema>, ctx);\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/** Default max output in characters (~19k tokens at 4 chars/token) */\nconst DEFAULT_MAX_OUTPUT_CHARS = 76_800;\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 * @param maxOutputChars - Maximum characters to return (default: 76,800 = ~19k tokens)\n * @returns A GadgetOutputViewer gadget instance\n *\n * @example\n * ```typescript\n * const store = new GadgetOutputStore();\n * const viewer = createGadgetOutputViewer(store, 76_800);\n * registry.register(\"GadgetOutputViewer\", viewer);\n * ```\n */\nexport function createGadgetOutputViewer(\n store: GadgetOutputStore,\n maxOutputChars: number = DEFAULT_MAX_OUTPUT_CHARS,\n) {\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 // Step 3: Build output string\n let output = lines.join(\"\\n\");\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 // Step 4: Apply output size limit to prevent context explosion\n let truncatedBySize = false;\n let linesIncluded = returnedLines;\n if (output.length > maxOutputChars) {\n truncatedBySize = true;\n let truncatedOutput = \"\";\n linesIncluded = 0;\n\n for (const line of lines) {\n if (truncatedOutput.length + line.length + 1 > maxOutputChars) break;\n truncatedOutput += line + \"\\n\";\n linesIncluded++;\n }\n\n output = truncatedOutput;\n }\n\n // Build header with appropriate messaging\n let header: string;\n if (truncatedBySize) {\n const remainingLines = returnedLines - linesIncluded;\n header =\n `[Showing ${linesIncluded} of ${totalLines} lines (truncated due to size limit)]\\n` +\n `[... ${remainingLines.toLocaleString()} more lines. Use limit parameter to paginate, e.g., limit: \"${linesIncluded + 1}-${linesIncluded + 200}\"]\\n`;\n } else if (returnedLines < totalLines) {\n header = `[Showing ${returnedLines} of ${totalLines} lines]\\n`;\n } else {\n header = `[Showing all ${totalLines} lines]\\n`;\n }\n\n return header + output;\n },\n });\n}\n\n// Export helpers for testing\nexport { applyPattern, applyPatterns, applyLineLimit };\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 * Retry configuration for LLM API calls.\n *\n * Provides exponential backoff with jitter to handle transient failures\n * like rate limits (429), server errors (5xx), and connection issues.\n */\n\n/**\n * Configuration options for retry behavior.\n *\n * @example\n * ```typescript\n * // Custom retry with monitoring\n * const agent = LLMist.createAgent()\n * .withRetry({\n * retries: 5,\n * minTimeout: 2000,\n * onRetry: (error, attempt) => console.log(`Retry ${attempt}`),\n * })\n * .ask(\"Hello\");\n * ```\n */\nexport interface RetryConfig {\n /**\n * Whether retry is enabled.\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Maximum number of retry attempts.\n * @default 3\n */\n retries?: number;\n\n /**\n * Minimum delay before the first retry in milliseconds.\n * @default 1000\n */\n minTimeout?: number;\n\n /**\n * Maximum delay between retries in milliseconds.\n * @default 30000\n */\n maxTimeout?: number;\n\n /**\n * Exponential factor for backoff calculation.\n * @default 2\n */\n factor?: number;\n\n /**\n * Whether to add random jitter to prevent thundering herd.\n * @default true\n */\n randomize?: boolean;\n\n /**\n * Called before each retry attempt.\n * Use for logging or metrics.\n */\n onRetry?: (error: Error, attempt: number) => void;\n\n /**\n * Called when all retries are exhausted and the operation fails.\n * The error will still be thrown after this callback.\n */\n onRetriesExhausted?: (error: Error, attempts: number) => void;\n\n /**\n * Custom function to determine if an error should trigger a retry.\n * If not provided, uses the default `isRetryableError` classification.\n *\n * @returns true to retry, false to fail immediately\n */\n shouldRetry?: (error: Error) => boolean;\n}\n\n/**\n * Resolved retry configuration with all defaults applied.\n */\nexport interface ResolvedRetryConfig {\n enabled: boolean;\n retries: number;\n minTimeout: number;\n maxTimeout: number;\n factor: number;\n randomize: boolean;\n onRetry?: (error: Error, attempt: number) => void;\n onRetriesExhausted?: (error: Error, attempts: number) => void;\n shouldRetry?: (error: Error) => boolean;\n}\n\n/**\n * Default retry configuration values.\n * Conservative defaults: 3 retries with up to 30s delay.\n */\nexport const DEFAULT_RETRY_CONFIG: Omit<\n ResolvedRetryConfig,\n \"onRetry\" | \"onRetriesExhausted\" | \"shouldRetry\"\n> = {\n enabled: true,\n retries: 3,\n minTimeout: 1000,\n maxTimeout: 30000,\n factor: 2,\n randomize: true,\n};\n\n/**\n * Resolves a partial retry configuration by applying defaults.\n *\n * @param config - Partial configuration (optional)\n * @returns Fully resolved configuration with defaults applied\n */\nexport function resolveRetryConfig(config?: RetryConfig): ResolvedRetryConfig {\n if (!config) {\n return { ...DEFAULT_RETRY_CONFIG };\n }\n\n return {\n enabled: config.enabled ?? DEFAULT_RETRY_CONFIG.enabled,\n retries: config.retries ?? DEFAULT_RETRY_CONFIG.retries,\n minTimeout: config.minTimeout ?? DEFAULT_RETRY_CONFIG.minTimeout,\n maxTimeout: config.maxTimeout ?? DEFAULT_RETRY_CONFIG.maxTimeout,\n factor: config.factor ?? DEFAULT_RETRY_CONFIG.factor,\n randomize: config.randomize ?? DEFAULT_RETRY_CONFIG.randomize,\n onRetry: config.onRetry,\n onRetriesExhausted: config.onRetriesExhausted,\n shouldRetry: config.shouldRetry,\n };\n}\n\n/**\n * Determines if an error is retryable based on common LLM API error patterns.\n *\n * Retryable errors include:\n * - Rate limits (429)\n * - Server errors (500, 502, 503, 504)\n * - Timeouts and connection errors\n * - Provider-specific transient errors\n *\n * Non-retryable errors include:\n * - Authentication errors (401, 403)\n * - Bad request errors (400)\n * - Not found errors (404)\n * - Content policy violations\n *\n * @param error - The error to classify\n * @returns true if the error is retryable\n */\nexport function isRetryableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n const name = error.name;\n\n // Rate limits (429) - always retry\n if (message.includes(\"429\") || message.includes(\"rate limit\") || message.includes(\"rate_limit\")) {\n return true;\n }\n\n // Server errors (5xx) - retry\n if (\n message.includes(\"500\") ||\n message.includes(\"502\") ||\n message.includes(\"503\") ||\n message.includes(\"504\") ||\n message.includes(\"internal server error\") ||\n message.includes(\"bad gateway\") ||\n message.includes(\"service unavailable\") ||\n message.includes(\"gateway timeout\")\n ) {\n return true;\n }\n\n // Timeouts - retry\n if (\n message.includes(\"timeout\") ||\n message.includes(\"etimedout\") ||\n message.includes(\"timed out\")\n ) {\n return true;\n }\n\n // Connection errors - retry\n if (\n message.includes(\"econnreset\") ||\n message.includes(\"econnrefused\") ||\n message.includes(\"enotfound\") ||\n message.includes(\"connection\") ||\n message.includes(\"network\")\n ) {\n return true;\n }\n\n // Provider-specific error names (from Anthropic, OpenAI SDKs)\n if (\n name === \"APIConnectionError\" ||\n name === \"RateLimitError\" ||\n name === \"InternalServerError\" ||\n name === \"ServiceUnavailableError\" ||\n name === \"APITimeoutError\"\n ) {\n return true;\n }\n\n // Overloaded errors (common with Claude)\n if (message.includes(\"overloaded\") || message.includes(\"capacity\")) {\n return true;\n }\n\n // Don't retry authentication, bad requests, or content policy errors\n if (\n message.includes(\"401\") ||\n message.includes(\"403\") ||\n message.includes(\"400\") ||\n message.includes(\"404\") ||\n message.includes(\"authentication\") ||\n message.includes(\"unauthorized\") ||\n message.includes(\"forbidden\") ||\n message.includes(\"invalid\") ||\n message.includes(\"content policy\") ||\n name === \"AuthenticationError\" ||\n name === \"BadRequestError\" ||\n name === \"NotFoundError\" ||\n name === \"PermissionDeniedError\"\n ) {\n return false;\n }\n\n // Default: don't retry unknown errors\n return false;\n}\n\n/**\n * Formats an LLM API error into a clean, user-friendly message.\n *\n * Extracts the most relevant information from provider error objects,\n * hiding verbose JSON/stack traces while preserving actionable details.\n *\n * @param error - The error to format\n * @returns A clean, single-line error message\n *\n * @example\n * ```typescript\n * // Gemini RESOURCE_EXHAUSTED error\n * formatLLMError(error);\n * // Returns: \"Rate limit exceeded (429) - retry after a few seconds\"\n *\n * // Anthropic overloaded error\n * formatLLMError(error);\n * // Returns: \"API overloaded - retry later\"\n * ```\n */\nexport function formatLLMError(error: Error): string {\n const message = error.message;\n const name = error.name;\n\n // Gemini RESOURCE_EXHAUSTED\n if (message.includes(\"RESOURCE_EXHAUSTED\") || message.includes(\"429\")) {\n return \"Rate limit exceeded (429) - retry after a few seconds\";\n }\n\n // Rate limits\n if (message.toLowerCase().includes(\"rate limit\") || message.toLowerCase().includes(\"rate_limit\")) {\n return \"Rate limit exceeded - retry after a few seconds\";\n }\n\n // Overloaded/capacity errors\n if (message.toLowerCase().includes(\"overloaded\") || message.toLowerCase().includes(\"capacity\")) {\n return \"API overloaded - retry later\";\n }\n\n // Server errors\n if (message.includes(\"500\") || message.toLowerCase().includes(\"internal server error\")) {\n return \"Internal server error (500) - the API is experiencing issues\";\n }\n if (message.includes(\"502\") || message.toLowerCase().includes(\"bad gateway\")) {\n return \"Bad gateway (502) - the API is temporarily unavailable\";\n }\n if (message.includes(\"503\") || message.toLowerCase().includes(\"service unavailable\")) {\n return \"Service unavailable (503) - the API is temporarily down\";\n }\n if (message.includes(\"504\") || message.toLowerCase().includes(\"gateway timeout\")) {\n return \"Gateway timeout (504) - the request took too long\";\n }\n\n // Timeout errors\n if (message.toLowerCase().includes(\"timeout\") || message.toLowerCase().includes(\"timed out\")) {\n return \"Request timed out - the API took too long to respond\";\n }\n\n // Connection errors\n if (message.toLowerCase().includes(\"econnrefused\")) {\n return \"Connection refused - unable to reach the API\";\n }\n if (message.toLowerCase().includes(\"econnreset\")) {\n return \"Connection reset - the API closed the connection\";\n }\n if (message.toLowerCase().includes(\"enotfound\")) {\n return \"DNS error - unable to resolve API hostname\";\n }\n\n // Auth errors\n if (message.includes(\"401\") || message.toLowerCase().includes(\"unauthorized\") || name === \"AuthenticationError\") {\n return \"Authentication failed - check your API key\";\n }\n if (message.includes(\"403\") || message.toLowerCase().includes(\"forbidden\") || name === \"PermissionDeniedError\") {\n return \"Permission denied - your API key lacks required permissions\";\n }\n\n // Bad request\n if (message.includes(\"400\") || name === \"BadRequestError\") {\n // Try to extract a useful message from the error\n const match = message.match(/message['\":\\s]+['\"]?([^'\"}\\]]+)/i);\n if (match) {\n return `Bad request: ${match[1].trim()}`;\n }\n return \"Bad request - check your input parameters\";\n }\n\n // Content policy\n if (message.toLowerCase().includes(\"content policy\") || message.toLowerCase().includes(\"safety\")) {\n return \"Content policy violation - the request was blocked\";\n }\n\n // Try to extract a clean message from JSON errors\n // First try proper JSON parsing (handles nested structures and escaped quotes)\n try {\n const parsed = JSON.parse(message);\n // Support common API error structures: {error: {message: \"...\"}} or {message: \"...\"}\n const extractedMessage = parsed?.error?.message || parsed?.message;\n if (typeof extractedMessage === \"string\" && extractedMessage.length > 0) {\n return extractedMessage.trim();\n }\n } catch {\n // Not valid JSON, fall through to regex\n }\n\n // Fall back to regex extraction for malformed JSON or partial strings\n const jsonMatch = message.match(/[\"']?message[\"']?\\s*[:=]\\s*[\"']([^\"']+)[\"']/i);\n if (jsonMatch) {\n return jsonMatch[1].trim();\n }\n\n // If the message is very long (likely JSON dump), truncate it\n if (message.length > 200) {\n // Try to find the first sentence or meaningful part\n const firstPart = message.split(/[.!?\\n]/)[0];\n if (firstPart && firstPart.length > 10 && firstPart.length < 150) {\n return firstPart.trim();\n }\n return message.slice(0, 150).trim() + \"...\";\n }\n\n // Return the original message if we couldn't simplify it\n return message;\n}\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(config: CompactionConfig = {}): 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 =\n \"[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 { HybridStrategy } from \"./hybrid.js\";\nexport { SlidingWindowStrategy } from \"./sliding-window.js\";\nexport { SummarizationStrategy } from \"./summarization.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 { LLMMessage } from \"../../core/messages.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 {\n HybridStrategy,\n SlidingWindowStrategy,\n SummarizationStrategy,\n} from \"./strategies/index.js\";\nimport type { CompactionStrategy } from \"./strategy.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 * ConversationManager handles conversation state and message building.\n * Extracted from AgentLoop to follow Single Responsibility Principle.\n */\n\nimport type { MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, type LLMMessage, LLMMessageBuilder } from \"../core/messages.js\";\nimport type { GadgetMediaOutput } from \"../gadgets/types.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: MessageContent): void {\n this.historyBuilder.addUser(content);\n }\n\n addAssistantMessage(content: string): void {\n this.historyBuilder.addAssistant(content);\n }\n\n addGadgetCallResult(\n gadgetName: string,\n parameters: Record<string, unknown>,\n result: string,\n invocationId: string,\n media?: GadgetMediaOutput[],\n mediaIds?: string[],\n ): void {\n this.historyBuilder.addGadgetCallResult(gadgetName, parameters, result, invocationId, media, mediaIds);\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 // Assistant messages are always text, extract if multimodal\n this.historyBuilder.addAssistant(extractMessageText(msg.content));\n }\n // System messages are not added to history (they're in baseMessages)\n }\n }\n\n getConversationHistory(): LLMMessage[] {\n // Returns full conversation history: initial messages (from previous sessions via withHistory())\n // plus runtime history (from current session). Excludes base messages (system prompt, gadget instructions).\n return [...this.initialMessages, ...this.historyBuilder.build()];\n }\n}\n","/**\n * Event handler sugar for cleaner event processing.\n *\n * Instead of verbose if/else chains, use named handlers\n * for each event type.\n *\n * @example\n * ```typescript\n * await agent.runWith({\n * onText: (content) => console.log(\"LLM:\", content),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\n\nimport type { StreamEvent } from \"../gadgets/types.js\";\n\n/**\n * Named event handlers for different event types.\n */\nexport interface EventHandlers {\n /** Called when text is generated by the LLM */\n onText?: (content: string) => void | Promise<void>;\n\n /** Called when a gadget is about to be executed */\n onGadgetCall?: (call: {\n gadgetName: string;\n invocationId: string;\n parameters?: Record<string, unknown>;\n parametersRaw: string;\n dependencies: string[];\n }) => void | Promise<void>;\n\n /** Called when a gadget execution completes */\n onGadgetResult?: (result: {\n gadgetName: string;\n invocationId: 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 invocationId: event.call.invocationId,\n parameters: event.call.parameters,\n parametersRaw: event.call.parametersRaw,\n dependencies: event.call.dependencies,\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 * 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 * Runtime validators for hook action types.\n *\n * These validators ensure that controllers return valid action objects,\n * catching common mistakes like missing required fields.\n */\n\nimport type {\n AfterGadgetExecutionAction,\n AfterLLMCallAction,\n AfterLLMErrorAction,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n} from \"./hooks.js\";\n\nexport class HookValidationError extends Error {\n constructor(hookName: string, message: string) {\n super(`Invalid action from ${hookName}: ${message}`);\n this.name = \"HookValidationError\";\n }\n}\n\n/**\n * Validate beforeLLMCall action.\n */\nexport function validateBeforeLLMCallAction(action: BeforeLLMCallAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"beforeLLMCall\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"proceed\" && actionType !== \"skip\") {\n throw new HookValidationError(\n \"beforeLLMCall\",\n `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n );\n }\n\n if (actionType === \"skip\" && !action.syntheticResponse) {\n throw new HookValidationError(\n \"beforeLLMCall\",\n \"When action is 'skip', syntheticResponse is required\",\n );\n }\n}\n\n/**\n * Validate afterLLMCall action.\n */\nexport function validateAfterLLMCallAction(action: AfterLLMCallAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n const validActions = [\"continue\", \"append_messages\", \"modify_and_continue\", \"append_and_modify\"];\n if (!validActions.includes(actionType)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Invalid action type: ${actionType}. Must be one of: ${validActions.join(\", \")}`,\n );\n }\n\n if (actionType === \"append_messages\" || actionType === \"append_and_modify\") {\n if (!(\"messages\" in action) || !action.messages || !Array.isArray(action.messages)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', messages array is required`,\n );\n }\n\n if (action.messages.length === 0) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', messages array must not be empty`,\n );\n }\n\n // Validate each message\n for (let i = 0; i < action.messages.length; i++) {\n const msg = action.messages[i];\n if (!msg || typeof msg !== \"object\") {\n throw new HookValidationError(\"afterLLMCall\", `Message at index ${i} must be an object`);\n }\n if (!msg.role || !msg.content) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Message at index ${i} must have 'role' and 'content' fields`,\n );\n }\n if (![\"system\", \"user\", \"assistant\"].includes(msg.role)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Message at index ${i} has invalid role: ${msg.role}`,\n );\n }\n }\n }\n\n if (actionType === \"modify_and_continue\" || actionType === \"append_and_modify\") {\n if (!(\"modifiedMessage\" in action) || !action.modifiedMessage) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', modifiedMessage is required`,\n );\n }\n }\n}\n\n/**\n * Validate afterLLMError action.\n */\nexport function validateAfterLLMErrorAction(action: AfterLLMErrorAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterLLMError\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"rethrow\" && actionType !== \"recover\") {\n throw new HookValidationError(\n \"afterLLMError\",\n `Invalid action type: ${actionType}. Must be 'rethrow' or 'recover'`,\n );\n }\n\n if (actionType === \"recover\" && !action.fallbackResponse) {\n throw new HookValidationError(\n \"afterLLMError\",\n \"When action is 'recover', fallbackResponse is required\",\n );\n }\n}\n\n/**\n * Validate beforeGadgetExecution action.\n */\nexport function validateBeforeGadgetExecutionAction(action: BeforeGadgetExecutionAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"proceed\" && actionType !== \"skip\") {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n );\n }\n\n if (actionType === \"skip\" && !action.syntheticResult) {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n \"When action is 'skip', syntheticResult is required\",\n );\n }\n}\n\n/**\n * Validate afterGadgetExecution action.\n */\nexport function validateAfterGadgetExecutionAction(action: AfterGadgetExecutionAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"continue\" && actionType !== \"recover\") {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n `Invalid action type: ${actionType}. Must be 'continue' or 'recover'`,\n );\n }\n\n if (actionType === \"recover\" && !action.fallbackResult) {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n \"When action is 'recover', fallbackResult is required\",\n );\n }\n}\n","/**\n * 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: 0.8,\n output: 4.0,\n cachedInput: 0.08,\n cacheWriteInput: 1.0,\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 // Dated Opus 4.5\n {\n provider: \"anthropic\",\n modelId: \"claude-opus-4-5-20251124\",\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: \"Most powerful model for coding and computer use. Extended thinking support.\",\n },\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: 0.8,\n output: 4.0,\n cachedInput: 0.08,\n cacheWriteInput: 1.0,\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.buildApiRequest(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: Normalize provider-specific stream into universal format\n yield* this.normalizeProviderStream(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 API request.\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 request object ready for the API call\n */\n protected abstract buildApiRequest(\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 * Normalize 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 normalizeProviderStream(rawStream: AsyncIterable<unknown>): LLMStream;\n}\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 ContentBlockParam,\n ImageBlockParam,\n MessageCreateParamsStreaming,\n MessageStreamEvent,\n TextBlockParam,\n} from \"@anthropic-ai/sdk/resources/messages\";\nimport type { ContentPart, ImageContentPart, ImageMimeType } from \"../core/input-content.js\";\nimport type { LLMMessage, MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, normalizeMessageContent } 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 // =========================================================================\n // Image Generation (Not Supported)\n // =========================================================================\n\n supportsImageGeneration(_modelId: string): boolean {\n return false;\n }\n\n async generateImage(): Promise<never> {\n throw new Error(\n \"Anthropic does not support image generation. Use OpenAI (DALL-E, GPT Image) or Google Gemini (Imagen) instead.\",\n );\n }\n\n // =========================================================================\n // Speech Generation (Not Supported)\n // =========================================================================\n\n supportsSpeechGeneration(_modelId: string): boolean {\n return false;\n }\n\n async generateSpeech(): Promise<never> {\n throw new Error(\n \"Anthropic does not support speech generation. Use OpenAI (TTS) or Google Gemini (TTS) instead.\",\n );\n }\n\n protected buildApiRequest(\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 // System messages are always text-only\n const system =\n systemMessages.length > 0\n ? systemMessages.map((m, index) => ({\n type: \"text\" as const,\n text: extractMessageText(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 multimodal content support\n // Cache_control is added to the last part of the last user message\n const conversation = nonSystemMessages.map((message, index) => ({\n role: message.role,\n content: this.convertToAnthropicContent(\n message.content,\n message.role === \"user\" && index === lastUserIndex,\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 /**\n * Convert llmist content to Anthropic's content block format.\n * Handles text, images (base64 only), and applies cache_control.\n */\n private convertToAnthropicContent(\n content: MessageContent,\n addCacheControl: boolean,\n ): ContentBlockParam[] {\n const parts = normalizeMessageContent(content);\n\n return parts.map((part, index) => {\n const isLastPart = index === parts.length - 1;\n const cacheControl =\n addCacheControl && isLastPart ? { cache_control: { type: \"ephemeral\" as const } } : {};\n\n if (part.type === \"text\") {\n return {\n type: \"text\" as const,\n text: part.text,\n ...cacheControl,\n } as TextBlockParam;\n }\n\n if (part.type === \"image\") {\n return this.convertImagePart(part, cacheControl);\n }\n\n if (part.type === \"audio\") {\n throw new Error(\n \"Anthropic does not support audio input. Use Google Gemini for audio processing.\",\n );\n }\n\n throw new Error(`Unsupported content type: ${(part as ContentPart).type}`);\n });\n }\n\n /**\n * Convert an image content part to Anthropic's image block format.\n */\n private convertImagePart(\n part: ImageContentPart,\n cacheControl: { cache_control?: { type: \"ephemeral\" } },\n ): ImageBlockParam {\n if (part.source.type === \"url\") {\n throw new Error(\n \"Anthropic does not support image URLs. Please provide base64-encoded image data instead.\",\n );\n }\n\n return {\n type: \"image\" as const,\n source: {\n type: \"base64\" as const,\n media_type: part.source.mediaType as ImageMimeType,\n data: part.source.data,\n },\n ...cacheControl,\n };\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 *normalizeProviderStream(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\n ? systemMessages.map((m) => extractMessageText(m.content)).join(\"\\n\\n\")\n : undefined;\n\n // Convert messages to Anthropic format, handling multimodal content\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: this.convertToAnthropicContent(message.content, false),\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 // For multimodal, extract text and estimate; images add ~1000 tokens\n let totalChars = 0;\n let imageCount = 0;\n for (const msg of messages) {\n const parts = normalizeMessageContent(msg.content);\n for (const part of parts) {\n if (part.type === \"text\") {\n totalChars += part.text.length;\n } else if (part.type === \"image\") {\n imageCount++;\n }\n }\n }\n // Anthropic charges ~1000 tokens per image (rough estimate).\n // Source: https://docs.anthropic.com/en/docs/build-with-claude/vision\n // Actual cost depends on image size, but this provides a reasonable fallback.\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN) + imageCount * 1000;\n }\n }\n}\n\nexport function createAnthropicProviderFromEnv(): AnthropicMessagesProvider | null {\n return createProviderFromEnv(\"ANTHROPIC_API_KEY\", Anthropic, AnthropicMessagesProvider);\n}\n","/**\n * Google Gemini Image Generation Model Catalog\n *\n * Pricing as of December 2025:\n *\n * Imagen 4 Family (standalone image generation):\n * - imagen-4.0-fast-generate-001: $0.02 per image\n * - imagen-4.0-generate-001: $0.04 per image\n * - imagen-4.0-ultra-generate-001: $0.06 per image\n *\n * Gemini Native Image Generation (multimodal):\n * - gemini-2.5-flash-image: $0.039 per output image\n * - gemini-3-pro-image-preview: ~$0.134 per 1K/2K image, $0.24 per 4K\n *\n * @see https://ai.google.dev/gemini-api/docs/pricing\n * @see https://ai.google.dev/gemini-api/docs/imagen\n */\n\nimport type { ImageModelSpec } from \"../core/media-types.js\";\n\n/** Imagen 4 supported aspect ratios */\nexport const IMAGEN4_ASPECT_RATIOS = [\"1:1\", \"3:4\", \"4:3\", \"9:16\", \"16:9\"] as const;\nexport type Imagen4AspectRatio = (typeof IMAGEN4_ASPECT_RATIOS)[number];\n\n/** Gemini native image supported aspect ratios */\nexport const GEMINI_IMAGE_ASPECT_RATIOS = [\"1:1\", \"3:4\", \"4:3\", \"9:16\", \"16:9\"] as const;\n\n/**\n * Google Image Model Specifications\n */\nexport const geminiImageModels: ImageModelSpec[] = [\n // Imagen 4 Family (standalone image generation)\n {\n provider: \"gemini\",\n modelId: \"imagen-4.0-fast-generate-001\",\n displayName: \"Imagen 4 Fast\",\n pricing: {\n perImage: 0.02,\n },\n supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n maxImages: 4,\n defaultSize: \"1:1\",\n features: {\n textRendering: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"imagen-4.0-generate-001\",\n displayName: \"Imagen 4\",\n pricing: {\n perImage: 0.04,\n },\n supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n maxImages: 4,\n defaultSize: \"1:1\",\n features: {\n textRendering: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"imagen-4.0-ultra-generate-001\",\n displayName: \"Imagen 4 Ultra\",\n pricing: {\n perImage: 0.06,\n },\n supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n maxImages: 4,\n defaultSize: \"1:1\",\n features: {\n textRendering: true,\n },\n },\n // Preview versions\n {\n provider: \"gemini\",\n modelId: \"imagen-4.0-generate-preview-06-06\",\n displayName: \"Imagen 4 (Preview)\",\n pricing: {\n perImage: 0.04,\n },\n supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n maxImages: 4,\n defaultSize: \"1:1\",\n features: {\n textRendering: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"imagen-4.0-ultra-generate-preview-06-06\",\n displayName: \"Imagen 4 Ultra (Preview)\",\n pricing: {\n perImage: 0.06,\n },\n supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n maxImages: 4,\n defaultSize: \"1:1\",\n features: {\n textRendering: true,\n },\n },\n // Gemini Native Image Generation (multimodal models)\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-flash-image\",\n displayName: \"Gemini 2.5 Flash Image\",\n pricing: {\n perImage: 0.039,\n },\n supportedSizes: [...GEMINI_IMAGE_ASPECT_RATIOS],\n maxImages: 1,\n defaultSize: \"1:1\",\n features: {\n conversational: true,\n textRendering: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-flash-image-preview\",\n displayName: \"Gemini 2.5 Flash Image (Preview)\",\n pricing: {\n perImage: 0.039,\n },\n supportedSizes: [...GEMINI_IMAGE_ASPECT_RATIOS],\n maxImages: 1,\n defaultSize: \"1:1\",\n features: {\n conversational: true,\n textRendering: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"gemini-3-pro-image-preview\",\n displayName: \"Gemini 3 Pro Image (Preview)\",\n pricing: {\n // Token-based: ~$0.134 per 1K/2K image, $0.24 per 4K\n // Using 2K as default\n bySize: {\n \"1K\": 0.134,\n \"2K\": 0.134,\n \"4K\": 0.24,\n },\n },\n supportedSizes: [\"1K\", \"2K\", \"4K\"],\n maxImages: 1,\n defaultSize: \"2K\",\n features: {\n conversational: true,\n textRendering: true,\n },\n },\n // Alias: nano-banana-pro-preview is gemini-3-pro-image-preview\n {\n provider: \"gemini\",\n modelId: \"nano-banana-pro-preview\",\n displayName: \"Nano Banana Pro (Gemini 3 Pro Image)\",\n pricing: {\n bySize: {\n \"1K\": 0.134,\n \"2K\": 0.134,\n \"4K\": 0.24,\n },\n },\n supportedSizes: [\"1K\", \"2K\", \"4K\"],\n maxImages: 1,\n defaultSize: \"2K\",\n features: {\n conversational: true,\n textRendering: true,\n },\n },\n];\n\n/**\n * Get image model spec by model ID.\n */\nexport function getGeminiImageModelSpec(modelId: string): ImageModelSpec | undefined {\n return geminiImageModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is a Gemini image model.\n */\nexport function isGeminiImageModel(modelId: string): boolean {\n return geminiImageModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for image generation.\n *\n * @param modelId - The model ID\n * @param size - Image size (for models with size-based pricing)\n * @param n - Number of images\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateGeminiImageCost(modelId: string, size = \"1:1\", n = 1): number | undefined {\n const spec = getGeminiImageModelSpec(modelId);\n if (!spec) return undefined;\n\n // Simple per-image pricing (Imagen 4, Gemini Flash Image)\n if (spec.pricing.perImage !== undefined) {\n return spec.pricing.perImage * n;\n }\n\n // Size-based pricing (Gemini 3 Pro Image)\n if (spec.pricing.bySize) {\n const sizePrice = spec.pricing.bySize[size];\n if (typeof sizePrice === \"number\") {\n return sizePrice * n;\n }\n }\n\n return undefined;\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-12-20\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 3 Flash (Preview)\n {\n provider: \"gemini\",\n modelId: \"gemini-3-flash-preview\",\n displayName: \"Gemini 3 Flash (Preview)\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n pricing: {\n input: 0.4, // $0.40 for text/image/video\n output: 3.0,\n cachedInput: 0.04,\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-12\",\n notes: \"Fast, cost-effective model with Deep Think mode. Good for agentic tasks.\",\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","/**\n * Google Gemini Speech (TTS) Model Catalog\n *\n * Pricing as of December 2025 (per 1M tokens):\n *\n * Gemini 2.5 Flash Preview TTS:\n * - Input (text): $0.50\n * - Output (audio): $10.00\n *\n * Gemini 2.5 Pro Preview TTS:\n * - Input (text): $1.00\n * - Output (audio): $20.00\n *\n * @see https://ai.google.dev/gemini-api/docs/pricing\n * @see https://ai.google.dev/gemini-api/docs/speech-generation\n */\n\nimport type { AudioFormat, SpeechModelSpec } from \"../core/media-types.js\";\n\n/**\n * Gemini TTS voices (30 prebuilt voices)\n * Each has distinct characteristics like \"Bright\", \"Upbeat\", \"Breathy\", \"Warm\", etc.\n */\nexport const GEMINI_TTS_VOICES = [\n \"Zephyr\", // Bright\n \"Puck\", // Upbeat\n \"Charon\", // Informative\n \"Kore\", // Firm\n \"Fenrir\", // Excitable\n \"Leda\", // Youthful\n \"Orus\", // Firm\n \"Aoede\", // Breezy\n \"Callirrhoe\", // Easy-going\n \"Autonoe\", // Bright\n \"Enceladus\", // Breathy\n \"Iapetus\", // Clear\n \"Umbriel\", // Easy-going\n \"Algieba\", // Smooth\n \"Despina\", // Smooth\n \"Erinome\", // Clear\n \"Algenib\", // Gravelly\n \"Rasalgethi\", // Informative\n \"Laomedeia\", // Upbeat\n \"Achernar\", // Soft\n \"Alnilam\", // Firm\n \"Schedar\", // Even\n \"Gacrux\", // Mature\n \"Pulcherrima\", // Forward\n \"Achird\", // Friendly\n \"Zubenelgenubi\", // Casual\n \"Vindemiatrix\", // Gentle\n \"Sadachbia\", // Lively\n \"Sadaltager\", // Knowledgeable\n \"Sulafat\", // Warm\n] as const;\n\nexport type GeminiTTSVoice = (typeof GEMINI_TTS_VOICES)[number];\n\n/** Gemini TTS supported audio format (PCM only, converted to WAV) */\nexport const GEMINI_TTS_FORMATS: AudioFormat[] = [\"pcm\", \"wav\"];\n\n/**\n * Gemini Speech Model Specifications\n */\nexport const geminiSpeechModels: SpeechModelSpec[] = [\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-flash-preview-tts\",\n displayName: \"Gemini 2.5 Flash TTS (Preview)\",\n pricing: {\n // $0.50 per 1M input tokens = $0.0000005 per token\n perInputToken: 0.0000005,\n // $10.00 per 1M audio output tokens = $0.00001 per token\n perAudioOutputToken: 0.00001,\n // Rough estimate: ~$0.01 per minute of audio\n perMinute: 0.01,\n },\n voices: [...GEMINI_TTS_VOICES],\n formats: GEMINI_TTS_FORMATS,\n maxInputLength: 8000, // bytes (text + prompt combined)\n defaultVoice: \"Zephyr\",\n defaultFormat: \"wav\",\n features: {\n multiSpeaker: true,\n languages: 24,\n voiceInstructions: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-pro-preview-tts\",\n displayName: \"Gemini 2.5 Pro TTS (Preview)\",\n pricing: {\n // $1.00 per 1M input tokens = $0.000001 per token\n perInputToken: 0.000001,\n // $20.00 per 1M audio output tokens = $0.00002 per token\n perAudioOutputToken: 0.00002,\n // Rough estimate: ~$0.02 per minute of audio\n perMinute: 0.02,\n },\n voices: [...GEMINI_TTS_VOICES],\n formats: GEMINI_TTS_FORMATS,\n maxInputLength: 8000, // bytes\n defaultVoice: \"Zephyr\",\n defaultFormat: \"wav\",\n features: {\n multiSpeaker: true,\n languages: 24,\n voiceInstructions: true,\n },\n },\n];\n\n/**\n * Get speech model spec by model ID.\n */\nexport function getGeminiSpeechModelSpec(modelId: string): SpeechModelSpec | undefined {\n return geminiSpeechModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is a Gemini speech model.\n */\nexport function isGeminiSpeechModel(modelId: string): boolean {\n return geminiSpeechModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for speech generation.\n *\n * Uses per-minute approximation since exact token counts are hard to predict.\n *\n * @param modelId - The model ID\n * @param characterCount - Number of characters in the input\n * @param estimatedMinutes - Optional: estimated audio duration\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateGeminiSpeechCost(\n modelId: string,\n characterCount: number,\n estimatedMinutes?: number,\n): number | undefined {\n const spec = getGeminiSpeechModelSpec(modelId);\n if (!spec) return undefined;\n\n // Use per-minute approximation\n if (spec.pricing.perMinute !== undefined) {\n if (estimatedMinutes !== undefined) {\n return estimatedMinutes * spec.pricing.perMinute;\n }\n // Fallback: rough estimate based on ~150 words/min, ~5 chars/word\n // ~750 chars/min of audio\n const approxMinutes = characterCount / 750;\n return approxMinutes * spec.pricing.perMinute;\n }\n\n return undefined;\n}\n","import { FunctionCallingConfigMode, GoogleGenAI, Modality } from \"@google/genai\";\nimport type { ContentPart } from \"../core/input-content.js\";\nimport type {\n ImageGenerationOptions,\n ImageGenerationResult,\n ImageModelSpec,\n SpeechGenerationOptions,\n SpeechGenerationResult,\n SpeechModelSpec,\n} from \"../core/media-types.js\";\nimport type { LLMMessage, MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, normalizeMessageContent } 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 {\n calculateGeminiImageCost,\n geminiImageModels,\n getGeminiImageModelSpec,\n isGeminiImageModel,\n} from \"./gemini-image-models.js\";\nimport { GEMINI_MODELS } from \"./gemini-models.js\";\nimport {\n calculateGeminiSpeechCost,\n geminiSpeechModels,\n getGeminiSpeechModelSpec,\n isGeminiSpeechModel,\n} from \"./gemini-speech-models.js\";\nimport { createProviderFromEnv } from \"./utils.js\";\n\n/**\n * Gemini content part - can be text or inline data (images/audio).\n */\ntype GeminiPart = { text: string } | { inlineData: { mimeType: string; data: string } };\n\n/**\n * Gemini content with role and multimodal parts.\n */\ntype GeminiContent = {\n role: string;\n parts: GeminiPart[];\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\n/**\n * Wraps raw PCM audio data in a WAV file container.\n *\n * WAV format structure:\n * - RIFF header (12 bytes)\n * - fmt chunk (24 bytes) - describes audio format\n * - data chunk (8 bytes + audio data)\n *\n * @param pcmData - Raw PCM audio samples\n * @param sampleRate - Sample rate in Hz (e.g., 24000)\n * @param bitsPerSample - Bits per sample (e.g., 16)\n * @param numChannels - Number of audio channels (1 = mono, 2 = stereo)\n * @returns ArrayBuffer containing valid WAV file\n */\nfunction wrapPcmInWav(\n pcmData: Uint8Array,\n sampleRate: number,\n bitsPerSample: number,\n numChannels: number,\n): ArrayBuffer {\n const byteRate = (sampleRate * numChannels * bitsPerSample) / 8;\n const blockAlign = (numChannels * bitsPerSample) / 8;\n const dataSize = pcmData.length;\n const headerSize = 44;\n const fileSize = headerSize + dataSize - 8; // File size minus RIFF header\n\n const buffer = new ArrayBuffer(headerSize + dataSize);\n const view = new DataView(buffer);\n const uint8 = new Uint8Array(buffer);\n\n // RIFF header\n view.setUint32(0, 0x52494646, false); // \"RIFF\"\n view.setUint32(4, fileSize, true); // File size - 8\n view.setUint32(8, 0x57415645, false); // \"WAVE\"\n\n // fmt chunk\n view.setUint32(12, 0x666d7420, false); // \"fmt \"\n view.setUint32(16, 16, true); // fmt chunk size (16 for PCM)\n view.setUint16(20, 1, true); // Audio format (1 = PCM)\n view.setUint16(22, numChannels, true); // Number of channels\n view.setUint32(24, sampleRate, true); // Sample rate\n view.setUint32(28, byteRate, true); // Byte rate\n view.setUint16(32, blockAlign, true); // Block align\n view.setUint16(34, bitsPerSample, true); // Bits per sample\n\n // data chunk\n view.setUint32(36, 0x64617461, false); // \"data\"\n view.setUint32(40, dataSize, true); // Data size\n\n // Copy PCM data\n uint8.set(pcmData, headerSize);\n\n return buffer;\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 // =========================================================================\n // Image Generation\n // =========================================================================\n\n getImageModelSpecs(): ImageModelSpec[] {\n return geminiImageModels;\n }\n\n supportsImageGeneration(modelId: string): boolean {\n return isGeminiImageModel(modelId);\n }\n\n async generateImage(options: ImageGenerationOptions): Promise<ImageGenerationResult> {\n const client = this.client as GoogleGenAI;\n const spec = getGeminiImageModelSpec(options.model);\n const isImagenModel = options.model.startsWith(\"imagen\");\n\n const aspectRatio = options.size ?? spec?.defaultSize ?? \"1:1\";\n const n = options.n ?? 1;\n\n if (isImagenModel) {\n // Use Imagen API for imagen models\n // Note: safetyFilterLevel and personGeneration can be configured for less restrictive filtering\n // Valid safetyFilterLevel values: \"BLOCK_NONE\" | \"BLOCK_ONLY_HIGH\" | \"BLOCK_MEDIUM_AND_ABOVE\" | \"BLOCK_LOW_AND_ABOVE\"\n // Valid personGeneration values: \"ALLOW_ALL\" | \"ALLOW_ADULT\" | \"DONT_ALLOW\"\n const response = await client.models.generateImages({\n model: options.model,\n prompt: options.prompt,\n config: {\n numberOfImages: n,\n aspectRatio: aspectRatio,\n outputMimeType: options.responseFormat === \"b64_json\" ? \"image/png\" : \"image/jpeg\",\n },\n });\n\n const images = response.generatedImages ?? [];\n const cost = calculateGeminiImageCost(options.model, aspectRatio, images.length);\n\n return {\n // Gemini's imageBytes is already base64 encoded, so use it directly\n images: images.map((img) => ({\n b64Json: img.image?.imageBytes ?? undefined,\n })),\n model: options.model,\n usage: {\n imagesGenerated: images.length,\n size: aspectRatio,\n quality: \"standard\",\n },\n cost,\n };\n }\n // Use native Gemini image generation for gemini-* models\n const response = await client.models.generateContent({\n model: options.model,\n contents: [{ role: \"user\", parts: [{ text: options.prompt }] }],\n config: {\n responseModalities: [Modality.IMAGE, Modality.TEXT],\n },\n });\n\n // Extract images from response\n const images: Array<{ b64Json?: string; url?: string }> = [];\n const candidate = response.candidates?.[0];\n if (candidate?.content?.parts) {\n for (const part of candidate.content.parts) {\n if (\"inlineData\" in part && part.inlineData) {\n images.push({\n b64Json: part.inlineData.data,\n });\n }\n }\n }\n\n const cost = calculateGeminiImageCost(options.model, aspectRatio, images.length);\n\n return {\n images,\n model: options.model,\n usage: {\n imagesGenerated: images.length,\n size: aspectRatio,\n quality: \"standard\",\n },\n cost,\n };\n }\n\n // =========================================================================\n // Speech Generation\n // =========================================================================\n\n getSpeechModelSpecs(): SpeechModelSpec[] {\n return geminiSpeechModels;\n }\n\n supportsSpeechGeneration(modelId: string): boolean {\n return isGeminiSpeechModel(modelId);\n }\n\n async generateSpeech(options: SpeechGenerationOptions): Promise<SpeechGenerationResult> {\n const client = this.client as GoogleGenAI;\n const spec = getGeminiSpeechModelSpec(options.model);\n\n const voice = options.voice ?? spec?.defaultVoice ?? \"Zephyr\";\n\n // Gemini TTS uses speech configuration\n const response = await client.models.generateContent({\n model: options.model,\n contents: [\n {\n role: \"user\",\n parts: [{ text: options.input }],\n },\n ],\n config: {\n responseModalities: [Modality.AUDIO],\n speechConfig: {\n voiceConfig: {\n prebuiltVoiceConfig: {\n voiceName: voice,\n },\n },\n },\n },\n });\n\n // Extract audio from response\n let pcmData: Uint8Array | undefined;\n const candidate = response.candidates?.[0];\n if (candidate?.content?.parts) {\n for (const part of candidate.content.parts) {\n if (\"inlineData\" in part && part.inlineData?.data) {\n // Convert base64 to Uint8Array\n const base64 = part.inlineData.data;\n const binary = atob(base64);\n pcmData = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n pcmData[i] = binary.charCodeAt(i);\n }\n break;\n }\n }\n }\n\n if (!pcmData) {\n throw new Error(\"No audio data in Gemini TTS response\");\n }\n\n // Wrap raw PCM data in WAV headers (Gemini returns 24kHz, 16-bit, mono PCM)\n const audioData = wrapPcmInWav(pcmData, 24000, 16, 1);\n\n const cost = calculateGeminiSpeechCost(options.model, options.input.length);\n\n return {\n audio: audioData,\n model: options.model,\n usage: {\n characterCount: options.input.length,\n },\n cost,\n format: spec?.defaultFormat ?? \"wav\",\n };\n }\n\n protected buildApiRequest(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n _spec: ModelSpec | undefined,\n messages: LLMMessage[],\n ): {\n model: string;\n contents: GeminiContent[];\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,\n config,\n };\n }\n\n protected async executeStreamRequest(\n payload: {\n model: string;\n contents: GeminiContent[];\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: Array<{ role: LLMMessage[\"role\"]; content: MessageContent }> = [];\n\n for (const message of messages) {\n if (message.role === \"system\") {\n // Convert system message to user+model exchange\n // System messages are always text-only\n expandedMessages.push({\n role: \"user\",\n content: extractMessageText(message.content),\n });\n expandedMessages.push({\n role: \"assistant\",\n content: \"Understood.\",\n });\n } else {\n expandedMessages.push({\n role: message.role,\n content: message.content,\n });\n }\n }\n\n return this.mergeConsecutiveMessages(expandedMessages);\n }\n\n /**\n * Merge consecutive messages with the same role (required by Gemini).\n * Handles multimodal content by converting to Gemini's part format.\n */\n private mergeConsecutiveMessages(\n messages: Array<{ role: LLMMessage[\"role\"]; content: MessageContent }>,\n ): 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 const geminiParts = this.convertToGeminiParts(message.content);\n\n if (currentGroup && currentGroup.role === geminiRole) {\n // Merge into current group\n currentGroup.parts.push(...geminiParts);\n } else {\n // Start new group\n if (currentGroup) {\n result.push(currentGroup);\n }\n currentGroup = {\n role: geminiRole,\n parts: geminiParts,\n };\n }\n }\n\n // Push the last group\n if (currentGroup) {\n result.push(currentGroup);\n }\n\n return result;\n }\n\n /**\n * Convert llmist content to Gemini's part format.\n * Handles text, images, and audio (Gemini supports all three).\n */\n private convertToGeminiParts(content: MessageContent): GeminiPart[] {\n const parts = normalizeMessageContent(content);\n\n return parts.map((part) => {\n if (part.type === \"text\") {\n return { text: part.text };\n }\n\n if (part.type === \"image\") {\n if (part.source.type === \"url\") {\n throw new Error(\n \"Gemini does not support image URLs directly. Please provide base64-encoded image data.\",\n );\n }\n return {\n inlineData: {\n mimeType: part.source.mediaType,\n data: part.source.data,\n },\n };\n }\n\n if (part.type === \"audio\") {\n return {\n inlineData: {\n mimeType: part.source.mediaType,\n data: part.source.data,\n },\n };\n }\n\n throw new Error(`Unsupported content type: ${(part as ContentPart).type}`);\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 *normalizeProviderStream(iterable: AsyncIterable<unknown>): LLMStream {\n const stream = iterable as AsyncIterable<GeminiChunk>;\n for await (const chunk of stream) {\n const text = this.extractMessageText(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 extractMessageText(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 // This now handles multimodal content\n const contents = this.convertMessagesToContents(messages);\n\n // Return 0 for empty messages - Gemini API requires non-empty contents\n if (!contents || contents.length === 0) {\n return 0;\n }\n\n try {\n // Use Gemini's count_tokens method\n const response = await client.models.countTokens({\n model: descriptor.name,\n 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 // For multimodal, extract text and estimate; images/audio add tokens\n let totalChars = 0;\n let mediaCount = 0;\n for (const msg of messages) {\n const parts = normalizeMessageContent(msg.content);\n for (const part of parts) {\n if (part.type === \"text\") {\n totalChars += part.text.length;\n } else if (part.type === \"image\" || part.type === \"audio\") {\n mediaCount++;\n }\n }\n }\n // Gemini charges ~258 tokens per image/audio (for standard size).\n // Source: https://ai.google.dev/gemini-api/docs/tokens\n // Actual cost varies by media type and dimensions.\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN) + mediaCount * 258;\n }\n }\n}\n\nexport function createGeminiProviderFromEnv(): GeminiGenerativeProvider | null {\n return createProviderFromEnv(\"GEMINI_API_KEY\", GoogleGenAI, GeminiGenerativeProvider);\n}\n","/**\n * OpenAI Image Generation Model Catalog\n *\n * Pricing as of December 2025:\n *\n * GPT Image 1.5 (flagship):\n * - Low quality: ~$0.008 per image\n * - Medium quality: ~$0.03 per image\n * - High quality: ~$0.13 per image\n *\n * GPT Image 1 (previous gen):\n * - Low quality: ~$0.011 per image\n * - Medium quality: ~$0.04 per image\n * - High quality: ~$0.17 per image\n *\n * GPT Image 1 Mini (cost-effective):\n * - Low quality: ~$0.005 per image\n * - Medium quality: ~$0.02 per image\n * - High quality: ~$0.052 per image\n *\n * Sora 2 (video generation):\n * - Standard quality: ~$0.50 per 5-second clip\n * - High quality: ~$1.00 per 5-second clip\n *\n * DALL-E 3 (deprecated):\n * - 1024x1024: $0.040 (standard), $0.080 (hd)\n * - 1024x1792: $0.080 (standard), $0.120 (hd)\n * - 1792x1024: $0.080 (standard), $0.120 (hd)\n *\n * DALL-E 2 (deprecated):\n * - 256x256: $0.016\n * - 512x512: $0.018\n * - 1024x1024: $0.020\n *\n * @see https://platform.openai.com/docs/guides/images\n */\n\nimport type { ImageModelSpec } from \"../core/media-types.js\";\n\n/** GPT Image supported sizes */\nexport const GPT_IMAGE_SIZES = [\"1024x1024\", \"1024x1536\", \"1536x1024\", \"1920x1080\", \"auto\"] as const;\nexport type GptImageSize = (typeof GPT_IMAGE_SIZES)[number];\n\n/** GPT Image quality levels */\nexport const GPT_IMAGE_QUALITIES = [\"low\", \"medium\", \"high\"] as const;\nexport type GptImageQuality = (typeof GPT_IMAGE_QUALITIES)[number];\n\n/** Sora video durations */\nexport const SORA_DURATIONS = [\"5s\", \"10s\", \"15s\", \"20s\"] as const;\nexport type SoraDuration = (typeof SORA_DURATIONS)[number];\n\n/** DALL-E 3 supported sizes (deprecated) */\nexport const DALLE3_SIZES = [\"1024x1024\", \"1024x1792\", \"1792x1024\"] as const;\nexport type DallE3Size = (typeof DALLE3_SIZES)[number];\n\n/** DALL-E 3 quality levels (deprecated) */\nexport const DALLE3_QUALITIES = [\"standard\", \"hd\"] as const;\nexport type DallE3Quality = (typeof DALLE3_QUALITIES)[number];\n\n/** DALL-E 2 supported sizes (deprecated) */\nexport const DALLE2_SIZES = [\"256x256\", \"512x512\", \"1024x1024\"] as const;\nexport type DallE2Size = (typeof DALLE2_SIZES)[number];\n\n/**\n * OpenAI Image Model Specifications\n */\nexport const openaiImageModels: ImageModelSpec[] = [\n // GPT Image 1.5 Family (flagship)\n {\n provider: \"openai\",\n modelId: \"gpt-image-1.5\",\n displayName: \"GPT Image 1.5\",\n pricing: {\n bySize: {\n \"1024x1024\": { low: 0.008, medium: 0.03, high: 0.13 },\n \"1024x1536\": { low: 0.012, medium: 0.045, high: 0.195 },\n \"1536x1024\": { low: 0.012, medium: 0.045, high: 0.195 },\n \"1920x1080\": { low: 0.016, medium: 0.06, high: 0.26 },\n },\n },\n supportedSizes: [...GPT_IMAGE_SIZES],\n supportedQualities: [...GPT_IMAGE_QUALITIES],\n maxImages: 1,\n defaultSize: \"1024x1024\",\n defaultQuality: \"medium\",\n features: {\n textRendering: true,\n transparency: true,\n editing: true,\n },\n },\n // GPT Image 1 Family (previous gen)\n {\n provider: \"openai\",\n modelId: \"gpt-image-1\",\n displayName: \"GPT Image 1\",\n pricing: {\n bySize: {\n \"1024x1024\": { low: 0.011, medium: 0.04, high: 0.17 },\n \"1024x1536\": { low: 0.016, medium: 0.06, high: 0.25 },\n \"1536x1024\": { low: 0.016, medium: 0.06, high: 0.25 },\n },\n },\n supportedSizes: [\"1024x1024\", \"1024x1536\", \"1536x1024\"],\n supportedQualities: [...GPT_IMAGE_QUALITIES],\n maxImages: 1,\n defaultSize: \"1024x1024\",\n defaultQuality: \"medium\",\n features: {\n textRendering: true,\n transparency: true,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-image-1-mini\",\n displayName: \"GPT Image 1 Mini\",\n pricing: {\n bySize: {\n \"1024x1024\": { low: 0.005, medium: 0.02, high: 0.052 },\n \"1024x1536\": { low: 0.0075, medium: 0.03, high: 0.078 },\n \"1536x1024\": { low: 0.0075, medium: 0.03, high: 0.078 },\n },\n },\n supportedSizes: [\"1024x1024\", \"1024x1536\", \"1536x1024\"],\n supportedQualities: [...GPT_IMAGE_QUALITIES],\n maxImages: 1,\n defaultSize: \"1024x1024\",\n defaultQuality: \"medium\",\n features: {\n textRendering: true,\n transparency: true,\n },\n },\n // Sora Video Generation Models\n {\n provider: \"openai\",\n modelId: \"sora-2\",\n displayName: \"Sora 2\",\n pricing: {\n bySize: {\n \"1920x1080\": { standard: 0.5, high: 1.0 },\n \"1080x1920\": { standard: 0.5, high: 1.0 },\n \"1024x1024\": { standard: 0.4, high: 0.8 },\n },\n },\n supportedSizes: [\"1920x1080\", \"1080x1920\", \"1024x1024\"],\n supportedQualities: [\"standard\", \"high\"],\n maxImages: 1,\n defaultSize: \"1920x1080\",\n defaultQuality: \"standard\",\n features: {\n videoGeneration: true,\n },\n },\n {\n provider: \"openai\",\n modelId: \"sora-2-pro\",\n displayName: \"Sora 2 Pro\",\n pricing: {\n bySize: {\n \"1920x1080\": { standard: 1.0, high: 2.0 },\n \"1080x1920\": { standard: 1.0, high: 2.0 },\n \"1024x1024\": { standard: 0.8, high: 1.6 },\n },\n },\n supportedSizes: [\"1920x1080\", \"1080x1920\", \"1024x1024\"],\n supportedQualities: [\"standard\", \"high\"],\n maxImages: 1,\n defaultSize: \"1920x1080\",\n defaultQuality: \"standard\",\n features: {\n videoGeneration: true,\n extendedDuration: true,\n },\n },\n // DALL-E Family (deprecated - use GPT Image models instead)\n {\n provider: \"openai\",\n modelId: \"dall-e-3\",\n displayName: \"DALL-E 3 (Deprecated)\",\n pricing: {\n bySize: {\n \"1024x1024\": { standard: 0.04, hd: 0.08 },\n \"1024x1792\": { standard: 0.08, hd: 0.12 },\n \"1792x1024\": { standard: 0.08, hd: 0.12 },\n },\n },\n supportedSizes: [...DALLE3_SIZES],\n supportedQualities: [...DALLE3_QUALITIES],\n maxImages: 1, // DALL-E 3 only supports n=1\n defaultSize: \"1024x1024\",\n defaultQuality: \"standard\",\n features: {\n textRendering: true,\n },\n },\n {\n provider: \"openai\",\n modelId: \"dall-e-2\",\n displayName: \"DALL-E 2 (Deprecated)\",\n pricing: {\n bySize: {\n \"256x256\": 0.016,\n \"512x512\": 0.018,\n \"1024x1024\": 0.02,\n },\n },\n supportedSizes: [...DALLE2_SIZES],\n maxImages: 10,\n defaultSize: \"1024x1024\",\n },\n];\n\n/**\n * Get image model spec by model ID.\n */\nexport function getOpenAIImageModelSpec(modelId: string): ImageModelSpec | undefined {\n return openaiImageModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is an OpenAI image model.\n */\nexport function isOpenAIImageModel(modelId: string): boolean {\n return openaiImageModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for image generation.\n *\n * @param modelId - The model ID (dall-e-3 or dall-e-2)\n * @param size - Image size\n * @param quality - Quality level (for DALL-E 3)\n * @param n - Number of images\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateOpenAIImageCost(\n modelId: string,\n size: string,\n quality = \"standard\",\n n = 1,\n): number | undefined {\n const spec = getOpenAIImageModelSpec(modelId);\n if (!spec) return undefined;\n\n // Get price for this size\n const sizePrice = spec.pricing.bySize?.[size];\n if (sizePrice === undefined) return undefined;\n\n let pricePerImage: number;\n\n if (typeof sizePrice === \"number\") {\n // Flat pricing (DALL-E 2)\n pricePerImage = sizePrice;\n } else {\n // Quality-based pricing (DALL-E 3)\n pricePerImage = sizePrice[quality];\n if (pricePerImage === undefined) return undefined;\n }\n\n return pricePerImage * n;\n}\n","/**\n * OpenAI Model Specifications\n *\n * Model data for OpenAI models including GPT-5.2, GPT-5.1, 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-12-20\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const OPENAI_MODELS: ModelSpec[] = [\n // GPT-5.2 Family (Latest flagship)\n {\n provider: \"openai\",\n modelId: \"gpt-5.2\",\n displayName: \"GPT-5.2\",\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n pricing: {\n input: 1.25,\n output: 10.0,\n cachedInput: 0.125,\n },\n knowledgeCutoff: \"2025-03-31\",\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.2\",\n releaseDate: \"2025-12-01\",\n notes: \"Latest flagship model with 1M context window and enhanced reasoning.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5.2-pro\",\n displayName: \"GPT-5.2 Pro\",\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n pricing: {\n input: 15.0,\n output: 120.0,\n },\n knowledgeCutoff: \"2025-03-31\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"GPT-5.2\",\n releaseDate: \"2025-12-01\",\n notes: \"Premium tier GPT-5.2 with enhanced reasoning. Does not support prompt caching.\",\n supportsTemperature: false,\n },\n },\n\n // GPT-5.1 Family\n {\n provider: \"openai\",\n modelId: \"gpt-5.1\",\n displayName: \"GPT-5.1\",\n contextWindow: 1_000_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.1\",\n releaseDate: \"2025-11-12\",\n notes: \"GPT-5 variant with improved instruction following. 2-3x faster than GPT-5.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5.1-codex\",\n displayName: \"GPT-5.1 Codex\",\n contextWindow: 1_000_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 },\n metadata: {\n family: \"GPT-5.1\",\n notes: \"GPT-5.1 variant optimized for code generation and analysis.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5.1-codex-max\",\n displayName: \"GPT-5.1 Codex Max\",\n contextWindow: 1_000_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 },\n metadata: {\n family: \"GPT-5.1\",\n notes: \"Extended thinking variant of GPT-5.1 Codex for complex code tasks.\",\n supportsTemperature: false,\n },\n },\n\n // GPT-5 Family\n {\n provider: \"openai\",\n modelId: \"gpt-5\",\n displayName: \"GPT-5\",\n contextWindow: 1_000_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: \"High-capability model for coding and agentic tasks. 90% caching discount.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5-codex\",\n displayName: \"GPT-5 Codex\",\n contextWindow: 1_000_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 },\n metadata: {\n family: \"GPT-5\",\n notes: \"GPT-5 variant optimized for code generation and analysis.\",\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: \"o1-pro\",\n displayName: \"o1 Pro\",\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n pricing: {\n input: 150.0,\n output: 600.0,\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: \"Premium tier o1 with extended reasoning. Does not support prompt caching.\",\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","/**\n * OpenAI Speech (TTS) Model Catalog\n *\n * Pricing as of December 2025:\n * - tts-1: $15.00 per 1M characters\n * - tts-1-hd: $30.00 per 1M characters\n * - gpt-4o-mini-tts: $0.60/1M input tokens + $12/1M audio output tokens (~$0.015/min)\n *\n * @see https://platform.openai.com/docs/guides/text-to-speech\n */\n\nimport type { AudioFormat, SpeechModelSpec } from \"../core/media-types.js\";\n\n/** OpenAI TTS voices for standard models (tts-1, tts-1-hd) */\nexport const OPENAI_TTS_VOICES = [\"alloy\", \"echo\", \"fable\", \"onyx\", \"nova\", \"shimmer\"] as const;\n\n/** Additional voices available in gpt-4o-mini-tts */\nexport const OPENAI_TTS_EXTENDED_VOICES = [\n ...OPENAI_TTS_VOICES,\n \"ash\",\n \"ballad\",\n \"coral\",\n \"sage\",\n \"verse\",\n] as const;\n\nexport type OpenAITTSVoice = (typeof OPENAI_TTS_VOICES)[number];\nexport type OpenAITTSExtendedVoice = (typeof OPENAI_TTS_EXTENDED_VOICES)[number];\n\n/** OpenAI supported audio formats */\nexport const OPENAI_TTS_FORMATS: AudioFormat[] = [\"mp3\", \"opus\", \"aac\", \"flac\", \"wav\", \"pcm\"];\n\n/**\n * OpenAI Speech Model Specifications\n */\nexport const openaiSpeechModels: SpeechModelSpec[] = [\n // Standard TTS models (character-based pricing)\n {\n provider: \"openai\",\n modelId: \"tts-1\",\n displayName: \"TTS-1\",\n pricing: {\n // $15 per 1M characters = $0.000015 per character\n perCharacter: 0.000015,\n },\n voices: [...OPENAI_TTS_VOICES],\n formats: OPENAI_TTS_FORMATS,\n maxInputLength: 4096,\n defaultVoice: \"alloy\",\n defaultFormat: \"mp3\",\n features: {\n voiceInstructions: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"tts-1-1106\",\n displayName: \"TTS-1 (Nov 2023)\",\n pricing: {\n perCharacter: 0.000015,\n },\n voices: [...OPENAI_TTS_VOICES],\n formats: OPENAI_TTS_FORMATS,\n maxInputLength: 4096,\n defaultVoice: \"alloy\",\n defaultFormat: \"mp3\",\n features: {\n voiceInstructions: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"tts-1-hd\",\n displayName: \"TTS-1 HD\",\n pricing: {\n // $30 per 1M characters = $0.00003 per character\n perCharacter: 0.00003,\n },\n voices: [...OPENAI_TTS_VOICES],\n formats: OPENAI_TTS_FORMATS,\n maxInputLength: 4096,\n defaultVoice: \"alloy\",\n defaultFormat: \"mp3\",\n features: {\n voiceInstructions: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"tts-1-hd-1106\",\n displayName: \"TTS-1 HD (Nov 2023)\",\n pricing: {\n perCharacter: 0.00003,\n },\n voices: [...OPENAI_TTS_VOICES],\n formats: OPENAI_TTS_FORMATS,\n maxInputLength: 4096,\n defaultVoice: \"alloy\",\n defaultFormat: \"mp3\",\n features: {\n voiceInstructions: false,\n },\n },\n // Token-based TTS model with voice instructions support\n {\n provider: \"openai\",\n modelId: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o Mini TTS\",\n pricing: {\n // $0.60 per 1M input tokens = $0.0000006 per token\n perInputToken: 0.0000006,\n // $12 per 1M audio output tokens = $0.000012 per token\n perAudioOutputToken: 0.000012,\n // ~$0.015 per minute of audio\n perMinute: 0.015,\n },\n voices: [...OPENAI_TTS_EXTENDED_VOICES],\n formats: OPENAI_TTS_FORMATS,\n maxInputLength: 2000, // tokens, not characters\n defaultVoice: \"alloy\",\n defaultFormat: \"mp3\",\n features: {\n voiceInstructions: true,\n },\n },\n];\n\n/**\n * Get speech model spec by model ID.\n */\nexport function getOpenAISpeechModelSpec(modelId: string): SpeechModelSpec | undefined {\n return openaiSpeechModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is an OpenAI speech model.\n */\nexport function isOpenAISpeechModel(modelId: string): boolean {\n return openaiSpeechModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for speech generation.\n *\n * For character-based models (tts-1, tts-1-hd): cost = characters * perCharacter\n * For token-based models (gpt-4o-mini-tts): uses perMinute approximation\n *\n * @param modelId - The model ID\n * @param characterCount - Number of characters in the input\n * @param estimatedMinutes - Optional: estimated audio duration for token-based models\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateOpenAISpeechCost(\n modelId: string,\n characterCount: number,\n estimatedMinutes?: number,\n): number | undefined {\n const spec = getOpenAISpeechModelSpec(modelId);\n if (!spec) return undefined;\n\n // Character-based pricing (tts-1, tts-1-hd)\n if (spec.pricing.perCharacter !== undefined) {\n return characterCount * spec.pricing.perCharacter;\n }\n\n // Token-based pricing (gpt-4o-mini-tts) - use per-minute approximation\n if (spec.pricing.perMinute !== undefined && estimatedMinutes !== undefined) {\n return estimatedMinutes * spec.pricing.perMinute;\n }\n\n // Fallback: rough estimate based on ~150 words/min, ~5 chars/word\n // ~750 chars/min of audio\n if (spec.pricing.perMinute !== undefined) {\n const approxMinutes = characterCount / 750;\n return approxMinutes * spec.pricing.perMinute;\n }\n\n return undefined;\n}\n","import OpenAI from \"openai\";\nimport type {\n ChatCompletionChunk,\n ChatCompletionContentPart,\n ChatCompletionMessageParam,\n} from \"openai/resources/chat/completions\";\nimport { encoding_for_model, type TiktokenModel } from \"tiktoken\";\nimport type { ContentPart, ImageContentPart } from \"../core/input-content.js\";\nimport type {\n ImageGenerationOptions,\n ImageGenerationResult,\n ImageModelSpec,\n SpeechGenerationOptions,\n SpeechGenerationResult,\n SpeechModelSpec,\n} from \"../core/media-types.js\";\nimport type { LLMMessage, MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, normalizeMessageContent } 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 {\n calculateOpenAIImageCost,\n getOpenAIImageModelSpec,\n isOpenAIImageModel,\n openaiImageModels,\n} from \"./openai-image-models.js\";\nimport { OPENAI_MODELS } from \"./openai-models.js\";\nimport {\n calculateOpenAISpeechCost,\n getOpenAISpeechModelSpec,\n isOpenAISpeechModel,\n openaiSpeechModels,\n} from \"./openai-speech-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 // =========================================================================\n // Image Generation\n // =========================================================================\n\n getImageModelSpecs(): ImageModelSpec[] {\n return openaiImageModels;\n }\n\n supportsImageGeneration(modelId: string): boolean {\n return isOpenAIImageModel(modelId);\n }\n\n async generateImage(options: ImageGenerationOptions): Promise<ImageGenerationResult> {\n const client = this.client as OpenAI;\n const spec = getOpenAIImageModelSpec(options.model);\n\n const size = options.size ?? spec?.defaultSize ?? \"1024x1024\";\n const quality = options.quality ?? spec?.defaultQuality ?? \"standard\";\n const n = options.n ?? 1;\n\n // Determine which parameters to include based on model capabilities\n const isDallE2 = options.model === \"dall-e-2\";\n const isGptImage = options.model.startsWith(\"gpt-image\");\n\n // Build request payload conditionally\n // - DALL-E 2: no quality parameter, no response_format\n // - GPT Image: quality uses low/medium/high, no response_format (uses output_format)\n // - DALL-E 3: supports quality (standard/hd) and response_format\n const requestParams: Parameters<typeof client.images.generate>[0] = {\n model: options.model,\n prompt: options.prompt,\n size: size as \"1024x1024\" | \"1024x1792\" | \"1792x1024\" | \"256x256\" | \"512x512\",\n n,\n };\n\n // Only DALL-E 3 supports the quality parameter with standard/hd values\n if (!isDallE2 && !isGptImage) {\n requestParams.quality = quality as \"standard\" | \"hd\";\n }\n\n // GPT Image models use output_format instead of response_format\n if (isGptImage) {\n // GPT Image supports: png, webp, jpeg\n // Map b64_json to the default format (png) since GPT Image API is different\n // For now, we'll always return URLs for GPT Image models\n // Note: GPT Image API uses different response structure\n } else if (!isDallE2) {\n // DALL-E 3 supports response_format\n requestParams.response_format = options.responseFormat ?? \"url\";\n }\n\n const response = await client.images.generate(requestParams);\n\n const cost = calculateOpenAIImageCost(options.model, size, quality, n);\n // Type assertion: we're not using streaming, so response is ImagesResponse\n const images = (response as OpenAI.Images.ImagesResponse).data ?? [];\n\n return {\n images: images.map((img) => ({\n url: img.url,\n b64Json: img.b64_json,\n revisedPrompt: img.revised_prompt,\n })),\n model: options.model,\n usage: {\n imagesGenerated: images.length,\n size,\n quality,\n },\n cost,\n };\n }\n\n // =========================================================================\n // Speech Generation\n // =========================================================================\n\n getSpeechModelSpecs(): SpeechModelSpec[] {\n return openaiSpeechModels;\n }\n\n supportsSpeechGeneration(modelId: string): boolean {\n return isOpenAISpeechModel(modelId);\n }\n\n async generateSpeech(options: SpeechGenerationOptions): Promise<SpeechGenerationResult> {\n const client = this.client as OpenAI;\n const spec = getOpenAISpeechModelSpec(options.model);\n\n const format = options.responseFormat ?? spec?.defaultFormat ?? \"mp3\";\n const voice = options.voice ?? spec?.defaultVoice ?? \"alloy\";\n\n const response = await client.audio.speech.create({\n model: options.model,\n input: options.input,\n voice: voice as \"alloy\" | \"echo\" | \"fable\" | \"onyx\" | \"nova\" | \"shimmer\",\n response_format: format,\n speed: options.speed ?? 1.0,\n });\n\n const audioBuffer = await response.arrayBuffer();\n const cost = calculateOpenAISpeechCost(options.model, options.input.length);\n\n return {\n audio: audioBuffer,\n model: options.model,\n usage: {\n characterCount: options.input.length,\n },\n cost,\n format,\n };\n }\n\n protected buildApiRequest(\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) => this.convertToOpenAIMessage(message)),\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 /**\n * Convert an LLMMessage to OpenAI's ChatCompletionMessageParam.\n * Handles role-specific content type requirements:\n * - system/assistant: string content only\n * - user: string or multimodal array content\n */\n private convertToOpenAIMessage(message: LLMMessage): ChatCompletionMessageParam {\n const role = ROLE_MAP[message.role];\n\n // User messages support multimodal content\n if (role === \"user\") {\n const content = this.convertToOpenAIContent(message.content);\n return {\n role: \"user\",\n content,\n ...(message.name ? { name: message.name } : {}),\n };\n }\n\n // System and assistant messages only support string content\n const textContent =\n typeof message.content === \"string\" ? message.content : extractMessageText(message.content);\n\n if (role === \"system\") {\n return {\n role: \"system\",\n content: textContent,\n ...(message.name ? { name: message.name } : {}),\n };\n }\n\n // Assistant role\n return {\n role: \"assistant\",\n content: textContent,\n ...(message.name ? { name: message.name } : {}),\n };\n }\n\n /**\n * Convert llmist content to OpenAI's content format.\n * Optimizes by returning string for text-only content, array for multimodal.\n */\n private convertToOpenAIContent(content: MessageContent): string | ChatCompletionContentPart[] {\n // Optimization: keep simple string content as-is\n if (typeof content === \"string\") {\n return content;\n }\n\n // Convert array content to OpenAI format\n return content.map((part) => {\n if (part.type === \"text\") {\n return { type: \"text\" as const, text: part.text };\n }\n\n if (part.type === \"image\") {\n return this.convertImagePart(part);\n }\n\n if (part.type === \"audio\") {\n throw new Error(\n \"OpenAI chat completions do not support audio input. Use Whisper for transcription or Gemini for audio understanding.\",\n );\n }\n\n throw new Error(`Unsupported content type: ${(part as ContentPart).type}`);\n });\n }\n\n /**\n * Convert an image content part to OpenAI's image_url format.\n * Supports both URLs and base64 data URLs.\n */\n private convertImagePart(part: ImageContentPart): ChatCompletionContentPart {\n if (part.source.type === \"url\") {\n return {\n type: \"image_url\" as const,\n image_url: { url: part.source.url },\n };\n }\n\n // Convert base64 to data URL format\n return {\n type: \"image_url\" as const,\n image_url: {\n url: `data:${part.source.mediaType};base64,${part.source.data}`,\n },\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 *normalizeProviderStream(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 let imageCount = 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\n // Handle multimodal content\n const textContent = extractMessageText(message.content);\n tokenCount += encoding.encode(textContent).length;\n\n // Count images for estimation (each image ~85 tokens base + variable)\n const parts = normalizeMessageContent(message.content);\n for (const part of parts) {\n if (part.type === \"image\") {\n imageCount++;\n }\n }\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 // Add ~765 tokens per image (low detail mode).\n // Source: https://platform.openai.com/docs/guides/vision\n // High detail mode varies by image size (510-1105 tokens per 512px tile + 85 base).\n tokenCount += imageCount * 765;\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 let totalChars = 0;\n let imageCount = 0;\n for (const msg of messages) {\n const parts = normalizeMessageContent(msg.content);\n for (const part of parts) {\n if (part.type === \"text\") {\n totalChars += part.text.length;\n } else if (part.type === \"image\") {\n imageCount++;\n }\n }\n }\n // Use same image token estimate as tiktoken path (765 tokens per image).\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN) + imageCount * 765;\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, optionally with provider prefix\n * (e.g., 'gpt-5', 'claude-sonnet-4-5-20250929', 'anthropic:claude-sonnet-4-5')\n * @returns ModelSpec if found, undefined otherwise\n */\n getModelSpec(modelId: string): ModelSpec | undefined {\n // Support provider-prefixed model IDs (e.g., \"anthropic:claude-sonnet-4-5\")\n // Strip the prefix to match against the registry's model IDs\n const normalizedId = modelId.includes(\":\") ? modelId.split(\":\")[1] : modelId;\n return this.modelSpecs.find((model) => model.modelId === normalizedId);\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","/**\n * Image Generation Namespace\n *\n * Provides image generation methods.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * const result = await llmist.image.generate({\n * model: \"dall-e-3\",\n * prompt: \"A cat in space\",\n * size: \"1024x1024\",\n * quality: \"hd\",\n * });\n *\n * console.log(result.images[0].url);\n * console.log(\"Cost:\", result.cost);\n * ```\n */\n\nimport type { ProviderAdapter } from \"../../providers/provider.js\";\nimport type {\n ImageGenerationOptions,\n ImageGenerationResult,\n ImageModelSpec,\n} from \"../media-types.js\";\n\nexport class ImageNamespace {\n constructor(\n private readonly adapters: ProviderAdapter[],\n private readonly defaultProvider: string,\n ) {}\n\n /**\n * Generate images from a text prompt.\n *\n * @param options - Image generation options\n * @returns Promise resolving to the generation result with images and cost\n * @throws Error if the provider doesn't support image generation\n */\n async generate(options: ImageGenerationOptions): Promise<ImageGenerationResult> {\n const modelId = options.model;\n\n // Find an adapter that supports this image model\n const adapter = this.findImageAdapter(modelId);\n if (!adapter || !adapter.generateImage) {\n throw new Error(\n `No provider supports image generation for model \"${modelId}\". ` +\n `Available image models: ${this.listModels()\n .map((m) => m.modelId)\n .join(\", \")}`,\n );\n }\n\n return adapter.generateImage(options);\n }\n\n /**\n * List all available image generation models.\n */\n listModels(): ImageModelSpec[] {\n const models: ImageModelSpec[] = [];\n for (const adapter of this.adapters) {\n if (adapter.getImageModelSpecs) {\n models.push(...adapter.getImageModelSpecs());\n }\n }\n return models;\n }\n\n /**\n * Check if a model is supported for image generation.\n */\n supportsModel(modelId: string): boolean {\n return this.findImageAdapter(modelId) !== undefined;\n }\n\n private findImageAdapter(modelId: string): ProviderAdapter | undefined {\n return this.adapters.find((adapter) => adapter.supportsImageGeneration?.(modelId) ?? false);\n }\n}\n","/**\n * Speech Generation Namespace\n *\n * Provides text-to-speech generation methods.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * const result = await llmist.speech.generate({\n * model: \"tts-1-hd\",\n * input: \"Hello, world!\",\n * voice: \"nova\",\n * });\n *\n * // Save the audio\n * fs.writeFileSync(\"output.mp3\", Buffer.from(result.audio));\n * console.log(\"Cost:\", result.cost);\n * ```\n */\n\nimport type { ProviderAdapter } from \"../../providers/provider.js\";\nimport type {\n SpeechGenerationOptions,\n SpeechGenerationResult,\n SpeechModelSpec,\n} from \"../media-types.js\";\n\nexport class SpeechNamespace {\n constructor(\n private readonly adapters: ProviderAdapter[],\n private readonly defaultProvider: string,\n ) {}\n\n /**\n * Generate speech audio from text.\n *\n * @param options - Speech generation options\n * @returns Promise resolving to the generation result with audio and cost\n * @throws Error if the provider doesn't support speech generation\n */\n async generate(options: SpeechGenerationOptions): Promise<SpeechGenerationResult> {\n const modelId = options.model;\n\n // Find an adapter that supports this speech model\n const adapter = this.findSpeechAdapter(modelId);\n if (!adapter || !adapter.generateSpeech) {\n throw new Error(\n `No provider supports speech generation for model \"${modelId}\". ` +\n `Available speech models: ${this.listModels()\n .map((m) => m.modelId)\n .join(\", \")}`,\n );\n }\n\n return adapter.generateSpeech(options);\n }\n\n /**\n * List all available speech generation models.\n */\n listModels(): SpeechModelSpec[] {\n const models: SpeechModelSpec[] = [];\n for (const adapter of this.adapters) {\n if (adapter.getSpeechModelSpecs) {\n models.push(...adapter.getSpeechModelSpecs());\n }\n }\n return models;\n }\n\n /**\n * Check if a model is supported for speech generation.\n */\n supportsModel(modelId: string): boolean {\n return this.findSpeechAdapter(modelId) !== undefined;\n }\n\n private findSpeechAdapter(modelId: string): ProviderAdapter | undefined {\n return this.adapters.find((adapter) => adapter.supportsSpeechGeneration?.(modelId) ?? false);\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 text generation methods (complete/stream).\n */\nexport interface TextGenerationOptions {\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: TextGenerationOptions = {},\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: TextGenerationOptions = {},\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","/**\n * Text Generation Namespace\n *\n * Provides text completion and streaming methods.\n * Replaces the deprecated llmist.complete() and llmist.stream() methods.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * // Complete\n * const answer = await llmist.text.complete(\"What is 2+2?\");\n *\n * // Stream\n * for await (const chunk of llmist.text.stream(\"Tell me a story\")) {\n * process.stdout.write(chunk);\n * }\n * ```\n */\n\nimport type { LLMist } from \"../client.js\";\nimport { complete, type TextGenerationOptions, stream } from \"../quick-methods.js\";\n\nexport class TextNamespace {\n constructor(private readonly client: LLMist) {}\n\n /**\n * Generate a complete text response.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Complete text response\n */\n async complete(prompt: string, options?: TextGenerationOptions): Promise<string> {\n return complete(this.client, prompt, options);\n }\n\n /**\n * Stream text chunks.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Async generator yielding text chunks\n */\n stream(prompt: string, options?: TextGenerationOptions): AsyncGenerator<string> {\n return stream(this.client, prompt, options);\n }\n}\n","/**\n * Vision Analysis Namespace\n *\n * Provides one-shot image analysis without agent setup.\n * Useful for quick image understanding tasks.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * const description = await llmist.vision.analyze({\n * model: \"gpt-4o\",\n * image: await readFile(\"photo.jpg\"),\n * prompt: \"Describe this image in detail\",\n * });\n *\n * console.log(description);\n * ```\n */\n\nimport type { LLMist } from \"../client.js\";\nimport type { ImageMimeType } from \"../input-content.js\";\nimport {\n detectImageMimeType,\n imageFromBuffer,\n imageFromUrl,\n isDataUrl,\n parseDataUrl,\n text,\n} from \"../input-content.js\";\nimport { LLMMessageBuilder } from \"../messages.js\";\n\n/**\n * Options for vision analysis.\n */\nexport interface VisionAnalyzeOptions {\n /** Model to use (must support vision, e.g., \"gpt-4o\", \"claude-sonnet-4-20250514\", \"gemini-2.5-flash\") */\n model: string;\n\n /** Image data: Buffer, Uint8Array, base64 string, data URL, or HTTPS URL */\n image: string | Buffer | Uint8Array;\n\n /** Analysis prompt describing what to do with the image */\n prompt: string;\n\n /** MIME type (auto-detected if not provided for Buffer/Uint8Array) */\n mimeType?: ImageMimeType;\n\n /** System prompt for analysis context */\n systemPrompt?: string;\n\n /** Max tokens for response */\n maxTokens?: number;\n\n /** Temperature (0-1) */\n temperature?: number;\n}\n\n/**\n * Result of vision analysis.\n */\nexport interface VisionAnalyzeResult {\n /** The analysis text */\n text: string;\n\n /** Model used */\n model: string;\n\n /** Token usage if available */\n usage?: {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n };\n}\n\nexport class VisionNamespace {\n constructor(private readonly client: LLMist) {}\n\n /**\n * Build a message builder with the image content attached.\n * Handles URLs, data URLs, base64 strings, and binary buffers.\n */\n private buildImageMessage(options: VisionAnalyzeOptions): LLMMessageBuilder {\n const builder = new LLMMessageBuilder();\n\n if (options.systemPrompt) {\n builder.addSystem(options.systemPrompt);\n }\n\n // Handle different image source types\n if (typeof options.image === \"string\") {\n if (options.image.startsWith(\"http://\") || options.image.startsWith(\"https://\")) {\n // URL - only supported by OpenAI\n builder.addUserWithImageUrl(options.prompt, options.image);\n } else if (isDataUrl(options.image)) {\n // Data URL - parse and use\n const parsed = parseDataUrl(options.image);\n if (!parsed) {\n throw new Error(\"Invalid data URL format\");\n }\n builder.addUserWithImage(options.prompt, parsed.data, parsed.mimeType as ImageMimeType);\n } else {\n // Assume base64 string\n const buffer = Buffer.from(options.image, \"base64\");\n builder.addUserWithImage(options.prompt, buffer, options.mimeType);\n }\n } else {\n // Buffer or Uint8Array\n builder.addUserWithImage(options.prompt, options.image, options.mimeType);\n }\n\n return builder;\n }\n\n /**\n * Stream the response and collect text and usage information.\n */\n private async streamAndCollect(\n options: VisionAnalyzeOptions,\n builder: LLMMessageBuilder,\n ): Promise<{ text: string; usage?: VisionAnalyzeResult[\"usage\"] }> {\n let response = \"\";\n let finalUsage: VisionAnalyzeResult[\"usage\"] | undefined;\n\n for await (const chunk of this.client.stream({\n model: options.model,\n messages: builder.build(),\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n })) {\n response += chunk.text;\n if (chunk.usage) {\n finalUsage = {\n inputTokens: chunk.usage.inputTokens,\n outputTokens: chunk.usage.outputTokens,\n totalTokens: chunk.usage.totalTokens,\n };\n }\n }\n\n return { text: response.trim(), usage: finalUsage };\n }\n\n /**\n * Analyze an image with a vision-capable model.\n * Returns the analysis as a string.\n *\n * @param options - Vision analysis options\n * @returns Promise resolving to the analysis text\n * @throws Error if the image format is unsupported or model doesn't support vision\n *\n * @example\n * ```typescript\n * // From file\n * const result = await llmist.vision.analyze({\n * model: \"gpt-4o\",\n * image: await fs.readFile(\"photo.jpg\"),\n * prompt: \"What's in this image?\",\n * });\n *\n * // From URL (OpenAI only)\n * const result = await llmist.vision.analyze({\n * model: \"gpt-4o\",\n * image: \"https://example.com/image.jpg\",\n * prompt: \"Describe this image\",\n * });\n * ```\n */\n async analyze(options: VisionAnalyzeOptions): Promise<string> {\n const builder = this.buildImageMessage(options);\n const { text } = await this.streamAndCollect(options, builder);\n return text;\n }\n\n /**\n * Analyze an image and return detailed result with usage info.\n *\n * @param options - Vision analysis options\n * @returns Promise resolving to the analysis result with usage info\n */\n async analyzeWithUsage(options: VisionAnalyzeOptions): Promise<VisionAnalyzeResult> {\n const builder = this.buildImageMessage(options);\n const { text, usage } = await this.streamAndCollect(options, builder);\n\n return {\n text,\n model: options.model,\n usage,\n };\n }\n\n /**\n * Check if a model supports vision/image input.\n *\n * @param modelId - Model ID to check\n * @returns True if the model supports vision\n */\n supportsModel(modelId: string): boolean {\n const spec = this.client.modelRegistry.getModelSpec(modelId);\n return spec?.features?.vision === true;\n }\n\n /**\n * List all models that support vision.\n *\n * @returns Array of model IDs that support vision\n */\n listModels(): string[] {\n return this.client.modelRegistry\n .listModels()\n .filter((spec) => spec.features?.vision === true)\n .map((spec) => spec.modelId);\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","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 { ImageNamespace } from \"./namespaces/image.js\";\nimport { SpeechNamespace } from \"./namespaces/speech.js\";\nimport { TextNamespace } from \"./namespaces/text.js\";\nimport { VisionNamespace } from \"./namespaces/vision.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"./options.js\";\nimport { ModelIdentifierParser } from \"./options.js\";\nimport {\n complete as completeHelper,\n type TextGenerationOptions,\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 private readonly defaultProvider: string;\n readonly modelRegistry: ModelRegistry;\n private readonly adapters: ProviderAdapter[];\n\n // Namespaces for different generation types\n readonly text: TextNamespace;\n readonly image: ImageNamespace;\n readonly speech: SpeechNamespace;\n readonly vision: VisionNamespace;\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.defaultProvider = resolvedDefaultProvider;\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 // Initialize generation namespaces\n this.text = new TextNamespace(this);\n this.image = new ImageNamespace(this.adapters, this.defaultProvider);\n this.speech = new SpeechNamespace(this.adapters, this.defaultProvider);\n this.vision = new VisionNamespace(this);\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?: TextGenerationOptions): 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?: TextGenerationOptions): 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?: TextGenerationOptions): 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?: TextGenerationOptions): 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","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(schema: ZodTypeAny): 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\") 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 ? new SchemaIntrospector(options.schema) : 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(value: string, expectedType?: TypeHint): 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","/**\n * LLMist client wrapper that automatically reports LLM costs via callback.\n *\n * Used internally by ExecutionContext to provide ctx.llmist for gadgets.\n * All LLM calls made through this wrapper will have their costs automatically\n * tracked and reported via the provided callback.\n *\n * @module gadgets/cost-reporting-client\n */\n\nimport type { LLMist } from \"../core/client.js\";\nimport type {\n ImageGenerationOptions,\n ImageGenerationResult,\n SpeechGenerationOptions,\n SpeechGenerationResult,\n} from \"../core/media-types.js\";\nimport type { ModelRegistry } from \"../core/model-registry.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { LLMGenerationOptions, LLMStream, LLMStreamChunk } from \"../core/options.js\";\nimport type { TextGenerationOptions } from \"../core/quick-methods.js\";\nimport type {\n CostReportingImageNamespace,\n CostReportingLLMist,\n CostReportingSpeechNamespace,\n} from \"./types.js\";\n\n/**\n * Callback type for reporting costs.\n */\nexport type CostReporter = (amount: number) => void;\n\n/**\n * LLMist client wrapper that automatically reports LLM costs.\n *\n * This wrapper intercepts all LLM calls, tracks token usage from responses,\n * calculates costs using ModelRegistry, and reports them via the callback.\n *\n * @example\n * ```typescript\n * let totalCost = 0;\n * const wrapper = new CostReportingLLMistWrapper(client, (cost) => {\n * totalCost += cost;\n * });\n *\n * // LLM cost automatically reported after completion\n * const result = await wrapper.complete(\"Hello\");\n * console.log(`Cost: $${totalCost}`);\n * ```\n */\nexport class CostReportingLLMistWrapper implements CostReportingLLMist {\n readonly image: CostReportingImageNamespace;\n readonly speech: CostReportingSpeechNamespace;\n\n constructor(\n private readonly client: LLMist,\n private readonly reportCost: CostReporter,\n ) {\n // Initialize image namespace with cost reporting\n this.image = {\n generate: async (options: ImageGenerationOptions): Promise<ImageGenerationResult> => {\n const result = await this.client.image.generate(options);\n // Report cost if available in the result\n if (result.cost !== undefined && result.cost > 0) {\n this.reportCost(result.cost);\n }\n return result;\n },\n };\n\n // Initialize speech namespace with cost reporting\n this.speech = {\n generate: async (options: SpeechGenerationOptions): Promise<SpeechGenerationResult> => {\n const result = await this.client.speech.generate(options);\n // Report cost if available in the result\n if (result.cost !== undefined && result.cost > 0) {\n this.reportCost(result.cost);\n }\n return result;\n },\n };\n }\n\n /**\n * Access to model registry for cost estimation.\n */\n get modelRegistry(): ModelRegistry {\n return this.client.modelRegistry;\n }\n\n /**\n * Quick completion with automatic cost reporting.\n *\n * Streams internally to track token usage, then reports the calculated cost.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration (model, temperature, etc.)\n * @returns Complete text response\n */\n async complete(prompt: string, options?: TextGenerationOptions): Promise<string> {\n const model = resolveModel(options?.model ?? \"haiku\");\n let result = \"\";\n let inputTokens = 0;\n let outputTokens = 0;\n let cachedInputTokens = 0;\n let cacheCreationInputTokens = 0;\n\n const messages = [\n ...(options?.systemPrompt\n ? [{ role: \"system\" as const, content: options.systemPrompt }]\n : []),\n { role: \"user\" as const, content: prompt },\n ];\n\n for await (const chunk of this.client.stream({\n model,\n messages,\n temperature: options?.temperature,\n maxTokens: options?.maxTokens,\n })) {\n result += chunk.text ?? \"\";\n if (chunk.usage) {\n inputTokens = chunk.usage.inputTokens;\n outputTokens = chunk.usage.outputTokens;\n cachedInputTokens = chunk.usage.cachedInputTokens ?? 0;\n cacheCreationInputTokens = chunk.usage.cacheCreationInputTokens ?? 0;\n }\n }\n\n this.reportCostFromUsage(\n model,\n inputTokens,\n outputTokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n );\n return result;\n }\n\n /**\n * Quick streaming with automatic cost reporting when stream completes.\n *\n * Yields text chunks as they arrive, then reports cost in finally block.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration (model, temperature, etc.)\n * @returns Async generator yielding text chunks\n */\n async *streamText(prompt: string, options?: TextGenerationOptions): AsyncGenerator<string> {\n const model = resolveModel(options?.model ?? \"haiku\");\n let inputTokens = 0;\n let outputTokens = 0;\n let cachedInputTokens = 0;\n let cacheCreationInputTokens = 0;\n\n const messages = [\n ...(options?.systemPrompt\n ? [{ role: \"system\" as const, content: options.systemPrompt }]\n : []),\n { role: \"user\" as const, content: prompt },\n ];\n\n try {\n for await (const chunk of this.client.stream({\n model,\n messages,\n temperature: options?.temperature,\n maxTokens: options?.maxTokens,\n })) {\n if (chunk.text) {\n yield chunk.text;\n }\n if (chunk.usage) {\n inputTokens = chunk.usage.inputTokens;\n outputTokens = chunk.usage.outputTokens;\n cachedInputTokens = chunk.usage.cachedInputTokens ?? 0;\n cacheCreationInputTokens = chunk.usage.cacheCreationInputTokens ?? 0;\n }\n }\n } finally {\n // Report cost when stream ends (success or early exit)\n this.reportCostFromUsage(\n model,\n inputTokens,\n outputTokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n );\n }\n }\n\n /**\n * Low-level stream access with automatic cost reporting.\n *\n * Returns a wrapped stream that reports costs when iteration completes.\n *\n * @param options - Full LLM generation options\n * @returns Wrapped LLM stream that auto-reports costs\n */\n stream(options: LLMGenerationOptions): LLMStream {\n return this.createCostReportingStream(options);\n }\n\n /**\n * Creates a wrapped stream that tracks usage and reports costs on completion.\n */\n private createCostReportingStream(options: LLMGenerationOptions): LLMStream {\n const innerStream = this.client.stream(options);\n const reportCostFromUsage = this.reportCostFromUsage.bind(this);\n const model = options.model;\n\n async function* costReportingWrapper(): AsyncGenerator<LLMStreamChunk> {\n let inputTokens = 0;\n let outputTokens = 0;\n let cachedInputTokens = 0;\n let cacheCreationInputTokens = 0;\n\n try {\n for await (const chunk of innerStream) {\n if (chunk.usage) {\n inputTokens = chunk.usage.inputTokens;\n outputTokens = chunk.usage.outputTokens;\n cachedInputTokens = chunk.usage.cachedInputTokens ?? 0;\n cacheCreationInputTokens = chunk.usage.cacheCreationInputTokens ?? 0;\n }\n yield chunk;\n }\n } finally {\n // Report cost when stream completes (success or early exit)\n if (inputTokens > 0 || outputTokens > 0) {\n reportCostFromUsage(\n model,\n inputTokens,\n outputTokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n );\n }\n }\n }\n\n return costReportingWrapper();\n }\n\n /**\n * Calculates and reports cost from token usage.\n */\n private reportCostFromUsage(\n model: string,\n inputTokens: number,\n outputTokens: number,\n cachedInputTokens = 0,\n cacheCreationInputTokens = 0,\n ): void {\n if (inputTokens === 0 && outputTokens === 0) return;\n\n // Model registry now handles provider-prefixed model IDs internally\n const estimate = this.client.modelRegistry.estimateCost(\n model,\n inputTokens,\n outputTokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n );\n\n if (estimate && estimate.totalCost > 0) {\n this.reportCost(estimate.totalCost);\n }\n }\n}\n","import type { ZodError } from \"zod\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { AbstractGadget } 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 execution errors with helpful context for LLM self-correction.\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 GadgetExecutionErrorFormatter {\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: AbstractGadget): 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: AbstractGadget | 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 GadgetExecutionErrorFormatter instance\n */\nexport function createErrorFormatter(\n options: ErrorFormatterOptions = {},\n): GadgetExecutionErrorFormatter {\n return new GadgetExecutionErrorFormatter(options);\n}\n","import { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport { parseBlockParams } from \"./block-params.js\";\nimport type { StreamEvent } from \"./types.js\";\n\nexport type ParameterFormat = \"block\";\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\n/**\n * Parser for extracting gadget invocations from LLM text output.\n * Processes text chunks incrementally and emits events for text and gadget calls.\n */\nexport class GadgetCallParser {\n private buffer = \"\";\n private lastEmittedTextOffset = 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 /**\n * Extract and consume text up to the given index.\n * Returns undefined if no meaningful text to emit.\n */\n private extractTextSegment(index: number): string | undefined {\n if (index <= this.lastEmittedTextOffset) {\n return undefined;\n }\n\n const segment = this.buffer.slice(this.lastEmittedTextOffset, index);\n this.lastEmittedTextOffset = index;\n\n return segment.trim().length > 0 ? segment : undefined;\n }\n\n /**\n * Parse gadget invocation metadata from the header line.\n *\n * Supported formats:\n * - `GadgetName` - Auto-generate ID, no dependencies\n * - `GadgetName:my_id` - Explicit ID, no dependencies\n * - `GadgetName:my_id:dep1,dep2` - Explicit ID with dependencies\n *\n * Dependencies must be comma-separated invocation IDs.\n */\n private parseInvocationMetadata(headerLine: string): {\n gadgetName: string;\n invocationId: string;\n dependencies: string[];\n } {\n const parts = headerLine.split(\":\");\n\n if (parts.length === 1) {\n // Just name: GadgetName\n return {\n gadgetName: parts[0],\n invocationId: `gadget_${++globalInvocationCounter}`,\n dependencies: [],\n };\n } else if (parts.length === 2) {\n // Name + ID: GadgetName:calc_1\n return {\n gadgetName: parts[0],\n invocationId: parts[1].trim(),\n dependencies: [],\n };\n } else {\n // Name + ID + deps: GadgetName:calc_1:dep1,dep2\n const deps = parts[2]\n .split(\",\")\n .map((d) => d.trim())\n .filter((d) => d.length > 0);\n return {\n gadgetName: parts[0],\n invocationId: parts[1].trim(),\n dependencies: deps,\n };\n }\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.extractTextSegment(partStartIndex);\n if (textBefore !== undefined) {\n yield { type: \"text\", content: textBefore };\n }\n\n // Extract gadget metadata from header line\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 headerLine = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n const { gadgetName, invocationId, dependencies } = this.parseInvocationMetadata(headerLine);\n\n const contentStartIndex = metadataEndIndex + 1;\n\n let partEndIndex: number;\n let endMarkerLength = 0;\n\n // 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 end marker\n const endPos = this.buffer.indexOf(this.endPrefix, contentStartIndex);\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 && (endPos === -1 || nextStartPos < endPos)) {\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 (endPos !== -1) {\n // Found proper end marker\n partEndIndex = endPos;\n endMarkerLength = this.endPrefix.length;\n } else {\n // Neither end marker nor next start found - wait for more data\n break;\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,\n invocationId,\n parametersRaw,\n parameters,\n parseError,\n dependencies,\n },\n };\n\n // Move past this gadget\n startIndex = partEndIndex + endMarkerLength;\n\n this.lastEmittedTextOffset = startIndex;\n }\n\n // Keep unprocessed data in buffer\n if (startIndex > 0) {\n this.buffer = this.buffer.substring(startIndex);\n this.lastEmittedTextOffset = 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.lastEmittedTextOffset);\n\n if (startIndex !== -1) {\n // There's an incomplete gadget - try to parse it\n const textBefore = this.extractTextSegment(startIndex);\n if (textBefore !== undefined) {\n yield { type: \"text\", content: textBefore };\n }\n\n // Extract gadget metadata from header line\n const metadataStartIndex = startIndex + this.startPrefix.length;\n const metadataEndIndex = this.buffer.indexOf(\"\\n\", metadataStartIndex);\n\n if (metadataEndIndex !== -1) {\n const headerLine = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n const { gadgetName, invocationId, dependencies } = this.parseInvocationMetadata(headerLine);\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,\n invocationId,\n parametersRaw: parametersRaw,\n parameters,\n parseError,\n dependencies,\n },\n };\n\n return;\n }\n }\n\n // No incomplete gadget - just emit remaining text\n const remainingText = this.extractTextSegment(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.lastEmittedTextOffset = 0;\n }\n}\n\n","/**\n * Type-safe gadget factory with automatic parameter inference.\n *\n * Gadget eliminates the need for manual type assertions\n * by automatically inferring parameter types from the Zod schema.\n *\n * @example\n * ```typescript\n * class Calculator extends Gadget({\n * description: \"Performs arithmetic operations\",\n * schema: z.object({\n * operation: z.enum([\"add\", \"subtract\"]),\n * a: z.number(),\n * b: z.number(),\n * }),\n * }) {\n * // ✨ params is automatically typed!\n * execute(params: this['params']): string {\n * const { operation, a, b } = params; // All typed!\n * return operation === \"add\" ? String(a + b) : String(a - b);\n * }\n * }\n * ```\n */\n\nimport type { ZodType } from \"zod\";\nimport { AbstractGadget } from \"./gadget.js\";\nimport type { ExecutionContext, GadgetExample, GadgetExecuteReturn } from \"./types.js\";\n\n/**\n * Infer the TypeScript type from a Zod schema.\n */\ntype InferSchema<T> = T extends ZodType<infer U> ? U : never;\n\n/**\n * Configuration for creating a typed gadget.\n */\nexport interface GadgetConfig<TSchema extends ZodType> {\n /** Human-readable description of what the gadget does */\n description: string;\n\n /** Zod schema for parameter validation */\n schema: TSchema;\n\n /** Optional custom name (defaults to class name) */\n name?: string;\n\n /** Optional timeout in milliseconds */\n timeoutMs?: number;\n\n /** Optional usage examples to help LLMs understand proper invocation */\n examples?: GadgetExample<InferSchema<TSchema>>[];\n}\n\n/**\n * Factory function to create a typed gadget base class.\n *\n * The returned class automatically infers parameter types from the Zod schema,\n * eliminating the need for manual type assertions in the execute method.\n *\n * @param config - Configuration with description and schema\n * @returns Base class to extend with typed execute method\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { Gadget } from 'llmist';\n *\n * class Calculator extends Gadget({\n * description: \"Performs arithmetic operations\",\n * schema: z.object({\n * operation: z.enum([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n * a: z.number().describe(\"First number\"),\n * b: z.number().describe(\"Second number\"),\n * }),\n * }) {\n * execute(params: this['params']): string {\n * // params is automatically typed as:\n * // { operation: \"add\" | \"subtract\" | \"multiply\" | \"divide\"; a: number; b: number }\n * const { operation, a, b } = params;\n *\n * switch (operation) {\n * case \"add\": return String(a + b);\n * case \"subtract\": return String(a - b);\n * case \"multiply\": return String(a * b);\n * case \"divide\": return String(a / b);\n * }\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // With async execution\n * class WeatherGadget extends Gadget({\n * description: \"Fetches weather for a city\",\n * schema: z.object({\n * city: z.string().min(1).describe(\"City name\"),\n * }),\n * timeoutMs: 10000,\n * }) {\n * async execute(params: this['params']): Promise<string> {\n * const { city } = params; // Automatically typed as { city: string }\n * const weather = await fetchWeather(city);\n * return `Weather in ${city}: ${weather}`;\n * }\n * }\n * ```\n */\nexport function Gadget<TSchema extends ZodType>(config: GadgetConfig<TSchema>) {\n abstract class GadgetBase extends AbstractGadget {\n description = config.description;\n parameterSchema = config.schema;\n name = config.name;\n timeoutMs = config.timeoutMs;\n examples = config.examples;\n\n /**\n * Type helper property for accessing inferred parameter type.\n * This is used in the execute method signature: `execute(params: this['params'])`\n *\n * Note: This is just for type inference - the actual params in execute()\n * will be Record<string, unknown> which you can safely cast to this['params']\n */\n readonly params!: InferSchema<TSchema>;\n\n /**\n * Execute the gadget. Subclasses should cast params to this['params'].\n *\n * @param params - Validated parameters from the LLM\n * @param ctx - Optional execution context for cost reporting and LLM access\n * @returns Result as a string, or an object with result and optional cost\n *\n * @example\n * ```typescript\n * // Simple string return (free gadget)\n * execute(params: this['params']) {\n * return String(params.a + params.b);\n * }\n *\n * // Using context for callback-based cost reporting\n * execute(params: this['params'], ctx) {\n * ctx.reportCost(0.001);\n * return \"result\";\n * }\n *\n * // Using wrapped LLMist for automatic cost tracking\n * async execute(params: this['params'], ctx) {\n * return ctx.llmist.complete('Summarize: ' + params.text);\n * }\n * ```\n */\n abstract execute(\n params: Record<string, unknown>,\n ctx?: ExecutionContext,\n ): GadgetExecuteReturn | Promise<GadgetExecuteReturn>;\n }\n\n return GadgetBase as {\n new (): GadgetBase & { params: InferSchema<TSchema> };\n };\n}\n","import equal from \"fast-deep-equal\";\nimport type { ILogObj, Logger } from \"tslog\";\nimport { z } from \"zod\";\nimport { AgentBuilder } from \"../agent/builder.js\";\nimport { LLMist } from \"../core/client.js\";\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { ExecutionTree, type NodeId } from \"../core/execution-tree.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { parseBlockParams } from \"./block-params.js\";\nimport { CostReportingLLMistWrapper } from \"./cost-reporting-client.js\";\nimport { createGadget } from \"./create-gadget.js\";\nimport { type ErrorFormatterOptions, GadgetExecutionErrorFormatter } from \"./error-formatter.js\";\nimport {\n AbortException,\n HumanInputRequiredException,\n TaskCompletionSignal,\n TimeoutException,\n} from \"./exceptions.js\";\nimport type { MediaStore } from \"./media-store.js\";\nimport { stripMarkdownFences } from \"./parser.js\";\nimport type { GadgetRegistry } from \"./registry.js\";\nimport { Gadget } from \"./typed-gadget.js\";\nimport type {\n AgentContextConfig,\n ExecutionContext,\n GadgetExecuteResult,\n GadgetExecuteResultWithMedia,\n GadgetExecutionResult,\n GadgetMediaOutput,\n HostExports,\n ParsedGadgetCall,\n SubagentConfigMap,\n SubagentEvent,\n} from \"./types.js\";\n\n/**\n * Lazily create host exports to avoid circular dependency issues.\n * Cached after first call.\n */\nlet cachedHostExports: HostExports | undefined;\nfunction getHostExportsInternal(): HostExports {\n if (!cachedHostExports) {\n cachedHostExports = {\n AgentBuilder,\n Gadget,\n createGadget,\n ExecutionTree,\n LLMist,\n z,\n };\n }\n return cachedHostExports;\n}\n\nexport class GadgetExecutor {\n private readonly logger: Logger<ILogObj>;\n private readonly errorFormatter: GadgetExecutionErrorFormatter;\n private readonly argPrefix: string;\n\n constructor(\n private readonly registry: GadgetRegistry,\n private readonly requestHumanInput?: (question: string) => Promise<string>,\n logger?: Logger<ILogObj>,\n private readonly defaultGadgetTimeoutMs?: number,\n errorFormatterOptions?: ErrorFormatterOptions,\n private readonly client?: LLMist,\n private readonly mediaStore?: MediaStore,\n private readonly agentConfig?: AgentContextConfig,\n private readonly subagentConfig?: SubagentConfigMap,\n private readonly onSubagentEvent?: (event: SubagentEvent) => void,\n // Execution Tree context for gadget execution\n private readonly tree?: ExecutionTree,\n private readonly parentNodeId?: NodeId | null,\n private readonly baseDepth?: number,\n ) {\n this.logger = logger ?? createLogger({ name: \"llmist:executor\" });\n this.errorFormatter = new GadgetExecutionErrorFormatter(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 * Aborts the provided AbortController before rejecting, allowing gadgets to clean up.\n * Returns both the promise and a cancel function to clear the timeout when no longer needed.\n */\n private createTimeoutPromise(\n gadgetName: string,\n timeoutMs: number,\n abortController: AbortController,\n ): { promise: Promise<never>; cancel: () => void } {\n let timeoutId: ReturnType<typeof setTimeout>;\n\n const promise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n const timeoutError = new TimeoutException(gadgetName, timeoutMs);\n // Signal abort FIRST so gadgets can clean up before exception is thrown\n // Pass the timeout message as reason for better debugging context\n abortController.abort(timeoutError.message);\n reject(timeoutError);\n }, timeoutMs);\n });\n\n return {\n promise,\n cancel: () => clearTimeout(timeoutId),\n };\n }\n\n /**\n * Unify gadget execute result to consistent internal format.\n * Handles string returns (backwards compat), object returns with cost,\n * and object returns with media.\n */\n private unifyExecuteResult(\n raw: string | GadgetExecuteResult | GadgetExecuteResultWithMedia,\n ): { result: string; media?: GadgetMediaOutput[]; cost: number } {\n if (typeof raw === \"string\") {\n return { result: raw, cost: 0 };\n }\n // Check if it has media property (GadgetExecuteResultWithMedia)\n if (\"media\" in raw && raw.media) {\n return { result: raw.result, media: raw.media, cost: raw.cost ?? 0 };\n }\n return { result: raw.result, cost: raw.cost ?? 0 };\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 = !equal(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: subagentConfig[name].timeoutMs > gadget.timeoutMs > defaultGadgetTimeoutMs > no timeout\n const subagentTimeout = this.subagentConfig?.[call.gadgetName]?.timeoutMs;\n const timeoutMs = subagentTimeout ?? gadget.timeoutMs ?? this.defaultGadgetTimeoutMs;\n\n // Create AbortController for cancellation support\n // Signal is always provided to gadgets, even without timeout\n const abortController = new AbortController();\n\n // Create execution context with cost accumulator and abort signal\n let callbackCost = 0;\n const reportCost = (amount: number) => {\n if (amount > 0) {\n callbackCost += amount;\n this.logger.debug(\"Gadget reported cost via callback\", {\n gadgetName: call.gadgetName,\n amount,\n totalCallbackCost: callbackCost,\n });\n }\n };\n\n // Build execution context with abort signal, agent config, and tree access\n // Look up the gadget's own node ID from the tree (not the parent LLM call's ID)\n const gadgetNodeId = this.tree?.getNodeByInvocationId(call.invocationId)?.id;\n const gadgetDepth = gadgetNodeId\n ? this.tree?.getNode(gadgetNodeId)?.depth ?? this.baseDepth\n : this.baseDepth;\n\n const ctx: ExecutionContext = {\n reportCost,\n llmist: this.client ? new CostReportingLLMistWrapper(this.client, reportCost) : undefined,\n signal: abortController.signal,\n agentConfig: this.agentConfig,\n subagentConfig: this.subagentConfig,\n invocationId: call.invocationId,\n onSubagentEvent: this.onSubagentEvent,\n // Tree context for subagent support - use gadget's own node ID\n tree: this.tree,\n nodeId: gadgetNodeId,\n depth: gadgetDepth,\n // Host exports for external gadgets to use host's llmist classes\n hostExports: getHostExportsInternal(),\n // Logger for structured logging (respects CLI's log level/file config)\n logger: this.logger,\n // Human input callback for subagents to bubble up input requests\n requestHumanInput: this.requestHumanInput,\n };\n\n // Execute gadget (handle both sync and async)\n let rawResult: string | GadgetExecuteResult;\n if (timeoutMs && timeoutMs > 0) {\n // Execute with timeout - abort signal will be triggered before timeout rejection\n this.logger.debug(\"Executing gadget with timeout\", {\n gadgetName: call.gadgetName,\n timeoutMs,\n });\n const timeout = this.createTimeoutPromise(call.gadgetName, timeoutMs, abortController);\n try {\n rawResult = await Promise.race([\n Promise.resolve(gadget.execute(validatedParameters, ctx)),\n timeout.promise,\n ]);\n } finally {\n // Always cancel the timeout to prevent it from keeping the event loop alive\n timeout.cancel();\n }\n } else {\n // Execute without timeout\n rawResult = await Promise.resolve(gadget.execute(validatedParameters, ctx));\n }\n\n // Normalize result: handle string returns (legacy), object returns with cost, and media\n const { result, media, cost: returnCost } = this.unifyExecuteResult(rawResult);\n\n // Sum callback costs + return costs\n const totalCost = callbackCost + returnCost;\n\n // Store media in MediaStore if present\n let mediaIds: string[] | undefined;\n let storedMedia: import(\"./types.js\").StoredMedia[] | undefined;\n if (media && media.length > 0 && this.mediaStore) {\n storedMedia = await Promise.all(\n media.map((item) => this.mediaStore!.store(item, call.gadgetName)),\n );\n mediaIds = storedMedia.map((m) => m.id);\n this.logger.debug(\"Stored media outputs\", {\n gadgetName: call.gadgetName,\n mediaIds,\n count: media.length,\n });\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 cost: totalCost > 0 ? totalCost : undefined,\n callbackCost: callbackCost > 0 ? callbackCost : undefined,\n returnCost: returnCost > 0 ? returnCost : undefined,\n mediaCount: media?.length,\n });\n\n this.logger.debug(\"Gadget result\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result,\n cost: totalCost,\n executionTimeMs,\n mediaIds,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result,\n executionTimeMs,\n cost: totalCost,\n media,\n mediaIds,\n storedMedia,\n };\n } catch (error) {\n // Check if this is a TaskCompletionSignal\n if (error instanceof TaskCompletionSignal) {\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 an AbortException (thrown by gadgets when they detect abort signal)\n if (error instanceof AbortException) {\n this.logger.info(\"Gadget execution was aborted\", {\n gadgetName: call.gadgetName,\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 HumanInputRequiredException using duck typing\n // (handles module duplication issues in monorepos)\n const isHumanInputError =\n error instanceof Error &&\n error.name === \"HumanInputRequiredException\" &&\n \"question\" in error;\n if (isHumanInputError) {\n const question = (error as HumanInputRequiredException).question;\n this.logger.info(\"Gadget requested human input\", {\n gadgetName: call.gadgetName,\n question,\n });\n\n // If callback is provided, call it and wait for answer\n if (this.requestHumanInput) {\n try {\n const answer = await this.requestHumanInput(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","/**\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 { LLMist } from \"../core/client.js\";\nimport type { ExecutionTree, NodeId } from \"../core/execution-tree.js\";\nimport type { LLMStreamChunk, TokenUsage } from \"../core/options.js\";\nimport { GadgetExecutor } from \"../gadgets/executor.js\";\nimport type { MediaStore } from \"../gadgets/media-store.js\";\nimport { GadgetCallParser } from \"../gadgets/parser.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type {\n AgentContextConfig,\n GadgetExecutionResult,\n GadgetSkippedEvent,\n ParsedGadgetCall,\n StreamCompletionEvent,\n StreamEvent,\n SubagentConfigMap,\n SubagentEvent,\n} 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 DependencySkipAction,\n DependencySkipControllerContext,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetSkippedContext,\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 requesting human input during execution */\n requestHumanInput?: (question: string) => Promise<string>;\n\n /** Default gadget timeout */\n defaultGadgetTimeoutMs?: number;\n\n /** LLMist client for ExecutionContext.llmist */\n client?: LLMist;\n\n /** MediaStore for storing gadget media outputs */\n mediaStore?: MediaStore;\n\n /** Parent agent configuration for subagents to inherit */\n agentConfig?: AgentContextConfig;\n\n /** Subagent-specific configuration overrides */\n subagentConfig?: SubagentConfigMap;\n\n /** Callback for subagent gadgets to report subagent events to parent */\n onSubagentEvent?: (event: SubagentEvent) => void;\n\n // ==========================================================================\n // Execution Tree Context (for tree-based tracking)\n // ==========================================================================\n\n /** Execution tree for tracking LLM calls and gadget executions */\n tree?: ExecutionTree;\n\n /** Parent node ID (for gadget nodes created by this processor) */\n parentNodeId?: NodeId | null;\n\n /** Base depth for nodes created by this processor */\n baseDepth?: number;\n\n // ==========================================================================\n // Cross-Iteration Dependency Resolution\n // ==========================================================================\n\n /**\n * Set of invocation IDs that completed in previous iterations.\n * Used to resolve dependencies on gadgets from prior LLM responses.\n */\n priorCompletedInvocations?: Set<string>;\n\n /**\n * Set of invocation IDs that failed in previous iterations.\n * Used to skip gadgets that depend on previously-failed gadgets.\n */\n priorFailedInvocations?: Set<string>;\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: GadgetCallParser;\n private readonly executor: GadgetExecutor;\n\n // Execution Tree context\n private readonly tree?: ExecutionTree;\n private readonly parentNodeId: NodeId | null;\n private readonly baseDepth: number;\n\n private responseText = \"\";\n private observerFailureCount = 0;\n\n // Dependency tracking for gadget execution DAG\n /** Gadgets waiting for their dependencies to complete */\n private gadgetsAwaitingDependencies: Map<string, ParsedGadgetCall> = new Map();\n /** Completed gadget results, keyed by invocation ID */\n private completedResults: Map<string, GadgetExecutionResult> = new Map();\n /** Invocation IDs of gadgets that have failed (error or skipped due to dependency) */\n private failedInvocations: Set<string> = new Set();\n /** Promises for independent gadgets currently executing (fire-and-forget) */\n private inFlightExecutions: Map<string, Promise<void>> = new Map();\n /** Queue of completed gadget results ready to be yielded (for real-time streaming) */\n private completedResultsQueue: StreamEvent[] = [];\n\n // Cross-iteration dependency tracking\n /** Invocation IDs completed in previous iterations (read-only reference from Agent) */\n private readonly priorCompletedInvocations: Set<string>;\n /** Invocation IDs that failed in previous iterations (read-only reference from Agent) */\n private readonly priorFailedInvocations: Set<string>;\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\n // Initialize tree context\n this.tree = options.tree;\n this.parentNodeId = options.parentNodeId ?? null;\n this.baseDepth = options.baseDepth ?? 0;\n\n // Initialize cross-iteration dependency tracking (use empty sets if not provided)\n this.priorCompletedInvocations = options.priorCompletedInvocations ?? new Set();\n this.priorFailedInvocations = options.priorFailedInvocations ?? new Set();\n\n this.parser = new GadgetCallParser({\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n argPrefix: options.gadgetArgPrefix,\n });\n\n // Wrap onSubagentEvent to also push to completedResultsQueue for real-time streaming\n // during parallel gadget execution. This ensures subagent events are yielded\n // while waiting for gadgets to complete, not batched at the end.\n const wrappedOnSubagentEvent = options.onSubagentEvent\n ? (event: SubagentEvent) => {\n // Push to queue for real-time streaming during parallel execution\n this.completedResultsQueue.push({\n type: \"subagent_event\",\n subagentEvent: event,\n });\n // Also call the original callback (for Agent's queue and hooks)\n options.onSubagentEvent?.(event);\n }\n : undefined;\n\n this.executor = new GadgetExecutor(\n options.registry,\n options.requestHumanInput,\n this.logger.getSubLogger({ name: \"executor\" }),\n options.defaultGadgetTimeoutMs,\n { argPrefix: options.gadgetArgPrefix },\n options.client,\n options.mediaStore,\n options.agentConfig,\n options.subagentConfig,\n wrappedOnSubagentEvent,\n // Tree context for gadget execution\n options.tree,\n options.parentNodeId,\n options.baseDepth,\n );\n }\n\n /**\n * Process an LLM stream and yield events in real-time.\n *\n * This is an async generator that yields events immediately as they occur:\n * - Text events are yielded as text is streamed from the LLM\n * - gadget_call events are yielded immediately when a gadget call is parsed\n * - gadget_result events are yielded when gadget execution completes\n *\n * The final event is always a StreamCompletionEvent containing metadata.\n */\n async *process(stream: AsyncIterable<LLMStreamChunk>): AsyncGenerator<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.responseText,\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.responseText += 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.responseText,\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 - yield immediately\n for (const event of this.parser.feed(processedChunk)) {\n for await (const processedEvent of this.processEventGenerator(event)) {\n yield processedEvent;\n\n // Track gadget execution\n if (processedEvent.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (processedEvent.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n }\n\n // Step 4: Drain completed parallel gadget results (real-time streaming)\n // This yields results from gadgets that completed during this chunk processing\n for (const evt of this.drainCompletedResults()) {\n yield evt;\n\n if (evt.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n }\n\n // Finalize parsing\n for (const event of this.parser.finalize()) {\n for await (const processedEvent of this.processEventGenerator(event)) {\n yield processedEvent;\n\n if (processedEvent.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (processedEvent.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n }\n\n // Wait for all in-flight parallel gadgets to complete, yielding events in real-time\n // This enables subagent events to be displayed during long-running gadget execution\n for await (const evt of this.waitForInFlightExecutions()) {\n yield evt;\n\n if (evt.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n\n // Drain any remaining completed results (stragglers that finished after final poll)\n for (const evt of this.drainCompletedResults()) {\n yield evt;\n\n if (evt.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n\n // Final pass to process any remaining pending gadgets\n // This handles cases where the last gadgets in the stream have dependencies\n // (now that in-flight gadgets have completed, their dependents can execute)\n for await (const evt of this.processPendingGadgetsGenerator()) {\n yield evt;\n\n if (evt.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n\n // Step 4: Interceptor - Transform final message\n let finalMessage = this.responseText;\n if (this.hooks.interceptors?.interceptAssistantMessage) {\n const context: MessageInterceptorContext = {\n iteration: this.iteration,\n rawResponse: this.responseText,\n logger: this.logger,\n };\n finalMessage = this.hooks.interceptors.interceptAssistantMessage(finalMessage, context);\n }\n\n // Yield completion event with all metadata\n const completionEvent: StreamCompletionEvent = {\n type: \"stream_complete\",\n shouldBreakLoop,\n didExecuteGadgets,\n finishReason,\n usage,\n rawResponse: this.responseText,\n finalMessage,\n };\n yield completionEvent;\n }\n\n /**\n * Process a single parsed event, yielding events in real-time.\n */\n private async *processEventGenerator(event: StreamEvent): AsyncGenerator<StreamEvent> {\n if (event.type === \"text\") {\n // processTextEvent is async - need to await the result before iterating\n for (const e of await this.processTextEvent(event)) {\n yield e;\n }\n } else if (event.type === \"gadget_call\") {\n for await (const e of this.processGadgetCallGenerator(event.call)) {\n yield e;\n }\n } else {\n yield event;\n }\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.responseText,\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, yielding events in real-time.\n *\n * Yields gadget_call event IMMEDIATELY when parsed (before execution),\n * enabling real-time UI feedback.\n */\n private async *processGadgetCallGenerator(call: ParsedGadgetCall): AsyncGenerator<StreamEvent> {\n // Yield gadget_call IMMEDIATELY (real-time feedback before execution)\n yield { type: \"gadget_call\", call };\n\n // Add gadget to execution tree\n if (this.tree) {\n this.tree.addGadget({\n invocationId: call.invocationId,\n name: call.gadgetName,\n parameters: call.parameters ?? {},\n dependencies: call.dependencies,\n parentId: this.parentNodeId,\n });\n }\n\n // Check for dependencies\n if (call.dependencies.length > 0) {\n // Check for self-referential dependency (circular to self)\n if (call.dependencies.includes(call.invocationId)) {\n this.logger.warn(\"Gadget has self-referential dependency (depends on itself)\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n });\n this.failedInvocations.add(call.invocationId);\n const skipEvent: GadgetSkippedEvent = {\n type: \"gadget_skipped\",\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n failedDependency: call.invocationId,\n failedDependencyError: `Gadget \"${call.invocationId}\" cannot depend on itself (self-referential dependency)`,\n };\n yield skipEvent;\n return;\n }\n\n // Check if any dependency has failed (including from prior iterations)\n const failedDep = call.dependencies.find(\n (dep) => this.failedInvocations.has(dep) || this.priorFailedInvocations.has(dep),\n );\n if (failedDep) {\n // Dependency failed - handle skip\n const skipEvents = await this.handleFailedDependency(call, failedDep);\n for (const evt of skipEvents) {\n yield evt;\n }\n return;\n }\n\n // Check if all dependencies are satisfied (including from prior iterations)\n const unsatisfied = call.dependencies.filter(\n (dep) => !this.completedResults.has(dep) && !this.priorCompletedInvocations.has(dep),\n );\n if (unsatisfied.length > 0) {\n // Queue for later execution - gadget_call already yielded above\n this.logger.debug(\"Queueing gadget for later - waiting on dependencies\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n waitingOn: unsatisfied,\n });\n this.gadgetsAwaitingDependencies.set(call.invocationId, call);\n return; // Execution deferred, gadget_call already yielded\n }\n\n // All dependencies satisfied - execute synchronously (dependency already complete)\n for await (const evt of this.executeGadgetGenerator(call)) {\n yield evt;\n }\n\n // Check if any pending gadgets can now execute\n for await (const evt of this.processPendingGadgetsGenerator()) {\n yield evt;\n }\n return;\n }\n\n // NO dependencies - start immediately (parallel execution)\n // Results are pushed to completedResultsQueue and yielded during stream processing\n const executionPromise = this.executeGadgetAndCollect(call);\n this.inFlightExecutions.set(call.invocationId, executionPromise);\n // DON'T await - continue processing stream immediately\n }\n\n /**\n * Execute a gadget through the full hook lifecycle and yield events.\n * Handles parameter interception, before/after controllers, observers,\n * execution, result interception, and tree tracking.\n */\n private async *executeGadgetGenerator(call: ParsedGadgetCall): AsyncGenerator<StreamEvent> {\n // Log parse errors if present (execution continues - errors are part of the result)\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\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 // Mark gadget as running in execution tree\n if (this.tree) {\n const gadgetNode = this.tree.getNodeByInvocationId(call.invocationId);\n if (gadgetNode) {\n this.tree.startGadget(gadgetNode.id);\n }\n }\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 // Capture the raw result before any hook transformations.\n // Used in onGadgetExecutionComplete to provide both pre-hook (originalResult)\n // and post-hook (finalResult) values for observers that need to audit changes.\n const originalResult = result.result;\n\n // Step 5: Interceptor - Transform result (modifies result.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 (can further modify result)\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 cost: result.cost,\n logger: this.logger,\n };\n await this.hooks.observers?.onGadgetExecutionComplete?.(context);\n });\n }\n await this.runObserversInParallel(completeObservers);\n\n // Complete gadget in execution tree\n if (this.tree) {\n const gadgetNode = this.tree.getNodeByInvocationId(result.invocationId);\n if (gadgetNode) {\n if (result.error) {\n this.tree.completeGadget(gadgetNode.id, {\n error: result.error,\n executionTimeMs: result.executionTimeMs,\n cost: result.cost,\n });\n } else {\n this.tree.completeGadget(gadgetNode.id, {\n result: result.result,\n executionTimeMs: result.executionTimeMs,\n cost: result.cost,\n media: result.media,\n });\n }\n }\n }\n\n // Track completion for dependency resolution\n this.completedResults.set(result.invocationId, result);\n if (result.error) {\n this.failedInvocations.add(result.invocationId);\n }\n\n // Yield result event immediately\n yield { type: \"gadget_result\", result };\n }\n\n /**\n * Execute a gadget and push events to the completed results queue (non-blocking).\n * Used for fire-and-forget parallel execution of independent gadgets.\n * Results are pushed to completedResultsQueue for real-time streaming to the caller.\n */\n private async executeGadgetAndCollect(call: ParsedGadgetCall): Promise<void> {\n for await (const evt of this.executeGadgetGenerator(call)) {\n // Push each event to the queue as it's produced for real-time streaming\n this.completedResultsQueue.push(evt);\n }\n // NOTE: Don't delete from inFlightExecutions here - it creates a race condition\n // where fast-completing gadgets are removed before waitForInFlightExecutions runs.\n // The map is cleared in waitForInFlightExecutions after all promises are awaited.\n }\n\n /**\n * Drain all completed results from the queue.\n * Used to yield results as they complete during stream processing.\n * @returns Generator that yields all events currently in the queue\n */\n private *drainCompletedResults(): Generator<StreamEvent> {\n while (this.completedResultsQueue.length > 0) {\n yield this.completedResultsQueue.shift()!;\n }\n }\n\n /**\n * Wait for all in-flight gadget executions to complete, yielding events in real-time.\n * Called at stream end to ensure all parallel executions finish.\n * Results and subagent events are pushed to completedResultsQueue during execution.\n * This generator yields queued events while polling, enabling real-time display\n * of subagent activity (LLM calls, nested gadgets) during long-running gadgets.\n * Clears the inFlightExecutions map after all gadgets complete.\n */\n private async *waitForInFlightExecutions(): AsyncGenerator<StreamEvent> {\n if (this.inFlightExecutions.size === 0) {\n return;\n }\n\n this.logger.debug(\"Waiting for in-flight gadget executions\", {\n count: this.inFlightExecutions.size,\n invocationIds: Array.from(this.inFlightExecutions.keys()),\n });\n\n // Create a combined promise that resolves when all gadgets complete\n const allDone = Promise.all(this.inFlightExecutions.values()).then(() => \"done\" as const);\n\n // Poll interval for draining queue (100ms provides responsive updates)\n const POLL_INTERVAL_MS = 100;\n\n // Poll loop: yield queued events while waiting for gadgets to complete\n while (true) {\n // Race between: all gadgets completing OR poll timeout\n const result = await Promise.race([\n allDone,\n new Promise<\"poll\">((resolve) => setTimeout(() => resolve(\"poll\"), POLL_INTERVAL_MS)),\n ]);\n\n // Yield any events that accumulated in the queue\n yield* this.drainCompletedResults();\n\n if (result === \"done\") {\n // All gadgets complete - exit loop\n break;\n }\n // result === \"poll\" - continue polling\n }\n\n // Clear the map after all promises have completed\n this.inFlightExecutions.clear();\n }\n\n /**\n * Handle a gadget that cannot execute because a dependency failed.\n * Calls the onDependencySkipped controller to allow customization.\n */\n private async handleFailedDependency(\n call: ParsedGadgetCall,\n failedDep: string,\n ): Promise<StreamEvent[]> {\n const events: StreamEvent[] = [];\n const depResult = this.completedResults.get(failedDep);\n const depError = depResult?.error ?? \"Dependency failed\";\n\n // Call controller to allow customization of skip behavior\n let action: DependencySkipAction = { action: \"skip\" };\n if (this.hooks.controllers?.onDependencySkipped) {\n const context: DependencySkipControllerContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n failedDependency: failedDep,\n failedDependencyError: depError,\n logger: this.logger,\n };\n action = await this.hooks.controllers.onDependencySkipped(context);\n }\n\n if (action.action === \"skip\") {\n // Mark as failed so downstream dependents also skip\n this.failedInvocations.add(call.invocationId);\n\n // Skip gadget in execution tree\n if (this.tree) {\n const gadgetNode = this.tree.getNodeByInvocationId(call.invocationId);\n if (gadgetNode) {\n this.tree.skipGadget(gadgetNode.id, failedDep, depError, \"dependency_failed\");\n }\n }\n\n // Emit skip event\n const skipEvent: GadgetSkippedEvent = {\n type: \"gadget_skipped\",\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n failedDependency: failedDep,\n failedDependencyError: depError,\n };\n events.push(skipEvent);\n\n // Call observer\n if (this.hooks.observers?.onGadgetSkipped) {\n const observeContext: ObserveGadgetSkippedContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n failedDependency: failedDep,\n failedDependencyError: depError,\n logger: this.logger,\n };\n await this.safeObserve(() => this.hooks.observers?.onGadgetSkipped?.(observeContext));\n }\n\n this.logger.info(\"Gadget skipped due to failed dependency\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n failedDependency: failedDep,\n });\n } else if (action.action === \"execute_anyway\") {\n // Execute despite failed dependency\n this.logger.info(\"Executing gadget despite failed dependency (controller override)\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n failedDependency: failedDep,\n });\n for await (const evt of this.executeGadgetGenerator(call)) {\n events.push(evt);\n }\n } else if (action.action === \"use_fallback\") {\n // Use fallback result without executing\n const fallbackResult: GadgetExecutionResult = {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n result: action.fallbackResult,\n executionTimeMs: 0,\n };\n this.completedResults.set(call.invocationId, fallbackResult);\n events.push({ type: \"gadget_result\", result: fallbackResult });\n\n this.logger.info(\"Using fallback result for gadget with failed dependency\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n failedDependency: failedDep,\n });\n }\n\n return events;\n }\n\n /**\n * Process pending gadgets whose dependencies are now satisfied.\n * Yields events in real-time as gadgets complete.\n *\n * Gadgets are executed in parallel for efficiency,\n * but results are yielded as they become available.\n */\n private async *processPendingGadgetsGenerator(): AsyncGenerator<StreamEvent> {\n let progress = true;\n\n while (progress && this.gadgetsAwaitingDependencies.size > 0) {\n progress = false;\n\n // Find all gadgets that are ready to execute\n const readyToExecute: ParsedGadgetCall[] = [];\n const readyToSkip: Array<{ call: ParsedGadgetCall; failedDep: string }> = [];\n\n for (const [_invocationId, call] of this.gadgetsAwaitingDependencies) {\n // Check for failed dependency (including from prior iterations)\n const failedDep = call.dependencies.find(\n (dep) => this.failedInvocations.has(dep) || this.priorFailedInvocations.has(dep),\n );\n if (failedDep) {\n readyToSkip.push({ call, failedDep });\n continue;\n }\n\n // Check if all dependencies are satisfied (including from prior iterations)\n const allSatisfied = call.dependencies.every(\n (dep) => this.completedResults.has(dep) || this.priorCompletedInvocations.has(dep),\n );\n if (allSatisfied) {\n readyToExecute.push(call);\n }\n }\n\n // Handle skipped gadgets\n for (const { call, failedDep } of readyToSkip) {\n this.gadgetsAwaitingDependencies.delete(call.invocationId);\n const skipEvents = await this.handleFailedDependency(call, failedDep);\n for (const evt of skipEvents) {\n yield evt;\n }\n progress = true;\n }\n\n // Execute ready gadgets in parallel\n if (readyToExecute.length > 0) {\n this.logger.debug(\"Executing ready gadgets in parallel\", {\n count: readyToExecute.length,\n invocationIds: readyToExecute.map((c) => c.invocationId),\n });\n\n // Remove from pending before executing\n for (const call of readyToExecute) {\n this.gadgetsAwaitingDependencies.delete(call.invocationId);\n }\n\n // Execute all ready gadgets in parallel, collect events, then yield\n const eventSets = await Promise.all(\n readyToExecute.map(async (call) => {\n const events: StreamEvent[] = [];\n for await (const evt of this.executeGadgetGenerator(call)) {\n events.push(evt);\n }\n return events;\n }),\n );\n\n // Yield all events from parallel execution\n for (const events of eventSets) {\n for (const evt of events) {\n yield evt;\n }\n }\n\n progress = true;\n }\n }\n\n // Warn about any remaining unresolved gadgets (circular or missing dependencies)\n if (this.gadgetsAwaitingDependencies.size > 0) {\n // Collect all pending invocation IDs to detect circular dependencies\n const pendingIds = new Set(this.gadgetsAwaitingDependencies.keys());\n\n for (const [invocationId, call] of this.gadgetsAwaitingDependencies) {\n // Filter to deps that are not in current or prior completed sets\n const missingDeps = call.dependencies.filter(\n (dep) => !this.completedResults.has(dep) && !this.priorCompletedInvocations.has(dep),\n );\n\n // Categorize the dependency issue\n const circularDeps = missingDeps.filter((dep) => pendingIds.has(dep));\n const trulyMissingDeps = missingDeps.filter((dep) => !pendingIds.has(dep));\n\n let errorMessage: string;\n let logLevel: \"warn\" | \"error\" = \"warn\";\n\n if (circularDeps.length > 0 && trulyMissingDeps.length > 0) {\n errorMessage = `Dependencies unresolvable: circular=[${circularDeps.join(\", \")}], missing=[${trulyMissingDeps.join(\", \")}]`;\n logLevel = \"error\";\n } else if (circularDeps.length > 0) {\n errorMessage = `Circular dependency detected: \"${invocationId}\" depends on \"${circularDeps[0]}\" which also depends on \"${invocationId}\" (directly or indirectly)`;\n } else {\n errorMessage = `Dependency \"${missingDeps[0]}\" was never executed - check that the invocation ID exists and is spelled correctly`;\n }\n\n this.logger[logLevel](\"Gadget has unresolvable dependencies\", {\n gadgetName: call.gadgetName,\n invocationId,\n circularDependencies: circularDeps,\n missingDependencies: trulyMissingDeps,\n });\n\n // Mark as failed and emit skip event\n this.failedInvocations.add(invocationId);\n const skipEvent: GadgetSkippedEvent = {\n type: \"gadget_skipped\",\n gadgetName: call.gadgetName,\n invocationId,\n parameters: call.parameters ?? {},\n failedDependency: missingDeps[0],\n failedDependencyError: errorMessage,\n };\n yield skipEvent;\n }\n this.gadgetsAwaitingDependencies.clear();\n }\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 // Run all observers in parallel, waiting for completion\n // Errors are logged in safeObserve, no need to handle rejected promises\n await Promise.allSettled(\n observers.map((observer) => this.safeObserve(observer)),\n );\n }\n\n // ==========================================================================\n // Public accessors for cross-iteration dependency tracking\n // ==========================================================================\n\n /**\n * Get all invocation IDs that completed successfully in this iteration.\n * Used by Agent to accumulate completed IDs across iterations.\n */\n getCompletedInvocationIds(): Set<string> {\n return new Set(this.completedResults.keys());\n }\n\n /**\n * Get all invocation IDs that failed in this iteration.\n * Used by Agent to accumulate failed IDs across iterations.\n */\n getFailedInvocationIds(): Set<string> {\n return new Set(this.failedInvocations);\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 { ExecutionTree, type NodeId } from \"../core/execution-tree.js\";\nimport type { ContentPart } from \"../core/input-content.js\";\nimport type { MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, LLMMessageBuilder } from \"../core/messages.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { LLMGenerationOptions } from \"../core/options.js\";\nimport type { PromptTemplateConfig } from \"../core/prompt-config.js\";\nimport { MediaStore } from \"../gadgets/media-store.js\";\nimport { createGadgetOutputViewer } from \"../gadgets/output-viewer.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type {\n AgentContextConfig,\n LLMCallInfo,\n StreamCompletionEvent,\n StreamEvent,\n SubagentConfigMap,\n SubagentEvent,\n TextOnlyHandler,\n} from \"../gadgets/types.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { type AGENT_INTERNAL_KEY, isValidAgentKey } from \"./agent-internal-key.js\";\nimport type { CompactionConfig, CompactionEvent, CompactionStats } from \"./compaction/config.js\";\nimport type { RetryConfig, ResolvedRetryConfig } from \"../core/retry.js\";\nimport { resolveRetryConfig, isRetryableError } from \"../core/retry.js\";\nimport pRetry from \"p-retry\";\nimport { CompactionManager } from \"./compaction/manager.js\";\nimport { ConversationManager } from \"./conversation-manager.js\";\nimport type { IConversationManager } from \"./interfaces.js\";\nimport { type EventHandlers, runWithHandlers } from \"./event-handlers.js\";\nimport { GadgetOutputStore } from \"./gadget-output-store.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 GadgetResultInterceptorContext,\n LLMCallControllerContext,\n LLMErrorControllerContext,\n ObserveAbortContext,\n ObserveLLMCallContext,\n ObserveLLMCallReadyContext,\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()). Can be text or multimodal content. */\n userPrompt?: string | ContentPart[];\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 requesting human input during execution */\n requestHumanInput?: (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. User messages support multimodal content. */\n initialMessages?: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: MessageContent }>;\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 /** Default gadget timeout */\n defaultGadgetTimeoutMs?: number;\n\n /** Custom prompt configuration for gadget system prompts */\n promptConfig?: PromptTemplateConfig;\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 /** Retry configuration for LLM API calls (enabled by default) */\n retryConfig?: RetryConfig;\n\n /** Optional abort signal for cancelling requests mid-flight */\n signal?: AbortSignal;\n\n /** Subagent-specific configuration overrides (from CLI config) */\n subagentConfig?: SubagentConfigMap;\n\n /** Callback for subagent gadgets to report subagent events to parent */\n onSubagentEvent?: (event: SubagentEvent) => void;\n\n // ==========================================================================\n // Execution Tree Context (for shared tree model with subagents)\n // ==========================================================================\n\n /**\n * Shared execution tree for tracking all LLM calls and gadget executions.\n * If provided (by a parent subagent), nodes are added to this tree.\n * If not provided, the Agent creates its own tree.\n */\n parentTree?: ExecutionTree;\n\n /**\n * Parent node ID in the tree (when this agent is a subagent).\n * Used to set parentId on all nodes created by this agent.\n */\n parentNodeId?: NodeId;\n\n /**\n * Base depth for nodes created by this agent.\n * Root agents use 0; subagents use (parentDepth + 1).\n */\n baseDepth?: number;\n}\n\n/**\n * Agent: Lean orchestrator that delegates to StreamProcessor.\n *\n * Responsibilities:\n * - Run the main agent loop\n * - Call LLM API\n * - Delegate stream processing to StreamProcessor\n * - Coordinate conversation management\n * - Execute top-level lifecycle controllers\n *\n * NOT responsible for:\n * - Stream parsing (StreamProcessor)\n * - Hook coordination (StreamProcessor)\n * - Gadget execution (StreamProcessor -> GadgetExecutor)\n */\nexport class Agent {\n private readonly client: LLMist;\n private readonly model: string;\n private readonly maxIterations: number;\n private readonly temperature?: number;\n private readonly logger: Logger<ILogObj>;\n private readonly hooks: AgentHooks;\n private readonly conversation: ConversationManager;\n private readonly registry: GadgetRegistry;\n private readonly gadgetStartPrefix?: string;\n private readonly gadgetEndPrefix?: string;\n private readonly gadgetArgPrefix?: string;\n private readonly requestHumanInput?: (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 defaultGadgetTimeoutMs?: number;\n private readonly defaultMaxTokens?: number;\n private hasUserPrompt: 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 // Media storage (for gadgets returning images, audio, etc.)\n private readonly mediaStore: MediaStore;\n\n // Cancellation\n private readonly signal?: AbortSignal;\n\n // Retry configuration\n private readonly retryConfig: ResolvedRetryConfig;\n\n // Subagent configuration\n private readonly agentContextConfig: AgentContextConfig;\n private readonly subagentConfig?: SubagentConfigMap;\n\n // Subagent event callback for subagent gadgets\n private readonly userSubagentEventCallback?: (event: SubagentEvent) => void;\n // Internal queue for yielding subagent events in run()\n private readonly pendingSubagentEvents: SubagentEvent[] = [];\n // Combined callback that queues events AND calls user callback\n private readonly onSubagentEvent: (event: SubagentEvent) => void;\n // Counter for generating synthetic invocation IDs for wrapped text content\n private syntheticInvocationCounter = 0;\n\n // Cross-iteration dependency tracking - allows gadgets to depend on results from prior iterations\n private readonly completedInvocationIds: Set<string> = new Set();\n private readonly failedInvocationIds: Set<string> = new Set();\n\n // Queue for user messages injected during agent execution (REPL mid-session input)\n private readonly pendingUserMessages: string[] = [];\n\n // Execution Tree - first-class model for nested subagent support\n private readonly tree: ExecutionTree;\n private readonly parentNodeId: NodeId | null;\n private readonly baseDepth: number;\n\n /**\n * Creates a new Agent instance.\n * @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.\n */\n constructor(key: typeof AGENT_INTERNAL_KEY, options: AgentOptions) {\n if (!isValidAgentKey(key)) {\n throw new Error(\n \"Agent cannot be instantiated directly. Use LLMist.createAgent() or new AgentBuilder() instead.\",\n );\n }\n\n this.client = options.client;\n this.model = resolveModel(options.model);\n this.maxIterations = options.maxIterations ?? 10;\n this.temperature = options.temperature;\n this.logger = options.logger ?? createLogger({ name: \"llmist:agent\" });\n this.registry = options.registry;\n this.gadgetStartPrefix = options.gadgetStartPrefix;\n this.gadgetEndPrefix = options.gadgetEndPrefix;\n this.gadgetArgPrefix = options.gadgetArgPrefix;\n this.requestHumanInput = options.requestHumanInput;\n this.textOnlyHandler = options.textOnlyHandler ?? \"terminate\";\n this.textWithGadgetsHandler = options.textWithGadgetsHandler;\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 // Initialize media storage for gadgets returning images, audio, etc.\n this.mediaStore = new MediaStore();\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 // Pass the same character limit so viewer output is also bounded\n if (this.outputLimitEnabled) {\n this.registry.register(\n \"GadgetOutputViewer\",\n createGadgetOutputViewer(this.outputStore, this.outputLimitCharLimit),\n );\n }\n\n // Chain output limiter interceptor with user hooks\n this.hooks = this.chainOutputLimiterWithUserHooks(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.hasUserPrompt = !!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 // Initialize retry configuration (enabled by default)\n this.retryConfig = resolveRetryConfig(options.retryConfig);\n\n // Build agent context config for subagents to inherit\n this.agentContextConfig = {\n model: this.model,\n temperature: this.temperature,\n };\n this.subagentConfig = options.subagentConfig;\n\n // Initialize Execution Tree\n // If a parent tree is provided (subagent case), share it; otherwise create a new tree\n this.tree = options.parentTree ?? new ExecutionTree();\n this.parentNodeId = options.parentNodeId ?? null;\n this.baseDepth = options.baseDepth ?? 0;\n\n // Store user callback and create combined callback that:\n // 1. Queues events for yielding in run()\n // 2. Calls user callback if provided\n // 3. Fires hooks with subagentContext for consistent event handling\n this.userSubagentEventCallback = options.onSubagentEvent;\n this.onSubagentEvent = (event: SubagentEvent) => {\n this.pendingSubagentEvents.push(event);\n this.userSubagentEventCallback?.(event);\n\n // Fire the SAME hooks with subagentContext - enables consistent hook-based handling\n const subagentContext = {\n parentGadgetInvocationId: event.gadgetInvocationId,\n depth: event.depth,\n };\n\n // Fire hooks asynchronously but don't block\n if (event.type === \"llm_call_start\") {\n const info = event.event as LLMCallInfo;\n void this.hooks?.observers?.onLLMCallStart?.({\n iteration: info.iteration,\n options: { model: info.model, messages: [] },\n logger: this.logger,\n subagentContext,\n });\n } else if (event.type === \"llm_call_end\") {\n const info = event.event as LLMCallInfo;\n // Use full usage object if available (preserves cached tokens), fallback to basic reconstruction\n const usage = info.usage ?? (info.outputTokens\n ? {\n inputTokens: info.inputTokens ?? 0,\n outputTokens: info.outputTokens,\n totalTokens: (info.inputTokens ?? 0) + info.outputTokens,\n }\n : undefined);\n void this.hooks?.observers?.onLLMCallComplete?.({\n iteration: info.iteration,\n options: { model: info.model, messages: [] },\n finishReason: info.finishReason ?? null,\n usage,\n rawResponse: \"\",\n finalMessage: \"\",\n logger: this.logger,\n subagentContext,\n });\n } else if (event.type === \"gadget_call\") {\n const gadgetEvent = event.event as { call: { invocationId: string; gadgetName: string; parameters?: Record<string, unknown> } };\n void this.hooks?.observers?.onGadgetExecutionStart?.({\n iteration: 0,\n gadgetName: gadgetEvent.call.gadgetName,\n invocationId: gadgetEvent.call.invocationId,\n parameters: gadgetEvent.call.parameters ?? {},\n logger: this.logger,\n subagentContext,\n });\n } else if (event.type === \"gadget_result\") {\n const resultEvent = event.event as { result: { invocationId: string; gadgetName?: string; executionTimeMs?: number } };\n void this.hooks?.observers?.onGadgetExecutionComplete?.({\n iteration: 0,\n gadgetName: resultEvent.result.gadgetName ?? \"unknown\",\n invocationId: resultEvent.result.invocationId,\n parameters: {},\n executionTimeMs: resultEvent.result.executionTimeMs ?? 0,\n logger: this.logger,\n subagentContext,\n });\n }\n };\n }\n\n /**\n * Flush pending subagent events as StreamEvents.\n * Called from run() to yield queued subagent events from subagent gadgets.\n */\n private *flushPendingSubagentEvents(): Generator<StreamEvent> {\n while (this.pendingSubagentEvents.length > 0) {\n const event = this.pendingSubagentEvents.shift();\n if (event) {\n yield { type: \"subagent_event\", subagentEvent: event };\n }\n }\n }\n\n /**\n * Get the gadget registry for this agent.\n *\n * Useful for inspecting registered gadgets in tests or advanced use cases.\n *\n * @returns The GadgetRegistry instance\n *\n * @example\n * ```typescript\n * const agent = new AgentBuilder()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator, Weather)\n * .build();\n *\n * // Inspect registered gadgets\n * console.log(agent.getRegistry().getNames()); // ['Calculator', 'Weather']\n * ```\n */\n getRegistry(): GadgetRegistry {\n return this.registry;\n }\n\n /**\n * Get the media store for this agent session.\n *\n * The media store holds all media outputs (images, audio, etc.) produced by gadgets\n * during this agent's execution. Use this to:\n * - Access stored media files by ID\n * - List all stored media\n * - Clean up temporary files after execution\n *\n * @returns The MediaStore instance for this agent\n *\n * @example\n * ```typescript\n * const agent = new AgentBuilder()\n * .withModel(\"sonnet\")\n * .build();\n *\n * // After execution, access stored media\n * const store = agent.getMediaStore();\n * for (const media of store.list()) {\n * console.log(`${media.id}: ${media.path}`);\n * }\n *\n * // Clean up when done\n * await store.cleanup();\n * ```\n */\n getMediaStore(): MediaStore {\n return this.mediaStore;\n }\n\n /**\n * Get the execution tree for this agent.\n *\n * The execution tree provides a first-class model of all LLM calls and gadget executions,\n * including nested subagent activity. Use this to:\n * - Query execution state: `tree.getNode(id)`\n * - Get total cost: `tree.getTotalCost()`\n * - Get subtree cost/media/tokens: `tree.getSubtreeCost(nodeId)`\n * - Subscribe to events: `tree.on(\"llm_call_complete\", handler)`\n * - Stream all events: `for await (const event of tree.events())`\n *\n * For subagents (created with `withParentContext`), the tree is shared with the parent,\n * enabling unified tracking and real-time visibility across all nesting levels.\n *\n * @returns The ExecutionTree instance\n *\n * @example\n * ```typescript\n * const agent = LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withGadgets(BrowseWeb)\n * .ask(\"Research topic X\");\n *\n * for await (const event of agent.run()) {\n * // Process events...\n * }\n *\n * // After execution, query the tree\n * const tree = agent.getTree();\n * console.log(`Total cost: $${tree.getTotalCost().toFixed(4)}`);\n *\n * // Inspect all LLM calls\n * for (const node of tree.getAllNodes()) {\n * if (node.type === \"llm_call\") {\n * console.log(`LLM #${node.iteration}: ${node.model}`);\n * }\n * }\n * ```\n */\n getTree(): ExecutionTree {\n return this.tree;\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 * Get the conversation manager for this agent.\n * Used by REPL mode to extract session history for continuation.\n *\n * @returns The conversation manager containing all messages\n *\n * @example\n * ```typescript\n * // After running agent, extract history for next session\n * const history = agent.getConversation().getConversationHistory();\n * // Pass to next agent via builder.withHistory()\n * ```\n */\n getConversation(): IConversationManager {\n return this.conversation;\n }\n\n /**\n * Inject a user message to be processed in the next iteration.\n * Used by REPL mode to allow user input during a running session.\n *\n * The message is queued and will be added to the conversation before\n * the next LLM call. This allows users to provide additional context\n * or instructions while the agent is executing.\n *\n * @param message - The user message to inject\n *\n * @example\n * ```typescript\n * // While agent is running in TUI:\n * tui.onMidSessionInput((msg) => {\n * agent.injectUserMessage(msg);\n * });\n * ```\n */\n injectUserMessage(message: string): void {\n this.pendingUserMessages.push(message);\n this.logger.debug(\"User message queued for injection\", { message });\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.hasUserPrompt) {\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 // Check abort signal at start of each iteration\n if (await this.checkAbortAndNotify(currentIteration)) {\n return;\n }\n\n // Process any injected user messages (from REPL mid-session input)\n while (this.pendingUserMessages.length > 0) {\n const msg = this.pendingUserMessages.shift()!;\n this.conversation.addUserMessage(msg);\n this.logger.info(\"Injected user message into conversation\", {\n iteration: currentIteration,\n messageLength: msg.length,\n });\n }\n\n this.logger.debug(\"Starting iteration\", { iteration: currentIteration });\n\n try {\n // Check and perform context compaction if needed\n const compactionEvent = await this.checkAndPerformCompaction(currentIteration);\n if (compactionEvent) {\n yield compactionEvent;\n }\n\n // Prepare LLM call with hooks\n const prepared = await this.prepareLLMCall(currentIteration);\n const llmOptions = prepared.options;\n\n // Handle skip action from beforeLLMCall controller\n if (prepared.skipWithSynthetic !== undefined) {\n this.conversation.addAssistantMessage(prepared.skipWithSynthetic);\n yield { type: \"text\", content: prepared.skipWithSynthetic };\n break;\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\n // Add LLM call to execution tree\n const llmNode = this.tree.addLLMCall({\n iteration: currentIteration,\n model: llmOptions.model,\n parentId: this.parentNodeId,\n request: llmOptions.messages,\n });\n const currentLLMNodeId = llmNode.id;\n\n // Create LLM stream with retry logic (if enabled)\n const stream = await this.createStreamWithRetry(llmOptions, currentIteration);\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 requestHumanInput: this.requestHumanInput,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n client: this.client,\n mediaStore: this.mediaStore,\n agentConfig: this.agentContextConfig,\n subagentConfig: this.subagentConfig,\n onSubagentEvent: this.onSubagentEvent,\n // Tree context for execution tracking\n tree: this.tree,\n parentNodeId: currentLLMNodeId, // Gadgets are children of this LLM call\n baseDepth: this.baseDepth,\n // Cross-iteration dependency tracking\n priorCompletedInvocations: this.completedInvocationIds,\n priorFailedInvocations: this.failedInvocationIds,\n });\n\n // Consume the stream processor generator, yielding events in real-time\n // The final event is a StreamCompletionEvent containing metadata\n let streamMetadata: StreamCompletionEvent | null = null;\n let gadgetCallCount = 0;\n\n // Track outputs for conversation history (since we stream instead of batch)\n const textOutputs: string[] = [];\n const gadgetResults: StreamEvent[] = [];\n\n for await (const event of processor.process(stream)) {\n if (event.type === \"stream_complete\") {\n // Completion event - extract metadata, don't yield to consumer\n streamMetadata = event;\n continue;\n }\n\n // Track outputs for later conversation history updates\n if (event.type === \"text\") {\n textOutputs.push(event.content);\n } else if (event.type === \"gadget_result\") {\n gadgetCallCount++;\n gadgetResults.push(event);\n }\n\n // Yield event to consumer in real-time\n yield event;\n\n // Yield any subagent events that accumulated during gadget execution\n // This enables real-time display of subagent activity (Navigate, Screenshot, etc.)\n yield* this.flushPendingSubagentEvents();\n }\n\n // Ensure we received the completion metadata\n if (!streamMetadata) {\n throw new Error(\"Stream processing completed without metadata event\");\n }\n\n // Collect completed/failed invocation IDs for cross-iteration dependency tracking\n for (const id of processor.getCompletedInvocationIds()) {\n this.completedInvocationIds.add(id);\n }\n for (const id of processor.getFailedInvocationIds()) {\n this.failedInvocationIds.add(id);\n }\n\n // Use streamMetadata as the result for remaining logic\n const result = streamMetadata;\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 // Complete LLM call in execution tree (with cost calculation)\n this.completeLLMCallInTree(currentLLMNodeId, result);\n\n // Process afterLLMCall controller (may modify finalMessage or append messages)\n const finalMessage = await this.processAfterLLMCallController(\n currentIteration,\n llmOptions,\n result,\n gadgetCallCount,\n );\n\n // Update conversation with results (gadgets or text-only)\n const shouldBreakFromTextOnly = await this.updateConversationWithResults(\n result.didExecuteGadgets,\n textOutputs,\n gadgetResults,\n finalMessage,\n );\n if (shouldBreakFromTextOnly) {\n break;\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 * Create LLM stream with retry logic.\n * Wraps the stream creation with exponential backoff for transient failures.\n */\n private async createStreamWithRetry(\n llmOptions: LLMGenerationOptions,\n iteration: number,\n ): Promise<ReturnType<LLMist[\"stream\"]>> {\n // If retry is disabled, return stream directly\n if (!this.retryConfig.enabled) {\n return this.client.stream(llmOptions);\n }\n\n const { retries, minTimeout, maxTimeout, factor, randomize, onRetry, onRetriesExhausted, shouldRetry } =\n this.retryConfig;\n\n try {\n return await pRetry(\n async (attemptNumber) => {\n this.logger.debug(\"Creating LLM stream\", { attempt: attemptNumber, maxAttempts: retries + 1 });\n return this.client.stream(llmOptions);\n },\n {\n retries,\n minTimeout,\n maxTimeout,\n factor,\n randomize,\n signal: this.signal,\n onFailedAttempt: (context) => {\n const { error, attemptNumber, retriesLeft } = context;\n this.logger.warn(\n `LLM call failed (attempt ${attemptNumber}/${attemptNumber + retriesLeft}), retrying...`,\n { error: error.message, retriesLeft },\n );\n onRetry?.(error, attemptNumber);\n },\n shouldRetry: (context) => {\n // Use custom shouldRetry if provided, otherwise use default classification\n if (shouldRetry) {\n return shouldRetry(context.error);\n }\n return isRetryableError(context.error);\n },\n },\n );\n } catch (error) {\n // All retries exhausted - call observer hook before re-throwing\n this.logger.error(`LLM call failed after ${retries + 1} attempts`, {\n error: (error as Error).message,\n iteration,\n });\n onRetriesExhausted?.(error as Error, retries + 1);\n throw error;\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 * Chain the output limiter interceptor with user-provided hooks.\n * The limiter runs first, then chains to any user interceptor.\n */\n private chainOutputLimiterWithUserHooks(userHooks?: AgentHooks): AgentHooks {\n if (!this.outputLimitEnabled) {\n return userHooks ?? {};\n }\n\n const limiterInterceptor = (result: string, ctx: GadgetResultInterceptorContext): 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 // Agent Loop Helper Methods (extracted from run() for readability)\n // ==========================================================================\n\n /**\n * Check abort signal and notify observers if aborted.\n * @returns true if agent should terminate\n */\n private async checkAbortAndNotify(iteration: number): Promise<boolean> {\n if (!this.signal?.aborted) return false;\n\n this.logger.info(\"Agent loop terminated by abort signal\", {\n iteration,\n reason: this.signal.reason,\n });\n\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onAbort) {\n const context: ObserveAbortContext = {\n iteration,\n reason: this.signal?.reason,\n logger: this.logger,\n };\n await this.hooks.observers.onAbort(context);\n }\n });\n\n return true;\n }\n\n /**\n * Check and perform context compaction if needed.\n * @returns compaction stream event if compaction occurred, null otherwise\n */\n private async checkAndPerformCompaction(iteration: number): Promise<StreamEvent | null> {\n if (!this.compactionManager) return null;\n\n const compactionEvent = await this.compactionManager.checkAndCompact(\n this.conversation,\n iteration,\n );\n\n if (!compactionEvent) return null;\n\n this.logger.info(\"Context compacted\", {\n strategy: compactionEvent.strategy,\n tokensBefore: compactionEvent.tokensBefore,\n tokensAfter: compactionEvent.tokensAfter,\n });\n\n // Observer: Compaction occurred\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onCompaction) {\n await this.hooks.observers.onCompaction({\n iteration,\n event: compactionEvent,\n // biome-ignore lint/style/noNonNullAssertion: compactionManager exists if compactionEvent is truthy\n stats: this.compactionManager!.getStats(),\n logger: this.logger,\n });\n }\n });\n\n return { type: \"compaction\", event: compactionEvent } as StreamEvent;\n }\n\n /**\n * Prepare LLM call options and process beforeLLMCall controller.\n * @returns options and optional skipWithSynthetic response if controller wants to skip\n */\n private async prepareLLMCall(\n iteration: number,\n ): Promise<{ options: LLMGenerationOptions; skipWithSynthetic?: string }> {\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,\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,\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 return { options: llmOptions, skipWithSynthetic: action.syntheticResponse };\n } else if (action.action === \"proceed\" && action.modifiedOptions) {\n llmOptions = { ...llmOptions, ...action.modifiedOptions };\n }\n }\n\n // Observer: LLM call ready (after controller modifications)\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onLLMCallReady) {\n const context: ObserveLLMCallReadyContext = {\n iteration,\n maxIterations: this.maxIterations,\n options: llmOptions,\n logger: this.logger,\n };\n await this.hooks.observers.onLLMCallReady(context);\n }\n });\n\n return { options: llmOptions };\n }\n\n /**\n * Calculate cost and complete LLM call in execution tree.\n */\n private completeLLMCallInTree(\n nodeId: NodeId,\n result: StreamCompletionEvent,\n ): void {\n // Calculate cost using ModelRegistry (if available)\n const llmCost = this.client.modelRegistry?.estimateCost?.(\n this.model,\n result.usage?.inputTokens ?? 0,\n result.usage?.outputTokens ?? 0,\n result.usage?.cachedInputTokens ?? 0,\n result.usage?.cacheCreationInputTokens ?? 0,\n )?.totalCost;\n\n // Complete LLM call in execution tree (including cost for automatic aggregation)\n this.tree.completeLLMCall(nodeId, {\n response: result.rawResponse,\n usage: result.usage,\n finishReason: result.finishReason,\n cost: llmCost,\n });\n }\n\n /**\n * Process afterLLMCall controller and return modified final message.\n */\n private async processAfterLLMCallController(\n iteration: number,\n llmOptions: LLMGenerationOptions,\n result: StreamCompletionEvent,\n gadgetCallCount: number,\n ): Promise<string> {\n let finalMessage = result.finalMessage;\n\n if (!this.hooks.controllers?.afterLLMCall) {\n return finalMessage;\n }\n\n const context: AfterLLMCallControllerContext = {\n iteration,\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(extractMessageText(msg.content));\n } else if (msg.role === \"system\") {\n this.conversation.addUserMessage(`[System] ${extractMessageText(msg.content)}`);\n }\n }\n }\n\n return finalMessage;\n }\n\n /**\n * Update conversation history with gadget results or text-only response.\n * @returns true if loop should break (text-only handler requested termination)\n */\n private async updateConversationWithResults(\n didExecuteGadgets: boolean,\n textOutputs: string[],\n gadgetResults: StreamEvent[],\n finalMessage: string,\n ): Promise<boolean> {\n if (didExecuteGadgets) {\n // If configured, wrap accompanying text as a synthetic gadget call\n if (this.textWithGadgetsHandler) {\n const textContent = textOutputs.join(\"\");\n\n if (textContent.trim()) {\n const { gadgetName, parameterMapping, resultMapping } = this.textWithGadgetsHandler;\n const syntheticId = `gc_text_${++this.syntheticInvocationCounter}`;\n this.conversation.addGadgetCallResult(\n gadgetName,\n parameterMapping(textContent),\n resultMapping ? resultMapping(textContent) : textContent,\n syntheticId,\n );\n }\n }\n\n // Add all gadget results to conversation\n for (const output of gadgetResults) {\n if (output.type === \"gadget_result\") {\n const gadgetResult = output.result;\n this.conversation.addGadgetCallResult(\n gadgetResult.gadgetName,\n gadgetResult.parameters,\n gadgetResult.error ?? gadgetResult.result ?? \"\",\n gadgetResult.invocationId,\n gadgetResult.media,\n gadgetResult.mediaIds,\n );\n }\n }\n\n return false; // Don't break loop\n }\n\n // No gadgets executed - wrap text as synthetic TellUser result\n if (finalMessage.trim()) {\n const syntheticId = `gc_tell_${++this.syntheticInvocationCounter}`;\n this.conversation.addGadgetCallResult(\n \"TellUser\",\n { message: finalMessage, done: false, type: \"info\" },\n `ℹ️ ${finalMessage}`,\n syntheticId,\n );\n }\n\n // Handle text-only responses\n return await this.handleTextOnlyResponse(finalMessage);\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 type { ExecutionTree, NodeId } from \"../core/execution-tree.js\";\nimport type { ContentPart, ImageMimeType } from \"../core/input-content.js\";\nimport { detectImageMimeType, text, toBase64 } from \"../core/input-content.js\";\nimport type { MessageContent } from \"../core/messages.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { PromptTemplateConfig } from \"../core/prompt-config.js\";\nimport type { GadgetOrClass } from \"../gadgets/registry.js\";\nimport { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { ExecutionContext, SubagentConfigMap, SubagentEvent, 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 type { RetryConfig } from \"../core/retry.js\";\nimport { collectText, type EventHandlers } from \"./event-handlers.js\";\nimport type { AgentHooks, BeforeLLMCallAction, LLMCallControllerContext } from \"./hooks.js\";\n\n/**\n * Message for conversation history.\n * User messages can be text (string) or multimodal (ContentPart[]).\n */\nexport type HistoryMessage =\n | { user: string | ContentPart[] }\n | { assistant: string }\n | { system: string };\n\n/**\n * Context available to trailing message functions.\n * Provides iteration information for dynamic message generation.\n */\nexport type TrailingMessageContext = Pick<LLMCallControllerContext, \"iteration\" | \"maxIterations\">;\n\n/**\n * Trailing message can be a static string or a function that generates the message.\n * The function receives context about the current iteration.\n */\nexport type TrailingMessage = string | ((ctx: TrailingMessageContext) => 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?: PromptTemplateConfig;\n private gadgets: GadgetOrClass[] = [];\n private initialMessages: Array<{\n role: \"system\" | \"user\" | \"assistant\";\n content: MessageContent;\n }> = [];\n private requestHumanInput?: (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 defaultGadgetTimeoutMs?: number;\n private gadgetOutputLimit?: boolean;\n private gadgetOutputLimitPercent?: number;\n private compactionConfig?: CompactionConfig;\n private retryConfig?: RetryConfig;\n private signal?: AbortSignal;\n private trailingMessage?: TrailingMessage;\n private subagentConfig?: SubagentConfigMap;\n private subagentEventCallback?: (event: SubagentEvent) => void;\n // Tree context for subagent support - enables shared tree model\n // When a gadget calls withParentContext(ctx), it shares the parent's tree\n private parentContext?: {\n depth: number;\n tree?: ExecutionTree;\n nodeId?: NodeId;\n };\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 * .withPromptTemplateConfig({\n * mainInstruction: \"Use the gadget markers below:\",\n * rules: [\"Always use markers\", \"Never use function calling\"]\n * })\n * ```\n */\n withPromptTemplateConfig(config: PromptTemplateConfig): 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 * Clear any previously set conversation history.\n * Used before setting new cumulative history in REPL mode.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Reset history before setting new cumulative history\n * builder.clearHistory().withHistory(cumulativeHistory);\n * ```\n */\n clearHistory(): this {\n this.initialMessages = [];\n return this;\n }\n\n /**\n * Continue conversation from a previous agent's history.\n * Extracts full conversation history and sets it as initial messages.\n *\n * This is the recommended way to implement REPL session continuation.\n * It automatically handles history extraction and format conversion.\n *\n * @param agent - The previous agent to continue from\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // REPL loop with session continuity\n * let previousAgent: Agent | null = null;\n *\n * while (true) {\n * if (previousAgent) {\n * builder.continueFrom(previousAgent);\n * }\n * const agent = builder.ask(prompt);\n * await runAgent(agent);\n * previousAgent = agent;\n * }\n * ```\n */\n continueFrom(agent: Agent): this {\n const history = agent.getConversation().getConversationHistory();\n this.clearHistory();\n\n // Add each message from the previous agent's conversation\n for (const msg of history) {\n if (msg.role === \"user\") {\n this.initialMessages.push({ role: \"user\", content: msg.content });\n } else if (msg.role === \"assistant\") {\n this.initialMessages.push({ role: \"assistant\", content: msg.content });\n }\n // Skip system messages - they're regenerated from the builder's config\n }\n\n return this;\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.requestHumanInput = 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 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 * Configure retry behavior for LLM API calls.\n *\n * Retry is enabled by default with conservative settings (3 retries, exponential backoff).\n * Use this method to customize retry behavior for rate limits, timeouts, and transient errors.\n *\n * @param config - Retry configuration options\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Custom retry configuration\n * .withRetry({\n * retries: 5,\n * minTimeout: 2000,\n * maxTimeout: 60000,\n * })\n *\n * // With monitoring callbacks\n * .withRetry({\n * onRetry: (error, attempt) => {\n * console.log(`Retry ${attempt}: ${error.message}`);\n * },\n * onRetriesExhausted: (error, attempts) => {\n * alerting.warn(`Failed after ${attempts} attempts`);\n * }\n * })\n *\n * // Custom retry logic\n * .withRetry({\n * shouldRetry: (error) => error.message.includes('429'),\n * })\n * ```\n */\n withRetry(config: RetryConfig): this {\n this.retryConfig = { ...config, enabled: config.enabled ?? true };\n return this;\n }\n\n /**\n * Disable automatic retry for LLM API calls.\n *\n * By default, retry is enabled. Use this method to explicitly disable it.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withoutRetry() // Disable automatic retry\n * ```\n */\n withoutRetry(): this {\n this.retryConfig = { 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 * Set subagent configuration overrides.\n *\n * Subagent gadgets (like BrowseWeb) can read these settings from ExecutionContext\n * to inherit model and other options from the CLI configuration.\n *\n * @param config - Subagent configuration map keyed by gadget name\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withSubagentConfig({\n * BrowseWeb: { model: \"inherit\", maxIterations: 20, headless: true },\n * CodeAnalyzer: { model: \"sonnet\", maxIterations: 10 }\n * })\n * ```\n */\n withSubagentConfig(config: SubagentConfigMap): this {\n this.subagentConfig = config;\n return this;\n }\n\n /**\n * Set the callback for subagent events.\n *\n * Subagent gadgets (like BrowseWeb) can use ExecutionContext.onSubagentEvent\n * to report their internal LLM calls and gadget executions in real-time.\n * This callback receives those events, enabling hierarchical progress display.\n *\n * @param callback - Function to handle subagent events\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withSubagentEventCallback((event) => {\n * if (event.type === \"llm_call_start\") {\n * console.log(` Subagent LLM #${event.event.iteration} starting...`);\n * } else if (event.type === \"gadget_call\") {\n * console.log(` ⏵ ${event.event.call.gadgetName}...`);\n * }\n * })\n * ```\n */\n withSubagentEventCallback(callback: (event: SubagentEvent) => void): this {\n this.subagentEventCallback = callback;\n return this;\n }\n\n /**\n * Enable automatic subagent event forwarding to parent agent.\n *\n * When building a subagent inside a gadget, call this method to automatically\n * forward all LLM calls and gadget events to the parent agent. This enables\n * hierarchical progress display without any manual event handling.\n *\n * The method extracts `invocationId` and `onSubagentEvent` from the execution\n * context and sets up automatic forwarding via hooks and event wrapping.\n *\n * **NEW: Shared Tree Model** - When the parent provides an ExecutionTree via context,\n * the subagent shares that tree instead of creating its own. This enables:\n * - Unified cost tracking across all nesting levels\n * - Automatic media aggregation via `tree.getSubtreeMedia(nodeId)`\n * - Real-time visibility of nested execution in the parent\n *\n * **Signal Forwarding** - When parent context includes a signal, it's automatically\n * forwarded to the subagent for proper cancellation propagation.\n *\n * **Logger Inheritance** - When parent context includes a logger, it's inherited\n * by the subagent for consistent structured logging.\n *\n * @param ctx - ExecutionContext passed to the gadget's execute() method\n * @param depth - Nesting depth (default: 1 for direct child)\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // In a subagent gadget like BrowseWeb - ONE LINE enables auto-forwarding:\n * execute: async (params, ctx) => {\n * const agent = new AgentBuilder(client)\n * .withModel(model)\n * .withGadgets(Navigate, Click, Screenshot)\n * .withParentContext(ctx) // <-- This is all you need!\n * .ask(params.task);\n *\n * for await (const event of agent.run()) {\n * // Events automatically forwarded - just process normally\n * if (event.type === \"text\") {\n * result = event.content;\n * }\n * }\n *\n * // After subagent completes, costs are automatically aggregated\n * // No manual tracking needed - use tree methods:\n * const totalCost = ctx.tree?.getSubtreeCost(ctx.nodeId!);\n * const allMedia = ctx.tree?.getSubtreeMedia(ctx.nodeId!);\n * }\n * ```\n */\n withParentContext(ctx: ExecutionContext, depth = 1): this {\n // Capture tree context for shared tree model\n // This enables subagent events to flow through the parent's tree,\n // giving the TUI (and any tree subscribers) visibility into nested activity\n if (ctx.tree) {\n this.parentContext = {\n tree: ctx.tree,\n nodeId: ctx.nodeId,\n depth,\n };\n }\n\n // Auto-forward abort signal from parent for proper cancellation propagation\n if (ctx.signal && !this.signal) {\n this.signal = ctx.signal;\n }\n\n // Inherit logger from parent context for consistent logging across subagents\n if (ctx.logger && !this.logger) {\n this.logger = ctx.logger;\n }\n\n return this;\n }\n\n /**\n * Add an ephemeral trailing message that appears at the end of each LLM request.\n *\n * The message is NOT persisted to conversation history - it only appears in the\n * current LLM call. This is useful for injecting context-specific instructions\n * or reminders without polluting the conversation history.\n *\n * @param message - Static string or function that generates the message\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Static message\n * .withTrailingMessage(\"Always respond in JSON format.\")\n *\n * // Dynamic message based on iteration\n * .withTrailingMessage((ctx) =>\n * `[Iteration ${ctx.iteration}/${ctx.maxIterations}] Stay focused on the task.`\n * )\n * ```\n */\n withTrailingMessage(message: TrailingMessage): this {\n this.trailingMessage = message;\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, including the invocation ID so the LLM can\n * reference previous calls when building dependencies.\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 * @param invocationId - Invocation ID (shown to LLM so it can reference for dependencies)\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 * 'gc_1'\n * )\n * ```\n */\n withSyntheticGadgetCall(\n gadgetName: string,\n parameters: Record<string, unknown>,\n result: string,\n invocationId: 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 (including invocation ID)\n this.initialMessages.push({\n role: \"assistant\",\n content: `${startPrefix}${gadgetName}:${invocationId}\\n${paramStr}\\n${endPrefix}`,\n });\n\n // User message with result (including invocation ID so LLM can reference it)\n this.initialMessages.push({\n role: \"user\",\n content: `Result (${invocationId}): ${result}`,\n });\n\n return this;\n }\n\n /**\n * Compose the final hooks, including trailing message injection if configured.\n *\n * Note: Subagent event visibility is now handled entirely by the ExecutionTree.\n * When a subagent uses withParentContext(ctx), it shares the parent's tree,\n * and all events are automatically visible to tree subscribers (like the TUI).\n */\n private composeHooks(): AgentHooks | undefined {\n const hooks = this.hooks;\n\n // Handle trailing message injection\n if (!this.trailingMessage) {\n return hooks;\n }\n\n const trailingMsg = this.trailingMessage;\n const existingBeforeLLMCall = hooks?.controllers?.beforeLLMCall;\n\n const trailingMessageController = async (\n ctx: LLMCallControllerContext,\n ): Promise<BeforeLLMCallAction> => {\n // Run existing beforeLLMCall first if present\n const result: BeforeLLMCallAction = existingBeforeLLMCall\n ? await existingBeforeLLMCall(ctx)\n : { action: \"proceed\" };\n\n // If action is \"skip\", don't inject trailing message\n if (result.action === \"skip\") {\n return result;\n }\n\n // Get messages (possibly already modified by existing controller)\n const messages = [...(result.modifiedOptions?.messages || ctx.options.messages)];\n\n // Generate trailing message content\n const content =\n typeof trailingMsg === \"function\"\n ? trailingMsg({ iteration: ctx.iteration, maxIterations: ctx.maxIterations })\n : trailingMsg;\n\n // Append as ephemeral user message\n messages.push({ role: \"user\", content });\n\n return {\n action: \"proceed\",\n modifiedOptions: { ...result.modifiedOptions, messages },\n };\n };\n\n return {\n ...hooks,\n controllers: {\n ...hooks?.controllers,\n beforeLLMCall: trailingMessageController,\n },\n };\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 /**\n * Build AgentOptions with the given user prompt.\n * Centralizes options construction for ask(), askWithImage(), and askWithContent().\n */\n private buildAgentOptions(userPrompt: string | ContentPart[]): AgentOptions {\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\n const registry = GadgetRegistry.from(this.gadgets);\n\n return {\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.composeHooks(),\n promptConfig: this.promptConfig,\n initialMessages: this.initialMessages,\n requestHumanInput: this.requestHumanInput,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n textOnlyHandler: this.textOnlyHandler,\n textWithGadgetsHandler: this.textWithGadgetsHandler,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n gadgetOutputLimit: this.gadgetOutputLimit,\n gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,\n compactionConfig: this.compactionConfig,\n retryConfig: this.retryConfig,\n signal: this.signal,\n subagentConfig: this.subagentConfig,\n onSubagentEvent: this.subagentEventCallback,\n // Tree context for shared tree model (subagents share parent's tree)\n parentTree: this.parentContext?.tree,\n parentNodeId: this.parentContext?.nodeId,\n baseDepth: this.parentContext ? (this.parentContext.depth ?? 0) + 1 : 0,\n };\n }\n\n ask(userPrompt: string): Agent {\n const options = this.buildAgentOptions(userPrompt);\n return new Agent(AGENT_INTERNAL_KEY, options);\n }\n\n /**\n * Build and create the agent with a multimodal user prompt (text + image).\n * Returns the Agent instance ready to run.\n *\n * @param textPrompt - Text prompt describing what to do with the image\n * @param imageData - Image data (Buffer, Uint8Array, or base64 string)\n * @param mimeType - Optional MIME type (auto-detected if not provided)\n * @returns Configured Agent instance\n *\n * @example\n * ```typescript\n * const agent = LLMist.createAgent()\n * .withModel(\"gpt-4o\")\n * .withSystem(\"You analyze images\")\n * .askWithImage(\n * \"What's in this image?\",\n * await fs.readFile(\"photo.jpg\")\n * );\n *\n * for await (const event of agent.run()) {\n * // handle events\n * }\n * ```\n */\n askWithImage(\n textPrompt: string,\n imageData: Buffer | Uint8Array | string,\n mimeType?: ImageMimeType,\n ): Agent {\n const imageBuffer =\n typeof imageData === \"string\" ? Buffer.from(imageData, \"base64\") : imageData;\n const detectedMime = mimeType ?? detectImageMimeType(imageBuffer);\n\n if (!detectedMime) {\n throw new Error(\n \"Could not detect image MIME type. Please provide the mimeType parameter explicitly.\",\n );\n }\n\n // Build multimodal content\n const userContent: ContentPart[] = [\n text(textPrompt),\n {\n type: \"image\",\n source: {\n type: \"base64\",\n mediaType: detectedMime,\n data: toBase64(imageBuffer),\n },\n },\n ];\n\n const options = this.buildAgentOptions(userContent);\n return new Agent(AGENT_INTERNAL_KEY, options);\n }\n\n /**\n * Build and return an Agent configured with multimodal content.\n * More flexible than askWithImage - accepts any combination of content parts.\n *\n * @param content - Array of content parts (text, images, audio)\n * @returns A configured Agent ready for execution\n *\n * @example\n * ```typescript\n * import { text, imageFromBuffer, audioFromBuffer } from \"llmist\";\n *\n * const agent = LLMist.createAgent()\n * .withModel(\"gemini:gemini-2.5-flash\")\n * .askWithContent([\n * text(\"Describe this image and transcribe the audio:\"),\n * imageFromBuffer(imageData),\n * audioFromBuffer(audioData),\n * ]);\n *\n * for await (const event of agent.run()) {\n * // handle events\n * }\n * ```\n */\n askWithContent(content: ContentPart[]): Agent {\n const options = this.buildAgentOptions(content);\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.composeHooks(),\n promptConfig: this.promptConfig,\n initialMessages: this.initialMessages,\n requestHumanInput: this.requestHumanInput,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n textOnlyHandler: this.textOnlyHandler,\n textWithGadgetsHandler: this.textWithGadgetsHandler,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n gadgetOutputLimit: this.gadgetOutputLimit,\n gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,\n compactionConfig: this.compactionConfig,\n retryConfig: this.retryConfig,\n signal: this.signal,\n subagentConfig: this.subagentConfig,\n onSubagentEvent: this.subagentEventCallback,\n // Tree context for shared tree model (subagents share parent's tree)\n parentTree: this.parentContext?.tree,\n parentNodeId: this.parentContext?.nodeId,\n baseDepth: this.parentContext ? (this.parentContext.depth ?? 0) + 1 : 0,\n };\n\n return new Agent(AGENT_INTERNAL_KEY, options);\n }\n}\n","// Re-export Zod's z for schema definitions\n// Using llmist's z ensures .describe() metadata is preserved in JSON schemas\nexport { z } from \"zod\";\n// Constants for gadget block format parsing\nexport {\n GADGET_ARG_PREFIX,\n GADGET_END_PREFIX,\n GADGET_START_PREFIX,\n} from \"./core/constants.js\";\n// Provider constants (for token estimation)\nexport { FALLBACK_CHARS_PER_TOKEN } from \"./providers/constants.js\";\n// Syntactic sugar: Agent builder and event handlers\nexport type { HistoryMessage, TrailingMessage, TrailingMessageContext } from \"./agent/builder.js\";\nexport { AgentBuilder } from \"./agent/builder.js\";\nexport type { EventHandlers } from \"./agent/event-handlers.js\";\nexport { collectEvents, collectText, runWithHandlers } from \"./agent/event-handlers.js\";\n// Syntactic sugar: Hook presets\nexport type { LoggingOptions } from \"./agent/hook-presets.js\";\nexport { HookPresets } from \"./agent/hook-presets.js\";\n// Agent infrastructure\n// New clean hooks system\nexport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n AgentOptions,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n // Interceptor contexts\n ChunkInterceptorContext,\n // Context compaction\n CompactionConfig,\n CompactionContext,\n CompactionEvent,\n CompactionResult,\n CompactionStats,\n CompactionStrategy,\n Controllers,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n // LLM Assistance Hints\n HintsConfig,\n IConversationManager,\n Interceptors,\n IterationHintOptions,\n // Controller contexts and actions\n LLMCallControllerContext,\n LLMErrorControllerContext,\n MessageInterceptorContext,\n MessageTurn,\n ObserveChunkContext,\n ObserveCompactionContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetStartContext,\n // Observer contexts\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n Observers,\n ParallelGadgetHintOptions,\n ResolvedCompactionConfig,\n // Gadget output limiting\n StoredOutput,\n StreamProcessingResult,\n StreamProcessorOptions,\n // Subagent context for hook observers\n SubagentContext,\n} from \"./agent/index.js\";\nexport {\n // Compaction exports\n CompactionManager,\n // Existing exports\n ConversationManager,\n // LLM Assistance Hints\n createHints,\n DEFAULT_COMPACTION_CONFIG,\n DEFAULT_SUMMARIZATION_PROMPT,\n GadgetOutputStore,\n HybridStrategy,\n iterationProgressHint,\n parallelGadgetHint,\n SlidingWindowStrategy,\n StreamProcessor,\n SummarizationStrategy,\n} from \"./agent/index.js\";\nexport type { LLMistOptions } from \"./core/client.js\";\nexport { LLMist } from \"./core/client.js\";\n// Error utilities\nexport { isAbortError } from \"./core/errors.js\";\n// Agent class (for type references)\nexport { Agent } from \"./agent/agent.js\";\n\n// Retry configuration for LLM API calls\nexport type { RetryConfig, ResolvedRetryConfig } from \"./core/retry.js\";\nexport {\n DEFAULT_RETRY_CONFIG,\n formatLLMError,\n isRetryableError,\n resolveRetryConfig,\n} from \"./core/retry.js\";\n\n// Execution Tree - first-class model for nested subagent support\nexport type {\n AddGadgetParams,\n AddLLMCallParams,\n CompleteGadgetParams,\n CompleteLLMCallParams,\n ExecutionNode,\n ExecutionNodeType,\n GadgetNode,\n GadgetState,\n LLMCallNode,\n NodeId,\n} from \"./core/execution-tree.js\";\nexport { ExecutionTree } from \"./core/execution-tree.js\";\n\n// Unified execution events with tree context\nexport type {\n BaseExecutionEvent,\n CompactionEvent as TreeCompactionEvent,\n ExecutionEvent,\n ExecutionEventType,\n GadgetCallEvent,\n GadgetCompleteEvent,\n GadgetErrorEvent,\n GadgetEvent,\n GadgetSkippedEvent as TreeGadgetSkippedEvent,\n GadgetStartEvent,\n HumanInputRequiredEvent,\n LLMCallCompleteEvent,\n LLMCallErrorEvent,\n LLMCallStartEvent,\n LLMCallStreamEvent,\n LLMEvent,\n StreamCompleteEvent,\n TextEvent,\n} from \"./core/execution-events.js\";\nexport {\n filterByDepth,\n filterByParent,\n filterRootEvents,\n groupByParent,\n isGadgetEvent,\n isLLMEvent,\n isRootEvent,\n isSubagentEvent,\n} from \"./core/execution-events.js\";\n\n// Input content types for multimodal messages\nexport type {\n AudioContentPart,\n AudioMimeType,\n AudioSource,\n ContentPart,\n ImageBase64Source,\n ImageContentPart,\n ImageMimeType,\n ImageSource,\n ImageUrlSource,\n TextContentPart,\n} from \"./core/input-content.js\";\nexport {\n audioFromBase64,\n audioFromBuffer,\n detectAudioMimeType,\n detectImageMimeType,\n imageFromBase64,\n imageFromBuffer,\n imageFromUrl,\n isAudioPart,\n isDataUrl,\n isImagePart,\n isTextPart,\n parseDataUrl,\n text,\n toBase64,\n} from \"./core/input-content.js\";\n\nexport type { LLMMessage, MessageContent, MessageRole } from \"./core/messages.js\";\nexport { extractMessageText, LLMMessageBuilder, normalizeMessageContent } from \"./core/messages.js\";\n// Model catalog\nexport type {\n CostEstimate,\n ModelFeatures,\n ModelLimits,\n ModelPricing,\n ModelSpec,\n} from \"./core/model-catalog.js\";\nexport { ModelRegistry } from \"./core/model-registry.js\";\n// Syntactic sugar: Model shortcuts and quick methods\nexport {\n getModelId,\n getProvider,\n hasProviderPrefix,\n MODEL_ALIASES,\n resolveModel,\n} from \"./core/model-shortcuts.js\";\n// Vision namespace for one-shot image analysis\nexport type { VisionAnalyzeOptions, VisionAnalyzeResult } from \"./core/namespaces/vision.js\";\n// Media generation types (image, speech)\nexport type {\n ImageGenerationOptions,\n ImageGenerationResult,\n ImageModelSpec,\n SpeechGenerationOptions,\n SpeechGenerationResult,\n SpeechModelSpec,\n} from \"./core/media-types.js\";\nexport type {\n LLMGenerationOptions,\n LLMStream,\n LLMStreamChunk,\n ModelDescriptor,\n ProviderIdentifier,\n TokenUsage,\n} from \"./core/options.js\";\nexport { ModelIdentifierParser } from \"./core/options.js\";\nexport type {\n HintContext,\n HintTemplate,\n PromptContext,\n PromptTemplate,\n PromptTemplateConfig,\n} from \"./core/prompt-config.js\";\nexport {\n DEFAULT_HINTS,\n DEFAULT_PROMPTS,\n resolveHintTemplate,\n resolvePromptTemplate,\n resolveRulesTemplate,\n} from \"./core/prompt-config.js\";\nexport type { TextGenerationOptions } from \"./core/quick-methods.js\";\nexport { complete, stream } from \"./core/quick-methods.js\";\nexport type { CreateGadgetConfig } from \"./gadgets/create-gadget.js\";\nexport { createGadget } from \"./gadgets/create-gadget.js\";\n// Gadget infrastructure\nexport {\n AbortException,\n HumanInputRequiredException,\n TaskCompletionSignal,\n TimeoutException,\n} from \"./gadgets/exceptions.js\";\nexport { GadgetExecutor } from \"./gadgets/executor.js\";\nexport { AbstractGadget } from \"./gadgets/gadget.js\";\n// Gadget output viewer (for custom output store integration)\nexport { createGadgetOutputViewer } from \"./gadgets/output-viewer.js\";\nexport { GadgetCallParser } from \"./gadgets/parser.js\";\nexport type { GadgetClass, GadgetOrClass } from \"./gadgets/registry.js\";\nexport { GadgetRegistry } from \"./gadgets/registry.js\";\n\n// Syntactic sugar: Typed gadgets and helpers\nexport type { GadgetConfig } from \"./gadgets/typed-gadget.js\";\nexport { Gadget } from \"./gadgets/typed-gadget.js\";\nexport type {\n CostReportingLLMist,\n ExecutionContext,\n GadgetExample,\n GadgetExecuteResult,\n GadgetExecuteResultWithMedia,\n GadgetExecuteReturn,\n GadgetExecutionResult,\n GadgetMediaOutput,\n GadgetSkippedEvent,\n // Host exports for external gadgets\n HostExports,\n // Subagent LLM call info (for CLI/TUI display)\n LLMCallInfo,\n MediaKind,\n MediaMetadata,\n ParsedGadgetCall,\n StoredMedia,\n StreamEvent,\n // Subagent config types\n SubagentConfig,\n SubagentConfigMap,\n // Subagent event types\n SubagentEvent,\n SubagentStreamEvent,\n TextOnlyAction,\n TextOnlyContext,\n TextOnlyCustomHandler,\n TextOnlyGadgetConfig,\n TextOnlyHandler,\n TextOnlyStrategy,\n} from \"./gadgets/types.js\";\n// Response and media output helpers for gadgets\nexport {\n // Response formatting\n gadgetError,\n gadgetSuccess,\n getErrorMessage,\n withErrorHandling,\n // Media output\n createMediaOutput,\n resultWithAudio,\n resultWithFile,\n resultWithImage,\n resultWithImages,\n resultWithMedia,\n} from \"./gadgets/helpers.js\";\n\n// Host exports helper for external gadgets\nimport type { ExecutionContext, HostExports } from \"./gadgets/types.js\";\n\n/**\n * Get host llmist exports from execution context.\n *\n * External gadgets MUST use this instead of importing classes directly from 'llmist'\n * to ensure they use the same version as the host CLI, enabling proper tree sharing\n * and avoiding the \"dual-package problem\".\n *\n * @param ctx - The execution context passed to gadget.execute()\n * @returns The host's llmist exports (AgentBuilder, Gadget, etc.)\n * @throws Error if ctx or ctx.hostExports is undefined\n *\n * @example\n * ```typescript\n * import { getHostExports, Gadget, z } from 'llmist';\n * import type { ExecutionContext } from 'llmist';\n *\n * class BrowseWeb extends Gadget({\n * name: 'BrowseWeb',\n * description: 'Browse a website autonomously',\n * schema: z.object({ task: z.string(), url: z.string() }),\n * }) {\n * async execute(params: this['params'], ctx?: ExecutionContext) {\n * // Get host's AgentBuilder to ensure tree sharing works correctly\n * const { AgentBuilder } = getHostExports(ctx!);\n *\n * const agent = new AgentBuilder()\n * .withParentContext(ctx!)\n * .withGadgets(Navigate, Click, Screenshot)\n * .ask(params.task);\n *\n * for await (const event of agent.run()) {\n * // Events flow through host's shared tree\n * }\n * }\n * }\n * ```\n */\nexport function getHostExports(ctx: ExecutionContext): HostExports {\n if (!ctx?.hostExports) {\n throw new Error(\n \"hostExports not available. Gadgets that create subagents must be run \" +\n \"via llmist agent, not standalone. Ensure you are using llmist >= 6.2.0.\",\n );\n }\n return ctx.hostExports;\n}\n// Media storage for gadget outputs\nexport { MediaStore } from \"./gadgets/media-store.js\";\nexport type { ValidationIssue, ValidationResult } from \"./gadgets/validation.js\";\nexport { validateAndApplyDefaults, validateGadgetParams } from \"./gadgets/validation.js\";\n// Schema utilities\nexport { schemaToJSONSchema } from \"./gadgets/schema-to-json.js\";\nexport { validateGadgetSchema } from \"./gadgets/schema-validator.js\";\nexport type { LoggerOptions } from \"./logging/logger.js\";\nexport { createLogger, defaultLogger } from \"./logging/logger.js\";\n// Re-export Logger type for external gadgets that need to type ctx.logger\nexport type { ILogObj, Logger } from \"tslog\";\n\n// Utility functions for subagent gadgets\nexport type { ResolveValueOptions } from \"./utils/config-resolver.js\";\nexport {\n resolveConfig,\n resolveSubagentModel,\n resolveSubagentTimeout,\n resolveValue,\n} from \"./utils/config-resolver.js\";\nexport {\n AnthropicMessagesProvider,\n createAnthropicProviderFromEnv,\n} from \"./providers/anthropic.js\";\nexport { discoverProviderAdapters } from \"./providers/discovery.js\";\nexport { createGeminiProviderFromEnv, GeminiGenerativeProvider } from \"./providers/gemini.js\";\nexport { createOpenAIProviderFromEnv, OpenAIChatProvider } from \"./providers/openai.js\";\nexport type { ProviderAdapter } from \"./providers/provider.js\";\n\n// ============================================================================\n// Formatting Utilities\n// ============================================================================\nexport {\n format,\n formatBytes,\n formatDate,\n formatDuration,\n truncate,\n} from \"./utils/format.js\";\n\n// ============================================================================\n// Timing Utilities\n// ============================================================================\nexport type { RetryOptions } from \"./utils/timing.js\";\nexport {\n humanDelay,\n randomDelay,\n timing,\n withRetry,\n withTimeout,\n} from \"./utils/timing.js\";\n\n// ============================================================================\n// Session Management\n// ============================================================================\nexport type { ISessionManager } from \"./session/index.js\";\nexport { BaseSessionManager, SimpleSessionManager } from \"./session/index.js\";\n\n// ============================================================================\n// Subagent Helpers\n// ============================================================================\nexport type { SubagentOptions } from \"./agent/subagent.js\";\nexport { createSubagent, hasHostExports } from \"./agent/subagent.js\";\n\n// ============================================================================\n// Package Manifest Types\n// ============================================================================\nexport type {\n GadgetFactoryExports,\n LLMistPackageManifest,\n PresetDefinition,\n SessionManifestEntry,\n SubagentManifestEntry,\n} from \"./package/index.js\";\nexport {\n getPresetGadgets,\n getSubagent,\n hasPreset,\n hasSubagents,\n listPresets,\n listSubagents,\n parseManifest,\n} from \"./package/index.js\";\n","/**\n * Ready-to-use hook configurations for common monitoring, logging, and debugging tasks.\n *\n * HookPresets provide instant observability without writing custom hooks. They're the\n * fastest way to add monitoring to your agents during development and production.\n *\n * ## Available Presets\n *\n * - **logging(options?)** - Log LLM calls and gadget execution\n * - **timing()** - Measure execution time for operations\n * - **tokenTracking()** - Track cumulative token usage and costs\n * - **progressTracking(options?)** - Track progress with iterations, tokens, cost, and timing (SHOWCASE)\n * - **errorLogging()** - Log detailed error information\n * - **silent()** - No output (useful for testing)\n * - **monitoring(options?)** - All-in-one preset combining logging, timing, tokens, and errors\n * - **merge(...hookSets)** - Combine multiple hook configurations\n *\n * ## Quick Start\n *\n * @example\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * // Basic logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging())\n * .ask(\"Your prompt\");\n *\n * // Full monitoring suite (recommended for development)\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring({ verbose: true }))\n * .ask(\"Your prompt\");\n *\n * // Combine multiple presets\n * await LLMist.createAgent()\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * .ask(\"Your prompt\");\n *\n * // Environment-based configuration\n * const hooks = process.env.NODE_ENV === 'production'\n * ? HookPresets.merge(HookPresets.errorLogging(), HookPresets.tokenTracking())\n * : HookPresets.monitoring({ verbose: true });\n *\n * await LLMist.createAgent()\n * .withHooks(hooks)\n * .ask(\"Your prompt\");\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md | Full documentation}\n */\n\nimport type { ModelRegistry } from \"../core/model-registry.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n/**\n * Options for logging preset.\n */\nexport interface LoggingOptions {\n /** Include verbose details like parameters and results */\n verbose?: boolean;\n}\n\n/**\n * Progress statistics reported by progressTracking preset.\n *\n * Contains cumulative metrics across all LLM calls in the agent session,\n * useful for building progress UI, cost monitoring, and performance tracking.\n */\nexport interface ProgressStats {\n /** Current iteration number (increments on each LLM call start) */\n currentIteration: number;\n\n /** Total number of completed LLM calls */\n totalCalls: number;\n\n /** Cumulative input tokens across all calls */\n totalInputTokens: number;\n\n /** Cumulative output tokens across all calls */\n totalOutputTokens: number;\n\n /** Total tokens (input + output) */\n totalTokens: number;\n\n /** Cumulative cost in USD (includes LLM and gadget costs; requires modelRegistry for LLM cost estimation) */\n totalCost: number;\n\n /** Elapsed time in seconds since first call */\n elapsedSeconds: number;\n}\n\n/**\n * Options for progressTracking preset.\n *\n * Controls how progress data is tracked and reported during agent execution.\n */\nexport interface ProgressTrackingOptions {\n /**\n * Model registry for cost calculation.\n *\n * If provided, enables automatic cost estimation based on token usage\n * and model pricing data. Without it, totalCost will always be 0.\n *\n * @example\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * const client = LLMist.create();\n * const hooks = HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry // Enable cost tracking\n * });\n * ```\n */\n modelRegistry?: ModelRegistry;\n\n /**\n * Callback invoked after each LLM call completion with cumulative stats.\n *\n * Use this to update progress UI, log metrics, or track budgets in real-time.\n *\n * @example\n * ```typescript\n * HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * console.log(`Iteration #${stats.currentIteration}`);\n * console.log(`Cost so far: $${stats.totalCost.toFixed(4)}`);\n * console.log(`Elapsed: ${stats.elapsedSeconds}s`);\n * }\n * })\n * ```\n */\n onProgress?: (stats: ProgressStats) => void;\n\n /**\n * Whether to log progress to console after each LLM call.\n *\n * When enabled, prints a summary line with tokens, cost, and elapsed time.\n * Useful for quick debugging without implementing a custom callback.\n *\n * Default: false\n *\n * @example\n * ```typescript\n * // Quick console-based progress tracking\n * HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * logProgress: true // Log to console\n * })\n * // Output: 📊 Progress: Iteration #2 | 1,234 tokens | $0.0056 | 12.3s\n * ```\n */\n logProgress?: boolean;\n}\n\n/**\n * Common hook presets.\n */\nexport class HookPresets {\n /**\n * Logs LLM calls and gadget execution to console with optional verbosity.\n *\n * **Output (basic mode):**\n * - LLM call start/complete events with iteration numbers\n * - Gadget execution start/complete with gadget names\n * - Token counts when available\n *\n * **Output (verbose mode):**\n * - All basic mode output\n * - Full gadget parameters (formatted JSON)\n * - Full gadget results\n * - Complete LLM response text\n *\n * **Use cases:**\n * - Basic development debugging and execution flow visibility\n * - Understanding agent decision-making and tool usage\n * - Troubleshooting gadget invocations\n *\n * **Performance:** Minimal overhead. Console writes are synchronous but fast.\n *\n * @param options - Logging options\n * @param options.verbose - Include full parameters and results. Default: false\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging())\n * .ask(\"Calculate 15 * 23\");\n * // Output: [LLM] Starting call (iteration 0)\n * // [GADGET] Executing Calculator\n * // [GADGET] Completed Calculator\n * // [LLM] Completed (tokens: 245)\n * ```\n *\n * @example\n * ```typescript\n * // Verbose logging with full details\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging({ verbose: true }))\n * .ask(\"Calculate 15 * 23\");\n * // Output includes: parameters, results, and full responses\n * ```\n *\n * @example\n * ```typescript\n * // Environment-based verbosity\n * const isDev = process.env.NODE_ENV === 'development';\n * .withHooks(HookPresets.logging({ verbose: isDev }))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsloggingoptions | Full documentation}\n */\n static logging(options: LoggingOptions = {}): AgentHooks {\n return {\n observers: {\n onLLMCallStart: async (ctx) => {\n console.log(`[LLM] Starting call (iteration ${ctx.iteration})`);\n },\n onLLMCallComplete: async (ctx) => {\n const tokens = ctx.usage?.totalTokens ?? \"unknown\";\n console.log(`[LLM] Completed (tokens: ${tokens})`);\n if (options.verbose && ctx.finalMessage) {\n console.log(`[LLM] Response: ${ctx.finalMessage}`);\n }\n },\n onGadgetExecutionStart: async (ctx) => {\n console.log(`[GADGET] Executing ${ctx.gadgetName}`);\n if (options.verbose) {\n console.log(`[GADGET] Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n }\n },\n onGadgetExecutionComplete: async (ctx) => {\n console.log(`[GADGET] Completed ${ctx.gadgetName}`);\n if (options.verbose) {\n const display = ctx.error ?? ctx.finalResult ?? \"(no result)\";\n console.log(`[GADGET] Result: ${display}`);\n }\n },\n },\n };\n }\n\n /**\n * Measures and logs execution time for LLM calls and gadgets.\n *\n * **Output:**\n * - Duration in milliseconds with ⏱️ emoji for each operation\n * - Separate timing for each LLM iteration\n * - Separate timing for each gadget execution\n *\n * **Use cases:**\n * - Performance profiling and optimization\n * - Identifying slow operations (LLM calls vs gadget execution)\n * - Monitoring response times in production\n * - Capacity planning and SLA tracking\n *\n * **Performance:** Negligible overhead. Uses Date.now() for timing measurements.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic timing\n * await LLMist.createAgent()\n * .withHooks(HookPresets.timing())\n * .withGadgets(Weather, Database)\n * .ask(\"What's the weather in NYC?\");\n * // Output: ⏱️ LLM call took 1234ms\n * // ⏱️ Gadget Weather took 567ms\n * // ⏱️ LLM call took 890ms\n * ```\n *\n * @example\n * ```typescript\n * // Combined with logging for full context\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing()\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Correlate performance with cost\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstiming | Full documentation}\n */\n static timing(): AgentHooks {\n const timings = new Map<string, number>();\n\n return {\n observers: {\n onLLMCallStart: async (ctx) => {\n timings.set(`llm-${ctx.iteration}`, Date.now());\n },\n onLLMCallComplete: async (ctx) => {\n const start = timings.get(`llm-${ctx.iteration}`);\n if (start) {\n const duration = Date.now() - start;\n console.log(`⏱️ LLM call took ${duration}ms`);\n timings.delete(`llm-${ctx.iteration}`);\n }\n },\n onGadgetExecutionStart: async (ctx) => {\n const key = `gadget-${ctx.gadgetName}-${Date.now()}`;\n timings.set(key, Date.now());\n // Store key for lookup in complete handler\n (ctx as any)._timingKey = key;\n },\n onGadgetExecutionComplete: async (ctx) => {\n const key = (ctx as any)._timingKey;\n if (key) {\n const start = timings.get(key);\n if (start) {\n const duration = Date.now() - start;\n console.log(`⏱️ Gadget ${ctx.gadgetName} took ${duration}ms`);\n timings.delete(key);\n }\n }\n },\n },\n };\n }\n\n /**\n * Tracks cumulative token usage across all LLM calls.\n *\n * **Output:**\n * - Per-call token count with 📊 emoji\n * - Cumulative total across all calls\n * - Call count for average calculations\n *\n * **Use cases:**\n * - Cost monitoring and budget tracking\n * - Optimizing prompts to reduce token usage\n * - Comparing token efficiency across different approaches\n * - Real-time cost estimation\n *\n * **Performance:** Minimal overhead. Simple counter increments.\n *\n * **Note:** Token counts depend on the provider's response. Some providers\n * may not include usage data, in which case counts won't be logged.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic token tracking\n * await LLMist.createAgent()\n * .withHooks(HookPresets.tokenTracking())\n * .ask(\"Summarize this document...\");\n * // Output: 📊 Tokens this call: 1,234\n * // 📊 Total tokens: 1,234 (across 1 calls)\n * // 📊 Tokens this call: 567\n * // 📊 Total tokens: 1,801 (across 2 calls)\n * ```\n *\n * @example\n * ```typescript\n * // Cost calculation with custom hook\n * let totalTokens = 0;\n * .withHooks(HookPresets.merge(\n * HookPresets.tokenTracking(),\n * {\n * observers: {\n * onLLMCallComplete: async (ctx) => {\n * totalTokens += ctx.usage?.totalTokens ?? 0;\n * const cost = (totalTokens / 1_000_000) * 3.0; // $3 per 1M tokens\n * console.log(`💰 Estimated cost: $${cost.toFixed(4)}`);\n * },\n * },\n * }\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstokentracking | Full documentation}\n */\n static tokenTracking(): AgentHooks {\n let totalTokens = 0;\n let totalCalls = 0;\n\n return {\n observers: {\n onLLMCallComplete: async (ctx) => {\n totalCalls++;\n if (ctx.usage?.totalTokens) {\n totalTokens += ctx.usage.totalTokens;\n console.log(`📊 Tokens this call: ${ctx.usage.totalTokens}`);\n console.log(`📊 Total tokens: ${totalTokens} (across ${totalCalls} calls)`);\n }\n },\n },\n };\n }\n\n /**\n * Tracks comprehensive progress metrics including iterations, tokens, cost, and timing.\n *\n * **This preset showcases llmist's core capabilities by demonstrating:**\n * - Observer pattern for non-intrusive monitoring\n * - Integration with ModelRegistry for cost estimation\n * - Callback-based architecture for flexible UI updates\n * - Provider-agnostic token and cost tracking\n *\n * Unlike `tokenTracking()` which only logs to console, this preset provides\n * structured data through callbacks, making it perfect for building custom UIs,\n * dashboards, or progress indicators (like the llmist CLI).\n *\n * **Output (when logProgress: true):**\n * - Iteration number and call count\n * - Cumulative token usage (input + output)\n * - Cumulative cost in USD (requires modelRegistry)\n * - Elapsed time in seconds\n *\n * **Use cases:**\n * - Building CLI progress indicators with live updates\n * - Creating web dashboards with real-time metrics\n * - Budget monitoring and cost alerts\n * - Performance tracking and optimization\n * - Custom logging to external systems (Datadog, CloudWatch, etc.)\n *\n * **Performance:** Minimal overhead. Uses Date.now() for timing and optional\n * ModelRegistry.estimateCost() which is O(1) lookup. Callback invocation is\n * synchronous and fast.\n *\n * @param options - Progress tracking options\n * @param options.modelRegistry - ModelRegistry for cost estimation (optional)\n * @param options.onProgress - Callback invoked after each LLM call (optional)\n * @param options.logProgress - Log progress to console (default: false)\n * @returns Hook configuration with progress tracking observers\n *\n * @example\n * ```typescript\n * // Basic usage with callback (RECOMMENDED - used by llmist CLI)\n * import { LLMist, HookPresets } from 'llmist';\n *\n * const client = LLMist.create();\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * // Update your UI with stats\n * console.log(`#${stats.currentIteration} | ${stats.totalTokens} tokens | $${stats.totalCost.toFixed(4)}`);\n * }\n * }))\n * .withGadgets(Calculator)\n * .ask(\"Calculate 15 * 23\");\n * // Output: #1 | 245 tokens | $0.0012\n * ```\n *\n * @example\n * ```typescript\n * // Console logging mode (quick debugging)\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * logProgress: true // Simple console output\n * }))\n * .ask(\"Your prompt\");\n * // Output: 📊 Progress: Iteration #1 | 245 tokens | $0.0012 | 1.2s\n * ```\n *\n * @example\n * ```typescript\n * // Budget monitoring with alerts\n * const BUDGET_USD = 0.10;\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * if (stats.totalCost > BUDGET_USD) {\n * throw new Error(`Budget exceeded: $${stats.totalCost.toFixed(4)}`);\n * }\n * }\n * }))\n * .ask(\"Long running task...\");\n * ```\n *\n * @example\n * ```typescript\n * // Web dashboard integration\n * let progressBar: HTMLElement;\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * // Update web UI in real-time\n * progressBar.textContent = `Iteration ${stats.currentIteration}`;\n * progressBar.dataset.cost = stats.totalCost.toFixed(4);\n * progressBar.dataset.tokens = stats.totalTokens.toString();\n * }\n * }))\n * .ask(\"Your prompt\");\n * ```\n *\n * @example\n * ```typescript\n * // External logging (Datadog, CloudWatch, etc.)\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: async (stats) => {\n * await metrics.gauge('llm.iteration', stats.currentIteration);\n * await metrics.gauge('llm.cost', stats.totalCost);\n * await metrics.gauge('llm.tokens', stats.totalTokens);\n * }\n * }))\n * .ask(\"Your prompt\");\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsprogresstrackingoptions | Full documentation}\n * @see {@link ProgressTrackingOptions} for detailed options\n * @see {@link ProgressStats} for the callback data structure\n */\n static progressTracking(options?: ProgressTrackingOptions): AgentHooks {\n const { modelRegistry, onProgress, logProgress = false } = options ?? {};\n\n // State tracking - follows same pattern as tokenTracking()\n let totalCalls = 0;\n let currentIteration = 0;\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCost = 0;\n let totalGadgetCost = 0;\n const startTime = Date.now();\n\n return {\n observers: {\n // Track iteration on each LLM call start\n onLLMCallStart: async (ctx) => {\n currentIteration++;\n },\n\n // Accumulate metrics and report progress on each LLM call completion\n onLLMCallComplete: async (ctx) => {\n totalCalls++;\n\n // Track token usage from provider response\n if (ctx.usage) {\n totalInputTokens += ctx.usage.inputTokens;\n totalOutputTokens += ctx.usage.outputTokens;\n\n // Calculate cost using ModelRegistry (core llmist feature)\n // This showcases integration with llmist's pricing catalog\n if (modelRegistry) {\n try {\n // Extract model name from provider:model format\n // Example: \"openai:gpt-4o\" -> \"gpt-4o\"\n const modelName = ctx.options.model.includes(\":\")\n ? ctx.options.model.split(\":\")[1]\n : ctx.options.model;\n\n // Use core's estimateCost() for accurate pricing\n const costEstimate = modelRegistry.estimateCost(\n modelName,\n ctx.usage.inputTokens,\n ctx.usage.outputTokens,\n );\n\n if (costEstimate) {\n totalCost += costEstimate.totalCost;\n }\n } catch (error) {\n // Graceful degradation - log error but don't crash\n // This follows llmist's principle of non-intrusive monitoring\n if (logProgress) {\n console.warn(`⚠️ Cost estimation failed:`, error);\n }\n }\n }\n }\n\n // Build comprehensive progress stats (LLM + gadget costs combined)\n const stats: ProgressStats = {\n currentIteration,\n totalCalls,\n totalInputTokens,\n totalOutputTokens,\n totalTokens: totalInputTokens + totalOutputTokens,\n totalCost: totalCost + totalGadgetCost,\n elapsedSeconds: Number(((Date.now() - startTime) / 1000).toFixed(1)),\n };\n\n // Invoke callback if provided (used by CLI and custom UIs)\n if (onProgress) {\n onProgress(stats);\n }\n\n // Optional console logging for quick debugging\n if (logProgress) {\n const formattedTokens =\n stats.totalTokens >= 1000\n ? `${(stats.totalTokens / 1000).toFixed(1)}k`\n : `${stats.totalTokens}`;\n\n const formattedCost = stats.totalCost > 0 ? `$${stats.totalCost.toFixed(4)}` : \"$0\";\n\n console.log(\n `📊 Progress: Iteration #${stats.currentIteration} | ${formattedTokens} tokens | ${formattedCost} | ${stats.elapsedSeconds}s`,\n );\n }\n },\n\n // Track gadget execution costs\n onGadgetExecutionComplete: async (ctx) => {\n if (ctx.cost && ctx.cost > 0) {\n totalGadgetCost += ctx.cost;\n }\n },\n },\n };\n }\n\n /**\n * Logs detailed error information for debugging and troubleshooting.\n *\n * **Output:**\n * - LLM errors with ❌ emoji, including model and recovery status\n * - Gadget errors with full context (parameters, error message)\n * - Separate logging for LLM and gadget failures\n *\n * **Use cases:**\n * - Troubleshooting production issues\n * - Understanding error patterns and frequency\n * - Debugging error recovery behavior\n * - Collecting error metrics for monitoring\n *\n * **Performance:** Minimal overhead. Only logs when errors occur.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic error logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.errorLogging())\n * .withGadgets(Database)\n * .ask(\"Fetch user data\");\n * // Output (on LLM error): ❌ LLM Error (iteration 1): Rate limit exceeded\n * // Model: gpt-5-nano\n * // Recovered: true\n * // Output (on gadget error): ❌ Gadget Error: Database\n * // Error: Connection timeout\n * // Parameters: {...}\n * ```\n *\n * @example\n * ```typescript\n * // Combine with monitoring for full context\n * .withHooks(HookPresets.merge(\n * HookPresets.monitoring(), // Includes errorLogging\n * customErrorAnalytics\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Error analytics collection\n * const errors: any[] = [];\n * .withHooks(HookPresets.merge(\n * HookPresets.errorLogging(),\n * {\n * observers: {\n * onLLMCallError: async (ctx) => {\n * errors.push({ type: 'llm', error: ctx.error, recovered: ctx.recovered });\n * },\n * },\n * }\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetserrorlogging | Full documentation}\n */\n static errorLogging(): AgentHooks {\n return {\n observers: {\n onLLMCallError: async (ctx) => {\n console.error(`❌ LLM Error (iteration ${ctx.iteration}):`, ctx.error.message);\n console.error(` Model: ${ctx.options.model}`);\n console.error(` Recovered: ${ctx.recovered}`);\n },\n onGadgetExecutionComplete: async (ctx) => {\n if (ctx.error) {\n console.error(`❌ Gadget Error: ${ctx.gadgetName}`);\n console.error(` Error: ${ctx.error}`);\n console.error(` Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n }\n },\n },\n };\n }\n\n /**\n * Tracks context compaction events.\n *\n * **Output:**\n * - Compaction events with 🗜️ emoji\n * - Strategy name, tokens before/after, and savings\n * - Cumulative statistics\n *\n * **Use cases:**\n * - Monitoring long-running conversations\n * - Understanding when and how compaction occurs\n * - Debugging context management issues\n *\n * **Performance:** Minimal overhead. Simple console output.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * await LLMist.createAgent()\n * .withHooks(HookPresets.compactionTracking())\n * .ask(\"Your prompt\");\n * ```\n */\n static compactionTracking(): AgentHooks {\n return {\n observers: {\n onCompaction: async (ctx) => {\n const saved = ctx.event.tokensBefore - ctx.event.tokensAfter;\n const percent = ((saved / ctx.event.tokensBefore) * 100).toFixed(1);\n console.log(\n `🗜️ Compaction (${ctx.event.strategy}): ${ctx.event.tokensBefore} → ${ctx.event.tokensAfter} tokens (saved ${saved}, ${percent}%)`,\n );\n console.log(` Messages: ${ctx.event.messagesBefore} → ${ctx.event.messagesAfter}`);\n if (ctx.stats.totalCompactions > 1) {\n console.log(\n ` Cumulative: ${ctx.stats.totalCompactions} compactions, ${ctx.stats.totalTokensSaved} tokens saved`,\n );\n }\n },\n },\n };\n }\n\n /**\n * Returns empty hook configuration for clean output without any logging.\n *\n * **Output:**\n * - None. Returns {} (empty object).\n *\n * **Use cases:**\n * - Clean test output without console noise\n * - Production environments where logging is handled externally\n * - Baseline for custom hook development\n * - Temporary disable of all hook output\n *\n * **Performance:** Zero overhead. No-op hook configuration.\n *\n * @returns Empty hook configuration\n *\n * @example\n * ```typescript\n * // Clean test output\n * describe('Agent tests', () => {\n * it('should calculate correctly', async () => {\n * const result = await LLMist.createAgent()\n * .withHooks(HookPresets.silent()) // No console output\n * .withGadgets(Calculator)\n * .askAndCollect(\"What is 15 times 23?\");\n *\n * expect(result).toContain(\"345\");\n * });\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Conditional silence based on environment\n * const isTesting = process.env.NODE_ENV === 'test';\n * .withHooks(isTesting ? HookPresets.silent() : HookPresets.monitoring())\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetssilent | Full documentation}\n */\n static silent(): AgentHooks {\n return {};\n }\n\n /**\n * Combines multiple hook configurations into one.\n *\n * Merge allows you to compose preset and custom hooks for modular monitoring\n * configurations. Understanding merge behavior is crucial for proper composition.\n *\n * **Merge behavior:**\n * - **Observers:** Composed - all handlers run sequentially in order\n * - **Interceptors:** Last one wins - only the last interceptor applies\n * - **Controllers:** Last one wins - only the last controller applies\n *\n * **Why interceptors/controllers don't compose:**\n * - Interceptors have different signatures per method, making composition impractical\n * - Controllers return specific actions that can't be meaningfully combined\n * - Only observers support composition because they're read-only and independent\n *\n * **Use cases:**\n * - Combining multiple presets (logging + timing + tokens)\n * - Adding custom hooks to presets\n * - Building modular, reusable monitoring configurations\n * - Environment-specific hook composition\n *\n * **Performance:** Minimal overhead for merging. Runtime performance depends on merged hooks.\n *\n * @param hookSets - Variable number of hook configurations to merge\n * @returns Single merged hook configuration with composed/overridden handlers\n *\n * @example\n * ```typescript\n * // Combine multiple presets\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * // All observers from all three presets will run\n * ```\n *\n * @example\n * ```typescript\n * // Add custom observer to preset (both run)\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * {\n * observers: {\n * onLLMCallComplete: async (ctx) => {\n * await saveMetrics({ tokens: ctx.usage?.totalTokens });\n * },\n * },\n * }\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Multiple interceptors (last wins!)\n * .withHooks(HookPresets.merge(\n * {\n * interceptors: {\n * interceptTextChunk: (chunk) => chunk.toUpperCase(), // Ignored\n * },\n * },\n * {\n * interceptors: {\n * interceptTextChunk: (chunk) => chunk.toLowerCase(), // This wins\n * },\n * }\n * ))\n * // Result: text will be lowercase\n * ```\n *\n * @example\n * ```typescript\n * // Modular environment-based configuration\n * const baseHooks = HookPresets.errorLogging();\n * const devHooks = HookPresets.merge(baseHooks, HookPresets.monitoring({ verbose: true }));\n * const prodHooks = HookPresets.merge(baseHooks, HookPresets.tokenTracking());\n *\n * const hooks = process.env.NODE_ENV === 'production' ? prodHooks : devHooks;\n * .withHooks(hooks)\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmergehooksets | Full documentation}\n */\n static merge(...hookSets: AgentHooks[]): AgentHooks {\n const merged: AgentHooks = {\n observers: {},\n interceptors: {},\n controllers: {},\n };\n\n // Compose observers: run all handlers for the same event\n for (const hooks of hookSets) {\n if (hooks.observers) {\n for (const [key, handler] of Object.entries(hooks.observers)) {\n const typedKey = key as keyof typeof hooks.observers;\n if (merged.observers![typedKey]) {\n // Compose: run both existing and new handler\n const existing = merged.observers![typedKey];\n merged.observers![typedKey] = async (ctx: any) => {\n await existing(ctx);\n await handler(ctx);\n };\n } else {\n merged.observers![typedKey] = handler as any;\n }\n }\n }\n\n // Interceptors: last one wins (complex signatures make composition impractical)\n // Each interceptor has different parameters (chunk, message, parameters, etc.)\n // so we can't meaningfully compose them like we do with observers\n if (hooks.interceptors) {\n Object.assign(merged.interceptors!, hooks.interceptors);\n }\n\n // Controllers: last one wins (can't meaningfully compose boolean returns)\n if (hooks.controllers) {\n Object.assign(merged.controllers!, hooks.controllers);\n }\n }\n\n return merged;\n }\n\n /**\n * Composite preset combining logging, timing, tokenTracking, and errorLogging.\n *\n * This is the recommended preset for development and initial production deployments,\n * providing comprehensive observability with a single method call.\n *\n * **Includes:**\n * - All output from `logging()` preset (with optional verbosity)\n * - All output from `timing()` preset (execution times)\n * - All output from `tokenTracking()` preset (token usage)\n * - All output from `errorLogging()` preset (error details)\n *\n * **Output format:**\n * - Event logging: [LLM]/[GADGET] messages\n * - Timing: ⏱️ emoji with milliseconds\n * - Tokens: 📊 emoji with per-call and cumulative counts\n * - Errors: ❌ emoji with full error details\n *\n * **Use cases:**\n * - Full observability during development\n * - Comprehensive monitoring in production\n * - One-liner for complete agent visibility\n * - Troubleshooting and debugging with full context\n *\n * **Performance:** Combined overhead of all four presets, but still minimal in practice.\n *\n * @param options - Monitoring options\n * @param options.verbose - Passed to logging() preset for detailed output. Default: false\n * @returns Merged hook configuration combining all monitoring presets\n *\n * @example\n * ```typescript\n * // Basic monitoring (recommended for development)\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring())\n * .withGadgets(Calculator, Weather)\n * .ask(\"What is 15 times 23, and what's the weather in NYC?\");\n * // Output: All events, timing, tokens, and errors in one place\n * ```\n *\n * @example\n * ```typescript\n * // Verbose monitoring with full details\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring({ verbose: true }))\n * .ask(\"Your prompt\");\n * // Output includes: parameters, results, and complete responses\n * ```\n *\n * @example\n * ```typescript\n * // Environment-based monitoring\n * const isDev = process.env.NODE_ENV === 'development';\n * .withHooks(HookPresets.monitoring({ verbose: isDev }))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmonitoringoptions | Full documentation}\n */\n static monitoring(options: LoggingOptions = {}): AgentHooks {\n return HookPresets.merge(\n HookPresets.logging(options),\n HookPresets.timing(),\n HookPresets.tokenTracking(),\n HookPresets.errorLogging(),\n );\n }\n}\n","/**\n * Context Compaction System\n *\n * Automatically manages conversation context to prevent context window overflow\n * in long-running agent conversations.\n *\n * Features:\n * - Automatic threshold monitoring (default: 80% of context window)\n * - Multiple strategies: sliding-window, summarization, hybrid (default)\n * - Full visibility via StreamEvents and hooks\n * - Enabled by default with sensible defaults\n *\n * @example\n * ```typescript\n * // Auto-enabled with defaults\n * const agent = await LLMist.createAgent()\n * .withModel('sonnet')\n * .ask('Help me...');\n *\n * // Custom configuration\n * const agent = await LLMist.createAgent()\n * .withModel('gpt-4')\n * .withCompaction({\n * triggerThresholdPercent: 70,\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 */\n\n// Configuration\nexport {\n type CompactionConfig,\n type CompactionEvent,\n type CompactionStats,\n DEFAULT_COMPACTION_CONFIG,\n DEFAULT_SUMMARIZATION_PROMPT,\n type ResolvedCompactionConfig,\n resolveCompactionConfig,\n} from \"./config.js\";\n// Manager\nexport { CompactionManager } from \"./manager.js\";\n\n// Strategy implementations\nexport {\n HybridStrategy,\n SlidingWindowStrategy,\n SummarizationStrategy,\n} from \"./strategies/index.js\";\n// Strategy interface and utilities\nexport {\n type CompactionContext,\n type CompactionResult,\n type CompactionStrategy,\n flattenTurns,\n groupIntoTurns,\n type MessageTurn,\n} from \"./strategy.js\";\n","/**\n * Agent module - Composable, single-responsibility architecture for LLM agents.\n * This module provides a cleaner alternative to the monolithic AgentLoop.\n */\n\nexport type { AgentOptions } from \"./agent.js\";\n// Context compaction\nexport {\n type CompactionConfig,\n type CompactionContext,\n type CompactionEvent,\n CompactionManager,\n type CompactionResult,\n type CompactionStats,\n type CompactionStrategy,\n DEFAULT_COMPACTION_CONFIG,\n DEFAULT_SUMMARIZATION_PROMPT,\n HybridStrategy,\n type MessageTurn,\n type ResolvedCompactionConfig,\n SlidingWindowStrategy,\n SummarizationStrategy,\n} from \"./compaction/index.js\";\nexport { ConversationManager } from \"./conversation-manager.js\";\n// Gadget output limiting\nexport type { StoredOutput } from \"./gadget-output-store.js\";\nexport { GadgetOutputStore } from \"./gadget-output-store.js\";\n// LLM Assistance Hints\nexport {\n createHints,\n type HintsConfig,\n type IterationHintOptions,\n iterationProgressHint,\n type ParallelGadgetHintOptions,\n parallelGadgetHint,\n} from \"./hints.js\";\n// New clean hooks system\nexport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n // Interceptor contexts\n ChunkInterceptorContext,\n Controllers,\n // Dependency skip controller\n DependencySkipAction,\n DependencySkipControllerContext,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n Interceptors,\n // Controller contexts and actions\n LLMCallControllerContext,\n LLMErrorControllerContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveCompactionContext,\n ObserveGadgetCompleteContext,\n // Gadget skip observer\n ObserveGadgetSkippedContext,\n ObserveGadgetStartContext,\n // Observer contexts\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n Observers,\n // Subagent context for distinguishing subagent events in hooks\n SubagentContext,\n} from \"./hooks.js\";\nexport type { IConversationManager } from \"./interfaces.js\";\n// StreamProcessor for advanced use cases\nexport {\n type StreamProcessingResult,\n StreamProcessor,\n type StreamProcessorOptions,\n} from \"./stream-processor.js\";\n","/**\n * LLM Assistance Hints System\n *\n * Provides reusable hook factories that inject helpful context and coaching\n * messages to guide LLM behavior during agentic execution.\n *\n * ## Two Types of Hints\n *\n * 1. **Proactive (beforeLLMCall)**: Inject context before LLM generates response\n * - Example: Iteration progress (\"You're on iteration 3/10\")\n *\n * 2. **Reactive (afterLLMCall)**: Coach based on what LLM did\n * - Example: \"Tip: You can call multiple gadgets in parallel\"\n *\n * ## Usage\n *\n * ```typescript\n * import { createHints, iterationProgressHint, parallelGadgetHint } from \"llmist\";\n *\n * // Option 1: Use individual hints\n * const agent = new AgentBuilder()\n * .withHooks(HookPresets.merge(\n * iterationProgressHint({ timing: \"late\" }),\n * parallelGadgetHint(),\n * ))\n * .build();\n *\n * // Option 2: Use convenience factory\n * const agent = new AgentBuilder()\n * .withHooks(createHints({\n * iterationProgress: { timing: \"late\" },\n * parallelGadgets: true,\n * }))\n * .build();\n * ```\n *\n * @module agent/hints\n */\n\nimport {\n DEFAULT_HINTS,\n type HintContext,\n type HintTemplate,\n resolveHintTemplate,\n} from \"../core/prompt-config.js\";\nimport { HookPresets } from \"./hook-presets.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n// ============================================================================\n// CONFIGURATION TYPES\n// ============================================================================\n\n/**\n * Options for iteration progress hint.\n */\nexport interface IterationHintOptions {\n /**\n * When to show the hint.\n * - \"always\": Show on every iteration\n * - \"late\": Show only when >= 50% through iterations\n * - \"urgent\": Show only when >= 80% through iterations\n * @default \"always\"\n */\n timing?: \"always\" | \"late\" | \"urgent\";\n\n /**\n * Whether to include urgency indicators for late iterations.\n * Adds extra text when running low on iterations.\n * @default true\n */\n showUrgency?: boolean;\n\n /**\n * Custom template. Supports placeholders: {iteration}, {maxIterations}, {remaining}\n * Or a function receiving HintContext.\n * @default DEFAULT_HINTS.iterationProgressHint\n */\n template?: HintTemplate;\n}\n\n/**\n * Options for parallel gadget usage hint.\n */\nexport interface ParallelGadgetHintOptions {\n /**\n * Minimum number of gadget calls to consider \"efficient\".\n * If response has fewer calls, hint will suggest parallelization.\n * @default 2\n */\n minGadgetsForEfficiency?: number;\n\n /**\n * Custom message when single gadget detected.\n * @default DEFAULT_HINTS.parallelGadgetsHint\n */\n message?: string;\n\n /**\n * Whether to enable this hint.\n * @default true\n */\n enabled?: boolean;\n}\n\n/**\n * Combined hints configuration for createHints().\n */\nexport interface HintsConfig {\n /**\n * Enable iteration progress hints.\n * Pass `true` for defaults, or options object for customization.\n */\n iterationProgress?: boolean | IterationHintOptions;\n\n /**\n * Enable parallel gadget hints.\n * Pass `true` for defaults, or options object for customization.\n */\n parallelGadgets?: boolean | ParallelGadgetHintOptions;\n\n /**\n * Additional custom hooks to merge.\n */\n custom?: AgentHooks[];\n}\n\n// ============================================================================\n// HINT FACTORIES\n// ============================================================================\n\n/**\n * Creates a proactive hint that informs the LLM about iteration progress.\n *\n * This hint is injected before each LLM call (via beforeLLMCall controller),\n * helping the LLM understand how much \"budget\" remains for completing the task.\n *\n * @param options - Configuration options\n * @returns AgentHooks that can be merged with other hooks\n *\n * @example\n * ```typescript\n * // Basic usage - show on every iteration\n * const hooks = iterationProgressHint();\n *\n * // Show only when running low on iterations\n * const hooks = iterationProgressHint({ timing: \"late\" });\n *\n * // Custom template\n * const hooks = iterationProgressHint({\n * template: \"Turn {iteration} of {maxIterations}. {remaining} turns left.\",\n * });\n * ```\n */\nexport function iterationProgressHint(options?: IterationHintOptions): AgentHooks {\n const { timing = \"always\", showUrgency = true, template } = options ?? {};\n\n return {\n controllers: {\n beforeLLMCall: async (ctx) => {\n const iteration = ctx.iteration + 1; // 1-based for user-friendliness\n const maxIterations = ctx.maxIterations;\n const progress = iteration / maxIterations;\n\n // Check timing condition\n if (timing === \"late\" && progress < 0.5) {\n return { action: \"proceed\" };\n }\n if (timing === \"urgent\" && progress < 0.8) {\n return { action: \"proceed\" };\n }\n\n // Build hint context with all fields populated\n const remaining = maxIterations - iteration;\n const hintContext: HintContext = {\n iteration,\n maxIterations,\n remaining,\n };\n\n // Resolve template\n let hint = resolveHintTemplate(template, DEFAULT_HINTS.iterationProgressHint, hintContext);\n\n // Add urgency indicator if late in iterations\n if (showUrgency && progress >= 0.8) {\n hint += \" ⚠️ Running low on iterations - focus on completing the task.\";\n }\n\n // Inject as system-level context in messages\n const messages = [...ctx.options.messages];\n\n // Find last user message index (compatible with older ES targets)\n let lastUserIndex = -1;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n lastUserIndex = i;\n break;\n }\n }\n\n if (lastUserIndex >= 0) {\n // Insert hint after the last user message\n messages.splice(lastUserIndex + 1, 0, {\n role: \"user\",\n content: `[System Hint] ${hint}`,\n });\n } else {\n // No user messages found - append hint at the end\n messages.push({\n role: \"user\",\n content: `[System Hint] ${hint}`,\n });\n }\n\n return {\n action: \"proceed\",\n modifiedOptions: { messages },\n };\n },\n },\n };\n}\n\n/**\n * Creates a reactive hint that encourages parallel gadget usage.\n *\n * This hint analyzes the LLM's response and, if only a single gadget was called,\n * appends a reminder that multiple gadgets can be used in parallel for efficiency.\n *\n * @param options - Configuration options\n * @returns AgentHooks that can be merged with other hooks\n *\n * @example\n * ```typescript\n * // Basic usage\n * const hooks = parallelGadgetHint();\n *\n * // Custom threshold and message\n * const hooks = parallelGadgetHint({\n * minGadgetsForEfficiency: 3,\n * message: \"Consider calling multiple gadgets at once!\",\n * });\n * ```\n */\nexport function parallelGadgetHint(options?: ParallelGadgetHintOptions): AgentHooks {\n const {\n minGadgetsForEfficiency = 2,\n message = DEFAULT_HINTS.parallelGadgetsHint,\n enabled = true,\n } = options ?? {};\n\n return {\n controllers: {\n afterLLMCall: async (ctx) => {\n if (!enabled) {\n return { action: \"continue\" };\n }\n\n // Only hint if gadgets were called but below efficiency threshold\n if (ctx.gadgetCallCount > 0 && ctx.gadgetCallCount < minGadgetsForEfficiency) {\n return {\n action: \"append_messages\",\n messages: [\n {\n role: \"user\",\n content: `[System Hint] ${message}`,\n },\n ],\n };\n }\n\n return { action: \"continue\" };\n },\n },\n };\n}\n\n// ============================================================================\n// CONVENIENCE FACTORY\n// ============================================================================\n\n/**\n * Creates combined hints from a configuration object.\n *\n * This is a convenience function that creates and merges multiple hints\n * based on a simple configuration object.\n *\n * @param config - Configuration for which hints to enable\n * @returns Merged AgentHooks\n *\n * @example\n * ```typescript\n * const hooks = createHints({\n * iterationProgress: { timing: \"late\" },\n * parallelGadgets: true,\n * });\n *\n * const agent = new AgentBuilder()\n * .withHooks(HookPresets.merge(existingHooks, hooks))\n * .build();\n * ```\n */\nexport function createHints(config: HintsConfig): AgentHooks {\n const hooksToMerge: AgentHooks[] = [];\n\n // Iteration progress hint\n if (config.iterationProgress) {\n const options = typeof config.iterationProgress === \"boolean\" ? {} : config.iterationProgress;\n hooksToMerge.push(iterationProgressHint(options));\n }\n\n // Parallel gadgets hint\n if (config.parallelGadgets) {\n const options = typeof config.parallelGadgets === \"boolean\" ? {} : config.parallelGadgets;\n hooksToMerge.push(parallelGadgetHint(options));\n }\n\n // Custom hooks\n if (config.custom) {\n hooksToMerge.push(...config.custom);\n }\n\n return HookPresets.merge(...hooksToMerge);\n}\n","/**\n * Error utilities for llmist.\n */\n\n/**\n * Detects if an error is an abort/cancellation error from any provider.\n *\n * Different providers throw different error types when a request is aborted:\n * - Standard: `AbortError` (name) - from fetch/AbortController\n * - Anthropic SDK: `APIConnectionAbortedError`\n * - OpenAI SDK: `APIUserAbortError`\n * - Generic: errors with \"abort\", \"cancelled\", or \"canceled\" in the message\n *\n * @param error - The error to check\n * @returns `true` if the error is an abort-related error, `false` otherwise\n *\n * @example\n * ```typescript\n * import { isAbortError } from \"@llmist/core/errors\";\n *\n * const controller = new AbortController();\n *\n * try {\n * for await (const chunk of client.stream({ signal: controller.signal, ... })) {\n * // Process chunks...\n * }\n * } catch (error) {\n * if (isAbortError(error)) {\n * console.log(\"Request was cancelled - this is expected\");\n * return; // Graceful exit\n * }\n * // Re-throw unexpected errors\n * throw error;\n * }\n * ```\n */\nexport function isAbortError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n\n // Standard AbortError (from fetch/AbortController)\n if (error.name === \"AbortError\") return true;\n\n // Anthropic SDK\n if (error.name === \"APIConnectionAbortedError\") return true;\n\n // OpenAI SDK\n if (error.name === \"APIUserAbortError\") return true;\n\n // Message-based detection (fallback for edge cases)\n const message = error.message.toLowerCase();\n if (message.includes(\"abort\")) return true;\n if (message.includes(\"cancelled\")) return true;\n if (message.includes(\"canceled\")) return true;\n\n return false;\n}\n","/**\n * Unified event types for the Execution Tree.\n *\n * All events carry full tree context (nodeId, parentId, depth, path).\n * No special SubagentEvent wrapper needed - subagent events are regular\n * events with depth > 0.\n *\n * @module core/execution-events\n */\n\nimport type { GadgetMediaOutput } from \"../gadgets/types.js\";\nimport type { LLMMessage } from \"./messages.js\";\nimport type { TokenUsage } from \"./options.js\";\n\n// =============================================================================\n// Base Event Properties\n// =============================================================================\n\n/**\n * Base properties shared by all execution events.\n * Every event carries full tree context.\n */\nexport interface BaseExecutionEvent {\n /** Monotonically increasing event ID */\n eventId: number;\n /** Event timestamp */\n timestamp: number;\n /** Node that emitted this event */\n nodeId: string;\n /** Parent node ID (null for root events) */\n parentId: string | null;\n /** Nesting depth (0 = root, 1 = child, etc.) */\n depth: number;\n /** Full path from root to this node */\n path: string[];\n}\n\n// =============================================================================\n// LLM Call Events\n// =============================================================================\n\n/**\n * Emitted when an LLM call starts.\n */\nexport interface LLMCallStartEvent extends BaseExecutionEvent {\n type: \"llm_call_start\";\n /** Iteration number within agent loop (1-indexed) */\n iteration: number;\n /** Model identifier */\n model: string;\n /** Request messages */\n request?: LLMMessage[];\n}\n\n/**\n * Emitted for each streaming chunk from LLM.\n */\nexport interface LLMCallStreamEvent extends BaseExecutionEvent {\n type: \"llm_call_stream\";\n /** Text chunk */\n chunk: string;\n}\n\n/**\n * Emitted when an LLM call completes successfully.\n */\nexport interface LLMCallCompleteEvent extends BaseExecutionEvent {\n type: \"llm_call_complete\";\n /** Complete response text */\n response: string;\n /** Token usage */\n usage?: TokenUsage;\n /** Finish reason from LLM */\n finishReason?: string | null;\n /** Cost in USD */\n cost?: number;\n}\n\n/**\n * Emitted when an LLM call fails.\n */\nexport interface LLMCallErrorEvent extends BaseExecutionEvent {\n type: \"llm_call_error\";\n /** The error that occurred */\n error: Error;\n /** Whether the error was recovered by a controller */\n recovered: boolean;\n}\n\n// =============================================================================\n// Gadget Events\n// =============================================================================\n\n/**\n * Emitted when a gadget call is parsed from LLM output (before execution).\n */\nexport interface GadgetCallEvent extends BaseExecutionEvent {\n type: \"gadget_call\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Parameters */\n parameters: Record<string, unknown>;\n /** Dependencies (other invocation IDs) */\n dependencies: string[];\n}\n\n/**\n * Emitted when gadget execution starts.\n */\nexport interface GadgetStartEvent extends BaseExecutionEvent {\n type: \"gadget_start\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n}\n\n/**\n * Emitted when gadget execution completes successfully.\n */\nexport interface GadgetCompleteEvent extends BaseExecutionEvent {\n type: \"gadget_complete\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Result string */\n result: string;\n /** Execution time in ms */\n executionTimeMs: number;\n /** Cost in USD */\n cost?: number;\n /** Media outputs */\n media?: GadgetMediaOutput[];\n}\n\n/**\n * Emitted when gadget execution fails.\n */\nexport interface GadgetErrorEvent extends BaseExecutionEvent {\n type: \"gadget_error\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Error message */\n error: string;\n /** Execution time in ms */\n executionTimeMs: number;\n}\n\n/**\n * Emitted when a gadget is skipped.\n */\nexport interface GadgetSkippedEvent extends BaseExecutionEvent {\n type: \"gadget_skipped\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Reason for skipping */\n reason: \"dependency_failed\" | \"controller_skip\";\n /** Error message (combines reason and failedDependencyError for consistency with GadgetErrorEvent) */\n error: string;\n /** Failed dependency invocation ID (if dependency_failed) */\n failedDependency?: string;\n /** Error message from failed dependency */\n failedDependencyError?: string;\n}\n\n// =============================================================================\n// Text Events\n// =============================================================================\n\n/**\n * Emitted for text output from LLM (pure notification, not a tree node).\n */\nexport interface TextEvent extends BaseExecutionEvent {\n type: \"text\";\n /** Text content */\n content: string;\n}\n\n// =============================================================================\n// Other Events\n// =============================================================================\n\n/**\n * Emitted when context compaction occurs.\n */\nexport interface CompactionEvent extends BaseExecutionEvent {\n type: \"compaction\";\n /** Tokens before compaction */\n tokensBefore: number;\n /** Tokens after compaction */\n tokensAfter: number;\n /** Compaction strategy used */\n strategy: string;\n /** Messages removed */\n messagesRemoved: number;\n}\n\n/**\n * Emitted when human input is required.\n */\nexport interface HumanInputRequiredEvent extends BaseExecutionEvent {\n type: \"human_input_required\";\n /** Question for the user */\n question: string;\n /** Gadget name requesting input */\n gadgetName: string;\n /** Invocation ID */\n invocationId: string;\n}\n\n/**\n * Emitted when the execution stream completes.\n */\nexport interface StreamCompleteEvent extends BaseExecutionEvent {\n type: \"stream_complete\";\n /** Whether any gadgets were executed */\n didExecuteGadgets: boolean;\n /** Whether the agent loop should break */\n shouldBreakLoop: boolean;\n /** Total cost for this iteration */\n iterationCost?: number;\n}\n\n// =============================================================================\n// Union Types\n// =============================================================================\n\n/**\n * All LLM-related events.\n */\nexport type LLMEvent =\n | LLMCallStartEvent\n | LLMCallStreamEvent\n | LLMCallCompleteEvent\n | LLMCallErrorEvent;\n\n/**\n * All gadget-related events.\n */\nexport type GadgetEvent =\n | GadgetCallEvent\n | GadgetStartEvent\n | GadgetCompleteEvent\n | GadgetErrorEvent\n | GadgetSkippedEvent;\n\n/**\n * Union of all execution events.\n */\nexport type ExecutionEvent =\n | LLMCallStartEvent\n | LLMCallStreamEvent\n | LLMCallCompleteEvent\n | LLMCallErrorEvent\n | GadgetCallEvent\n | GadgetStartEvent\n | GadgetCompleteEvent\n | GadgetErrorEvent\n | GadgetSkippedEvent\n | TextEvent\n | CompactionEvent\n | HumanInputRequiredEvent\n | StreamCompleteEvent;\n\n/**\n * Event type discriminator.\n */\nexport type ExecutionEventType = ExecutionEvent[\"type\"] | \"*\";\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Check if an event is an LLM event.\n */\nexport function isLLMEvent(event: ExecutionEvent): event is LLMEvent {\n return event.type.startsWith(\"llm_call_\");\n}\n\n/**\n * Check if an event is a gadget event.\n */\nexport function isGadgetEvent(event: ExecutionEvent): event is GadgetEvent {\n return event.type.startsWith(\"gadget_\");\n}\n\n/**\n * Check if an event is from a subagent (nested execution).\n */\nexport function isSubagentEvent(event: ExecutionEvent): boolean {\n return event.depth > 0;\n}\n\n/**\n * Check if an event is from the root agent.\n */\nexport function isRootEvent(event: ExecutionEvent): boolean {\n return event.depth === 0;\n}\n\n// =============================================================================\n// Event Filtering Utilities\n// =============================================================================\n\n/**\n * Filter events by depth.\n */\nexport function filterByDepth(events: ExecutionEvent[], depth: number): ExecutionEvent[] {\n return events.filter((e) => e.depth === depth);\n}\n\n/**\n * Filter events by parent node.\n */\nexport function filterByParent(events: ExecutionEvent[], parentId: string): ExecutionEvent[] {\n return events.filter((e) => e.parentId === parentId);\n}\n\n/**\n * Filter events to only root-level events.\n */\nexport function filterRootEvents(events: ExecutionEvent[]): ExecutionEvent[] {\n return filterByDepth(events, 0);\n}\n\n/**\n * Group events by their parent node.\n */\nexport function groupByParent(events: ExecutionEvent[]): Map<string | null, ExecutionEvent[]> {\n const groups = new Map<string | null, ExecutionEvent[]>();\n\n for (const event of events) {\n const parentId = event.parentId;\n if (!groups.has(parentId)) {\n groups.set(parentId, []);\n }\n groups.get(parentId)?.push(event);\n }\n\n return groups;\n}\n","/**\n * Helper functions for gadget authors.\n *\n * This module provides:\n * 1. Response formatting helpers (gadgetSuccess, gadgetError, withErrorHandling)\n * 2. Media output helpers (resultWithImage, resultWithAudio, etc.)\n *\n * @example Response helpers\n * ```typescript\n * import { gadgetSuccess, gadgetError, withErrorHandling } from \"llmist\";\n *\n * // Simple response formatting\n * return gadgetSuccess({ url: \"https://example.com\", title: \"Example\" });\n * return gadgetError(\"Element not found\", { selector: \".missing\" });\n *\n * // Automatic error handling wrapper\n * const safeExecute = withErrorHandling(async (params) => {\n * // your code here - errors are automatically caught and formatted\n * return gadgetSuccess({ result: \"done\" });\n * });\n * ```\n *\n * @example Media output helpers\n * ```typescript\n * import { resultWithImage } from \"llmist\";\n *\n * const screenshotGadget = createGadget({\n * name: \"Screenshot\",\n * schema: z.object({ url: z.string() }),\n * execute: async ({ url }) => {\n * const screenshot = await takeScreenshot(url);\n * return resultWithImage(\n * `Screenshot of ${url}`,\n * screenshot,\n * { description: \"Webpage screenshot\" }\n * );\n * },\n * });\n * ```\n */\n\nimport { detectAudioMimeType, detectImageMimeType } from \"../core/input-content.js\";\nimport type {\n ExecutionContext,\n GadgetExecuteResultWithMedia,\n GadgetMediaOutput,\n MediaKind,\n MediaMetadata,\n} from \"./types.js\";\n\n// ============================================================================\n// Response Formatting Helpers\n// ============================================================================\n\n/**\n * Create a success response as JSON string.\n *\n * This is a convenience helper for gadgets that return JSON-formatted responses.\n * It automatically adds `success: true` and stringifies the result.\n *\n * @param data - Additional data to include in the response\n * @returns JSON string with success: true and provided data\n *\n * @example\n * ```typescript\n * return gadgetSuccess({ url: page.url(), title: await page.title() });\n * // Returns: '{\"success\":true,\"url\":\"...\",\"title\":\"...\"}'\n * ```\n */\nexport function gadgetSuccess(data: Record<string, unknown> = {}): string {\n return JSON.stringify({ success: true, ...data });\n}\n\n/**\n * Create an error response as JSON string.\n *\n * This is a convenience helper for gadgets that return JSON-formatted errors.\n * It stringifies the error message and any additional details.\n *\n * @param message - Error message\n * @param details - Additional error details (e.g., suggestions, context)\n * @returns JSON string with error message and details\n *\n * @example\n * ```typescript\n * return gadgetError(\"Element not found\", { selector: \".missing\", suggestions: [\"Try #id instead\"] });\n * // Returns: '{\"error\":\"Element not found\",\"selector\":\".missing\",\"suggestions\":[...]}'\n * ```\n */\nexport function gadgetError(message: string, details?: Record<string, unknown>): string {\n return JSON.stringify({ error: message, ...details });\n}\n\n/**\n * Safely extract error message from unknown error type.\n *\n * Handles both Error instances and other thrown values.\n *\n * @param error - Unknown error value\n * @returns String error message\n */\nexport function getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Wrap a gadget execute function with automatic error handling.\n *\n * This higher-order function catches any errors thrown during execution\n * and converts them to properly formatted error responses.\n *\n * @param execute - The execute function to wrap\n * @returns A wrapped function that catches errors and returns gadgetError responses\n *\n * @example\n * ```typescript\n * const safeExecute = withErrorHandling(async (params: MyParams) => {\n * // Your code here - if it throws, error is caught and formatted\n * const result = await riskyOperation(params.id);\n * return gadgetSuccess({ result });\n * });\n *\n * // In gadget:\n * execute(params) {\n * return safeExecute(params);\n * }\n * ```\n */\nexport function withErrorHandling<TParams>(\n execute: (params: TParams, ctx?: ExecutionContext) => Promise<string> | string,\n): (params: TParams, ctx?: ExecutionContext) => Promise<string> {\n return async (params: TParams, ctx?: ExecutionContext): Promise<string> => {\n try {\n return await execute(params, ctx);\n } catch (error) {\n return gadgetError(getErrorMessage(error));\n }\n };\n}\n\n// ============================================================================\n// Media Output Helpers\n// ============================================================================\n\n/**\n * Create a GadgetMediaOutput from raw data.\n *\n * @param kind - Type of media\n * @param data - Raw binary data (Buffer or Uint8Array)\n * @param mimeType - MIME type string\n * @param options - Optional description, metadata, and fileName\n * @returns A GadgetMediaOutput ready to include in results\n */\nexport function createMediaOutput(\n kind: MediaKind,\n data: Buffer | Uint8Array,\n mimeType: string,\n options?: { description?: string; metadata?: MediaMetadata; fileName?: string },\n): GadgetMediaOutput {\n const buffer = data instanceof Buffer ? data : Buffer.from(data);\n return {\n kind,\n data: buffer.toString(\"base64\"),\n mimeType,\n description: options?.description,\n metadata: options?.metadata,\n fileName: options?.fileName,\n };\n}\n\n/**\n * Create a result with multiple media outputs.\n *\n * @param result - Text result string\n * @param media - Array of GadgetMediaOutput items (must not be empty)\n * @param cost - Optional cost in USD\n * @returns A GadgetExecuteResultWithMedia\n * @throws Error if media array is empty\n *\n * @example\n * ```typescript\n * return resultWithMedia(\n * \"Generated 2 charts\",\n * [\n * createMediaOutput(\"image\", barChartPng, \"image/png\", { description: \"Bar chart\" }),\n * createMediaOutput(\"image\", pieChartPng, \"image/png\", { description: \"Pie chart\" }),\n * ],\n * 0.002\n * );\n * ```\n */\nexport function resultWithMedia(\n result: string,\n media: GadgetMediaOutput[],\n cost?: number,\n): GadgetExecuteResultWithMedia {\n if (media.length === 0) {\n throw new Error(\"resultWithMedia: media array cannot be empty\");\n }\n return {\n result,\n media,\n cost,\n };\n}\n\n/**\n * Options for resultWithImage helper.\n */\nexport interface ImageOptions {\n /** MIME type (auto-detected if not provided) */\n mimeType?: string;\n /** Human-readable description */\n description?: string;\n /** Image dimensions and other metadata */\n metadata?: MediaMetadata;\n /** Cost in USD */\n cost?: number;\n /** Filename to use when saving (if not provided, auto-generated) */\n fileName?: string;\n}\n\n/**\n * Create a result with a single image output.\n *\n * @param result - Text result string\n * @param imageData - Raw image data (PNG, JPEG, GIF, WebP)\n * @param options - Optional MIME type, description, metadata, cost\n * @returns A GadgetExecuteResultWithMedia\n *\n * @example\n * ```typescript\n * const screenshot = await page.screenshot({ type: \"png\" });\n * return resultWithImage(\n * \"Screenshot captured\",\n * screenshot,\n * { description: \"Homepage screenshot\", metadata: { width: 1920, height: 1080 } }\n * );\n * ```\n */\nexport function resultWithImage(\n result: string,\n imageData: Buffer | Uint8Array,\n options?: ImageOptions,\n): GadgetExecuteResultWithMedia {\n const buffer = imageData instanceof Buffer ? imageData : Buffer.from(imageData);\n const mimeType = options?.mimeType ?? detectImageMimeType(buffer);\n\n if (!mimeType) {\n throw new Error(\n \"Could not detect image MIME type. Please provide mimeType explicitly in options.\",\n );\n }\n\n return {\n result,\n media: [\n {\n kind: \"image\",\n data: buffer.toString(\"base64\"),\n mimeType,\n description: options?.description,\n metadata: options?.metadata,\n fileName: options?.fileName,\n },\n ],\n cost: options?.cost,\n };\n}\n\n/**\n * Image item for resultWithImages helper.\n */\nexport interface ImageItem {\n /** Raw image data */\n data: Buffer | Uint8Array;\n /** MIME type (auto-detected if not provided) */\n mimeType?: string;\n /** Human-readable description */\n description?: string;\n /** Image dimensions and other metadata */\n metadata?: MediaMetadata;\n /** Filename to use when saving (if not provided, auto-generated) */\n fileName?: string;\n}\n\n/**\n * Create a result with multiple image outputs.\n *\n * @param result - Text result string\n * @param images - Array of image items (must not be empty)\n * @param cost - Optional cost in USD\n * @returns A GadgetExecuteResultWithMedia\n * @throws Error if images array is empty\n *\n * @example\n * ```typescript\n * return resultWithImages(\n * \"Generated comparison images\",\n * [\n * { data: beforeImg, description: \"Before\" },\n * { data: afterImg, description: \"After\" },\n * ],\n * 0.01\n * );\n * ```\n */\nexport function resultWithImages(\n result: string,\n images: ImageItem[],\n cost?: number,\n): GadgetExecuteResultWithMedia {\n if (images.length === 0) {\n throw new Error(\"resultWithImages: images array cannot be empty\");\n }\n\n const media: GadgetMediaOutput[] = images.map((img, index) => {\n const buffer = img.data instanceof Buffer ? img.data : Buffer.from(img.data);\n const mimeType = img.mimeType ?? detectImageMimeType(buffer);\n\n if (!mimeType) {\n throw new Error(\n `Could not detect MIME type for image at index ${index}. Please provide mimeType explicitly.`,\n );\n }\n\n return {\n kind: \"image\" as const,\n data: buffer.toString(\"base64\"),\n mimeType,\n description: img.description,\n metadata: img.metadata,\n fileName: img.fileName,\n };\n });\n\n return { result, media, cost };\n}\n\n/**\n * Options for resultWithAudio helper.\n */\nexport interface AudioOptions {\n /** MIME type (auto-detected if not provided) */\n mimeType?: string;\n /** Human-readable description */\n description?: string;\n /** Duration in milliseconds */\n durationMs?: number;\n /** Cost in USD */\n cost?: number;\n /** Filename to use when saving (if not provided, auto-generated) */\n fileName?: string;\n}\n\n/**\n * Create a result with a single audio output.\n *\n * @param result - Text result string\n * @param audioData - Raw audio data (MP3, WAV, OGG, etc.)\n * @param options - Optional MIME type, description, duration, cost\n * @returns A GadgetExecuteResultWithMedia\n *\n * @example\n * ```typescript\n * const speech = await generateSpeech(text);\n * return resultWithAudio(\n * `Generated speech for: \"${text.slice(0, 50)}...\"`,\n * speech,\n * { mimeType: \"audio/mp3\", durationMs: 5000 }\n * );\n * ```\n */\nexport function resultWithAudio(\n result: string,\n audioData: Buffer | Uint8Array,\n options?: AudioOptions,\n): GadgetExecuteResultWithMedia {\n const buffer = audioData instanceof Buffer ? audioData : Buffer.from(audioData);\n const mimeType = options?.mimeType ?? detectAudioMimeType(buffer);\n\n if (!mimeType) {\n throw new Error(\n \"Could not detect audio MIME type. Please provide mimeType explicitly in options.\",\n );\n }\n\n const metadata: MediaMetadata | undefined = options?.durationMs\n ? { durationMs: options.durationMs }\n : undefined;\n\n return {\n result,\n media: [\n {\n kind: \"audio\",\n data: buffer.toString(\"base64\"),\n mimeType,\n description: options?.description,\n metadata,\n fileName: options?.fileName,\n },\n ],\n cost: options?.cost,\n };\n}\n\n/**\n * Options for resultWithFile helper.\n */\nexport interface FileOptions {\n /** Human-readable description */\n description?: string;\n /** Cost in USD */\n cost?: number;\n /** Filename to use when saving (if not provided, auto-generated) */\n fileName?: string;\n}\n\n/**\n * Create a result with a generic file output.\n *\n * Use this for arbitrary file types that don't fit image/audio categories.\n *\n * @param result - Text result string\n * @param fileData - Raw file data\n * @param mimeType - MIME type (required, not auto-detected)\n * @param options - Optional description and cost\n * @returns A GadgetExecuteResultWithMedia\n *\n * @example\n * ```typescript\n * const pdf = await generatePdf(content);\n * return resultWithFile(\n * \"Generated PDF report\",\n * pdf,\n * \"application/pdf\",\n * { description: \"Monthly report\" }\n * );\n * ```\n */\nexport function resultWithFile(\n result: string,\n fileData: Buffer | Uint8Array,\n mimeType: string,\n options?: FileOptions,\n): GadgetExecuteResultWithMedia {\n const buffer = fileData instanceof Buffer ? fileData : Buffer.from(fileData);\n\n return {\n result,\n media: [\n {\n kind: \"file\",\n data: buffer.toString(\"base64\"),\n mimeType,\n description: options?.description,\n fileName: options?.fileName,\n },\n ],\n cost: options?.cost,\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 { AbstractGadget } 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: AbstractGadget,\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 * Config resolution utility for subagent gadgets.\n *\n * Simplifies the common pattern of resolving configuration from multiple sources:\n * 1. Runtime params (explicit gadget call parameters)\n * 2. Subagent config (from CLI [subagents.Name] sections)\n * 3. Parent agent config (model inheritance)\n * 4. Package defaults\n *\n * @module utils/config-resolver\n */\n\nimport type { ExecutionContext } from \"../gadgets/types.js\";\n\n/**\n * Options for resolving a single config value.\n */\nexport interface ResolveValueOptions<T> {\n /** Runtime parameter value (highest priority) */\n runtime?: T;\n /** Subagent config key to check */\n subagentKey?: string;\n /** Parent config key to check (for inheritance) - \"model\" or \"temperature\" */\n parentKey?: \"model\" | \"temperature\";\n /** Default value (lowest priority) */\n defaultValue: T;\n /** Whether \"inherit\" string means use parent value */\n handleInherit?: boolean;\n}\n\n/**\n * Resolve a single configuration value through the priority chain.\n *\n * Priority (highest to lowest):\n * 1. Runtime parameter (if provided and not undefined)\n * 2. Subagent config (from ctx.subagentConfig[gadgetName][key])\n * 3. Parent config (from ctx.agentConfig[key], if parentKey specified)\n * 4. Default value\n *\n * Special handling for \"inherit\" string:\n * - If handleInherit is true and value is \"inherit\", falls through to parent/default\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget (e.g., \"BrowseWeb\")\n * @param options - Resolution options\n * @returns Resolved value\n *\n * @example\n * ```typescript\n * const model = resolveValue(ctx, \"BrowseWeb\", {\n * runtime: params.model,\n * subagentKey: \"model\",\n * parentKey: \"model\",\n * defaultValue: \"sonnet\",\n * handleInherit: true,\n * });\n * ```\n */\nexport function resolveValue<T>(\n ctx: ExecutionContext,\n gadgetName: string,\n options: ResolveValueOptions<T>,\n): T {\n const { runtime, subagentKey, parentKey, defaultValue, handleInherit } = options;\n\n // Priority 1: Runtime parameter\n if (runtime !== undefined) {\n // Handle \"inherit\" string if enabled\n if (handleInherit && runtime === \"inherit\") {\n // Fall through to lower priorities\n } else {\n return runtime;\n }\n }\n\n // Priority 2: Subagent config\n if (subagentKey && ctx.subagentConfig) {\n const subagentCfg = ctx.subagentConfig[gadgetName];\n if (subagentCfg && subagentKey in subagentCfg) {\n const value = subagentCfg[subagentKey] as T;\n // Handle \"inherit\" string if enabled\n if (handleInherit && value === \"inherit\") {\n // Fall through to parent/default\n } else if (value !== undefined) {\n return value;\n }\n }\n }\n\n // Priority 3: Parent config (inheritance)\n if (parentKey && ctx.agentConfig && parentKey in ctx.agentConfig) {\n const parentValue = ctx.agentConfig[parentKey] as T;\n if (parentValue !== undefined) {\n return parentValue;\n }\n }\n\n // Priority 4: Default value\n return defaultValue;\n}\n\n/**\n * Bulk configuration resolution for subagent gadgets.\n *\n * Takes a map of config keys to their resolution options and returns\n * a fully resolved configuration object.\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget (e.g., \"BrowseWeb\")\n * @param config - Map of config keys to resolution options\n * @returns Fully resolved configuration object\n *\n * @example\n * ```typescript\n * // Before: 27 lines of manual fallback logic\n * const subagentConfig = ctx.subagentConfig?.Dhalsim ?? {};\n * const parentModel = ctx.agentConfig?.model;\n * const model = params.model ?? subagentConfig.model ?? parentModel ?? \"sonnet\";\n * const maxIterations = params.maxIterations ?? subagentConfig.maxIterations ?? 15;\n * const headless = params.headless ?? subagentConfig.headless ?? true;\n *\n * // After: One function call\n * const { model, maxIterations, headless } = resolveConfig(ctx, \"BrowseWeb\", {\n * model: { runtime: params.model, subagentKey: \"model\", parentKey: \"model\", defaultValue: \"sonnet\", handleInherit: true },\n * maxIterations: { runtime: params.maxIterations, subagentKey: \"maxIterations\", defaultValue: 15 },\n * headless: { runtime: params.headless, subagentKey: \"headless\", defaultValue: true },\n * });\n * ```\n */\nexport function resolveConfig<T extends Record<string, unknown>>(\n ctx: ExecutionContext,\n gadgetName: string,\n config: { [K in keyof T]: ResolveValueOptions<T[K]> },\n): T {\n const result: Record<string, unknown> = {};\n\n for (const [key, options] of Object.entries(config)) {\n result[key] = resolveValue(ctx, gadgetName, options as ResolveValueOptions<unknown>);\n }\n\n return result as T;\n}\n\n/**\n * Convenience function for resolving subagent model with \"inherit\" support.\n *\n * This is the most common resolution pattern for subagent gadgets:\n * - Use runtime model if provided\n * - Check subagent config for model override\n * - Inherit parent model if configured\n * - Fall back to default\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget\n * @param runtimeModel - Model from gadget parameters\n * @param defaultModel - Default model if nothing else specified\n * @returns Resolved model string\n *\n * @example\n * ```typescript\n * const model = resolveSubagentModel(ctx, \"BrowseWeb\", params.model, \"sonnet\");\n * ```\n */\nexport function resolveSubagentModel(\n ctx: ExecutionContext,\n gadgetName: string,\n runtimeModel: string | undefined,\n defaultModel: string,\n): string {\n return resolveValue(ctx, gadgetName, {\n runtime: runtimeModel,\n subagentKey: \"model\",\n parentKey: \"model\",\n defaultValue: defaultModel,\n handleInherit: true,\n });\n}\n\n/**\n * Convenience function for resolving subagent timeout.\n *\n * Resolves timeout from the configuration priority chain:\n * - Use runtime timeout if provided\n * - Check subagent config for timeout override\n * - Fall back to default\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget\n * @param runtimeTimeout - Timeout from gadget parameters\n * @param defaultTimeout - Default timeout if nothing else specified\n * @returns Resolved timeout in milliseconds\n *\n * @example\n * ```typescript\n * const timeoutMs = resolveSubagentTimeout(ctx, \"BrowseWeb\", params.timeoutMs, 300000);\n * ```\n */\nexport function resolveSubagentTimeout(\n ctx: ExecutionContext,\n gadgetName: string,\n runtimeTimeout: number | undefined,\n defaultTimeout: number,\n): number {\n return resolveValue(ctx, gadgetName, {\n runtime: runtimeTimeout,\n subagentKey: \"timeoutMs\",\n defaultValue: defaultTimeout,\n });\n}\n","/**\n * Formatting utilities for gadget authors and CLI output.\n *\n * Provides common formatting functions for:\n * - Text truncation\n * - Byte size formatting\n * - Date formatting\n * - Duration formatting\n *\n * @module utils/format\n *\n * @example\n * ```typescript\n * import { format } from \"llmist\";\n *\n * format.truncate(\"Long text...\", 10); // \"Long tex...\"\n * format.bytes(1536); // \"1.5 KB\"\n * format.date(\"2024-01-15T10:30:00Z\"); // \"Jan 15, 2024 10:30 AM\"\n * format.duration(125000); // \"2m 5s\"\n * ```\n */\n\n/**\n * Truncate text to a maximum length, adding suffix if truncated.\n *\n * @param text - Text to truncate\n * @param maxLength - Maximum length including suffix\n * @param suffix - Suffix to append when truncated (default: \"...\")\n * @returns Truncated text\n *\n * @example\n * ```typescript\n * truncate(\"Hello, World!\", 10); // \"Hello, ...\"\n * truncate(\"Short\", 10); // \"Short\"\n * truncate(\"Custom\", 6, \"…\"); // \"Custo…\"\n * ```\n */\nexport function truncate(text: string, maxLength: number, suffix = \"...\"): string {\n if (text.length <= maxLength) return text;\n const truncateAt = maxLength - suffix.length;\n if (truncateAt <= 0) return suffix.slice(0, maxLength);\n return text.slice(0, truncateAt) + suffix;\n}\n\n/**\n * Format bytes as human-readable string.\n *\n * @param bytes - Number of bytes\n * @param decimals - Number of decimal places (default: 1)\n * @returns Formatted string (e.g., \"1.5 KB\", \"2.3 MB\")\n *\n * @example\n * ```typescript\n * formatBytes(0); // \"0 B\"\n * formatBytes(1024); // \"1 KB\"\n * formatBytes(1536); // \"1.5 KB\"\n * formatBytes(1048576); // \"1 MB\"\n * ```\n */\nexport function formatBytes(bytes: number, decimals = 1): string {\n if (bytes === 0) return \"0 B\";\n\n const k = 1024;\n const sizes = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n const size = bytes / Math.pow(k, i);\n\n // Use integer for whole numbers, decimals otherwise\n const formatted = size % 1 === 0 ? size.toString() : size.toFixed(decimals);\n\n return `${formatted} ${sizes[i]}`;\n}\n\n/**\n * Format ISO date string as human-readable date.\n *\n * @param isoDate - ISO date string (e.g., \"2024-01-15T10:30:00Z\")\n * @param options - Intl.DateTimeFormat options\n * @returns Formatted date string\n *\n * @example\n * ```typescript\n * formatDate(\"2024-01-15T10:30:00Z\");\n * // \"Jan 15, 2024, 10:30 AM\" (in local timezone)\n *\n * formatDate(\"2024-01-15T10:30:00Z\", { dateStyle: \"short\" });\n * // \"1/15/24\"\n * ```\n */\nexport function formatDate(\n isoDate: string,\n options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n },\n): string {\n try {\n const date = new Date(isoDate);\n return date.toLocaleString(undefined, options);\n } catch {\n return isoDate; // Return original if parsing fails\n }\n}\n\n/**\n * Format duration in milliseconds as human-readable string.\n *\n * @param ms - Duration in milliseconds\n * @param options - Formatting options\n * @returns Formatted duration string\n *\n * @example\n * ```typescript\n * formatDuration(500); // \"500ms\"\n * formatDuration(1500); // \"1.5s\"\n * formatDuration(65000); // \"1m 5s\"\n * formatDuration(3725000); // \"1h 2m 5s\"\n * ```\n */\nexport function formatDuration(\n ms: number,\n options: { compact?: boolean } = {},\n): string {\n if (ms < 1000) {\n return `${Math.round(ms)}ms`;\n }\n\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n\n if (hours > 0) {\n const remainingMinutes = minutes % 60;\n const remainingSeconds = seconds % 60;\n if (options.compact) {\n return `${hours}h ${remainingMinutes}m`;\n }\n return remainingSeconds > 0\n ? `${hours}h ${remainingMinutes}m ${remainingSeconds}s`\n : `${hours}h ${remainingMinutes}m`;\n }\n\n if (minutes > 0) {\n const remainingSeconds = seconds % 60;\n return remainingSeconds > 0\n ? `${minutes}m ${remainingSeconds}s`\n : `${minutes}m`;\n }\n\n // Less than a minute - show seconds with one decimal if not whole\n const secs = ms / 1000;\n return secs % 1 === 0 ? `${secs}s` : `${secs.toFixed(1)}s`;\n}\n\n/**\n * Format namespace object for convenient access.\n *\n * @example\n * ```typescript\n * import { format } from \"llmist\";\n *\n * format.truncate(\"text\", 5);\n * format.bytes(1024);\n * format.date(\"2024-01-15\");\n * format.duration(5000);\n * ```\n */\nexport const format = {\n truncate,\n bytes: formatBytes,\n date: formatDate,\n duration: formatDuration,\n} as const;\n","/**\n * Timing utilities for gadget authors.\n *\n * Provides common timing functions for:\n * - Random delays (human-like timing)\n * - Timeout handling\n * - Retry logic with backoff\n *\n * @module utils/timing\n *\n * @example\n * ```typescript\n * import { timing } from \"llmist\";\n *\n * // Human-like delays for browser automation\n * await timing.humanDelay(50, 150);\n *\n * // Add timeout to async operations\n * const result = await timing.withTimeout(\n * () => fetchData(),\n * 5000,\n * signal\n * );\n *\n * // Retry with exponential backoff\n * const data = await timing.withRetry(\n * () => unreliableApi(),\n * { maxRetries: 3, delay: 1000, backoff: \"exponential\" }\n * );\n * ```\n */\n\n/**\n * Generate a random delay within a range.\n *\n * @param min - Minimum delay in milliseconds\n * @param max - Maximum delay in milliseconds\n * @returns Random integer between min and max (inclusive)\n *\n * @example\n * ```typescript\n * const delay = randomDelay(50, 150); // e.g., 87\n * ```\n */\nexport function randomDelay(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\n/**\n * Sleep for a random duration (for human-like timing).\n *\n * Useful for browser automation to appear more human-like.\n *\n * @param min - Minimum delay in milliseconds (default: 50)\n * @param max - Maximum delay in milliseconds (default: 150)\n * @returns Promise that resolves after the random delay\n *\n * @example\n * ```typescript\n * // Default human-like delay (50-150ms)\n * await humanDelay();\n *\n * // Custom range for slower actions\n * await humanDelay(100, 300);\n * ```\n */\nexport async function humanDelay(min = 50, max = 150): Promise<void> {\n const delay = randomDelay(min, max);\n return new Promise((resolve) => setTimeout(resolve, delay));\n}\n\n/**\n * Execute an async function with a timeout.\n *\n * @param fn - Async function to execute\n * @param timeoutMs - Timeout in milliseconds\n * @param signal - Optional AbortSignal for early cancellation\n * @returns Promise that resolves with the function result or rejects on timeout\n * @throws Error with \"Operation timed out\" message if timeout is exceeded\n *\n * @example\n * ```typescript\n * const result = await withTimeout(\n * () => fetch(\"https://api.example.com/data\"),\n * 5000\n * );\n *\n * // With abort signal\n * const controller = new AbortController();\n * const result = await withTimeout(\n * () => longRunningTask(),\n * 30000,\n * controller.signal\n * );\n * ```\n */\nexport async function withTimeout<T>(\n fn: () => Promise<T>,\n timeoutMs: number,\n signal?: AbortSignal,\n): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n // Check if already aborted\n if (signal?.aborted) {\n reject(new Error(\"Operation aborted\"));\n return;\n }\n\n let settled = false;\n const timeoutId = setTimeout(() => {\n if (!settled) {\n settled = true;\n reject(new Error(`Operation timed out after ${timeoutMs}ms`));\n }\n }, timeoutMs);\n\n // Handle external abort\n const abortHandler = () => {\n if (!settled) {\n settled = true;\n clearTimeout(timeoutId);\n reject(new Error(\"Operation aborted\"));\n }\n };\n\n signal?.addEventListener(\"abort\", abortHandler);\n\n fn()\n .then((result) => {\n if (!settled) {\n settled = true;\n clearTimeout(timeoutId);\n signal?.removeEventListener(\"abort\", abortHandler);\n resolve(result);\n }\n })\n .catch((error) => {\n if (!settled) {\n settled = true;\n clearTimeout(timeoutId);\n signal?.removeEventListener(\"abort\", abortHandler);\n reject(error);\n }\n });\n });\n}\n\n/**\n * Options for retry logic.\n */\nexport interface RetryOptions {\n /** Maximum number of retry attempts (default: 3) */\n maxRetries?: number;\n /** Initial delay between retries in milliseconds (default: 1000) */\n delay?: number;\n /** Backoff strategy: \"linear\" adds delay, \"exponential\" doubles it (default: \"exponential\") */\n backoff?: \"linear\" | \"exponential\";\n /** Maximum delay cap in milliseconds (default: 30000) */\n maxDelay?: number;\n /** Optional function to determine if error is retryable (default: all errors) */\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n /** Optional callback on each retry attempt */\n onRetry?: (error: unknown, attempt: number, delay: number) => void;\n}\n\n/**\n * Execute an async function with retry logic.\n *\n * @param fn - Async function to execute\n * @param options - Retry options\n * @returns Promise that resolves with the function result or rejects after all retries exhausted\n *\n * @example\n * ```typescript\n * // Basic retry with defaults (3 retries, exponential backoff)\n * const result = await withRetry(() => unreliableApi());\n *\n * // Custom retry configuration\n * const result = await withRetry(\n * () => fetchWithErrors(),\n * {\n * maxRetries: 5,\n * delay: 500,\n * backoff: \"exponential\",\n * shouldRetry: (error) => error.status === 429 || error.status >= 500,\n * onRetry: (error, attempt, delay) => {\n * console.log(`Retry ${attempt} after ${delay}ms`);\n * }\n * }\n * );\n * ```\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {},\n): Promise<T> {\n const {\n maxRetries = 3,\n delay = 1000,\n backoff = \"exponential\",\n maxDelay = 30000,\n shouldRetry = () => true,\n onRetry,\n } = options;\n\n let lastError: unknown;\n let currentDelay = delay;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n\n // Check if we should retry\n if (attempt >= maxRetries || !shouldRetry(error, attempt)) {\n throw error;\n }\n\n // Calculate delay for next attempt\n const waitTime = Math.min(currentDelay, maxDelay);\n\n // Call onRetry callback\n onRetry?.(error, attempt + 1, waitTime);\n\n // Wait before retry\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n\n // Update delay for next iteration\n if (backoff === \"exponential\") {\n currentDelay *= 2;\n } else {\n currentDelay += delay;\n }\n }\n }\n\n // Should never reach here, but TypeScript needs it\n throw lastError;\n}\n\n/**\n * Timing namespace object for convenient access.\n *\n * @example\n * ```typescript\n * import { timing } from \"llmist\";\n *\n * await timing.humanDelay();\n * const result = await timing.withTimeout(() => fetch(url), 5000);\n * const data = await timing.withRetry(() => api.call(), { maxRetries: 3 });\n * ```\n */\nexport const timing = {\n randomDelay,\n humanDelay,\n withTimeout,\n withRetry,\n} as const;\n","/**\n * Session management interface and base class for gadget packages.\n *\n * Provides a standardized way to manage sessions (browser instances, API clients, etc.)\n * across gadgets. This enables:\n * - Consistent session lifecycle management\n * - Per-agent session isolation\n * - Automatic cleanup\n *\n * @module session/manager\n *\n * @example\n * ```typescript\n * import { BaseSessionManager, ISessionManager } from \"llmist\";\n *\n * // Extend for browser sessions\n * class BrowserSessionManager extends BaseSessionManager<Page, BrowserConfig> {\n * async createSession(config?: BrowserConfig): Promise<string> {\n * const browser = await launchBrowser(config);\n * const page = await browser.newPage();\n * const id = this.generateId(\"p\");\n * this.sessions.set(id, page);\n * return id;\n * }\n *\n * async closeSession(id: string): Promise<void> {\n * const page = this.sessions.get(id);\n * if (page) {\n * await page.close();\n * this.sessions.delete(id);\n * }\n * }\n * }\n * ```\n */\n\n/**\n * Interface for session managers.\n *\n * Session managers track and manage external resources (browser pages, API connections, etc.)\n * that need to be shared across multiple gadgets and properly cleaned up.\n *\n * @typeParam TSession - Type of session object (e.g., Page, APIClient)\n * @typeParam TConfig - Configuration type for creating sessions\n */\nexport interface ISessionManager<TSession = unknown, TConfig = unknown> {\n /**\n * Create a new session.\n *\n * @param config - Optional configuration for the session\n * @returns Promise resolving to the session ID\n */\n createSession(config?: TConfig): Promise<string>;\n\n /**\n * Get a session by ID.\n *\n * @param id - Session ID\n * @returns Session object or undefined if not found\n */\n getSession(id: string): TSession | undefined;\n\n /**\n * Get a session by ID, throwing if not found.\n *\n * @param id - Session ID\n * @returns Session object\n * @throws Error if session not found\n */\n requireSession(id: string): TSession;\n\n /**\n * Close and remove a session.\n *\n * @param id - Session ID to close\n */\n closeSession(id: string): Promise<void>;\n\n /**\n * Close all sessions.\n */\n closeAll(): Promise<void>;\n\n /**\n * List all active session IDs.\n *\n * @returns Array of session IDs\n */\n listSessions(): string[];\n\n /**\n * Check if a session exists.\n *\n * @param id - Session ID\n * @returns True if session exists\n */\n hasSession(id: string): boolean;\n}\n\n/**\n * Base implementation of session manager with common functionality.\n *\n * Extend this class to create domain-specific session managers.\n * You only need to implement `createSession` and `closeSession`.\n *\n * @typeParam TSession - Type of session object\n * @typeParam TConfig - Configuration type for creating sessions\n *\n * @example\n * ```typescript\n * class APIClientManager extends BaseSessionManager<APIClient, APIConfig> {\n * async createSession(config?: APIConfig): Promise<string> {\n * const client = new APIClient(config);\n * const id = this.generateId(\"api\");\n * this.sessions.set(id, client);\n * return id;\n * }\n *\n * async closeSession(id: string): Promise<void> {\n * const client = this.sessions.get(id);\n * if (client) {\n * await client.disconnect();\n * this.sessions.delete(id);\n * }\n * }\n * }\n * ```\n */\nexport abstract class BaseSessionManager<TSession, TConfig = unknown>\n implements ISessionManager<TSession, TConfig>\n{\n /** Map of session ID to session object */\n protected sessions = new Map<string, TSession>();\n\n /** Counter for generating unique session IDs */\n protected idCounter = 0;\n\n /**\n * Generate a unique session ID with the given prefix.\n *\n * @param prefix - Prefix for the ID (e.g., \"p\" for pages, \"b\" for browsers)\n * @returns Unique ID like \"p1\", \"p2\", etc.\n */\n protected generateId(prefix: string): string {\n return `${prefix}${++this.idCounter}`;\n }\n\n /**\n * Create a new session.\n * Must be implemented by subclasses.\n */\n abstract createSession(config?: TConfig): Promise<string>;\n\n /**\n * Close and remove a session.\n * Must be implemented by subclasses.\n */\n abstract closeSession(id: string): Promise<void>;\n\n /**\n * Get a session by ID.\n */\n getSession(id: string): TSession | undefined {\n return this.sessions.get(id);\n }\n\n /**\n * Get a session by ID, throwing if not found.\n */\n requireSession(id: string): TSession {\n const session = this.sessions.get(id);\n if (!session) {\n throw new Error(`Session not found: ${id}`);\n }\n return session;\n }\n\n /**\n * List all active session IDs.\n */\n listSessions(): string[] {\n return Array.from(this.sessions.keys());\n }\n\n /**\n * Check if a session exists.\n */\n hasSession(id: string): boolean {\n return this.sessions.has(id);\n }\n\n /**\n * Close all sessions.\n * Closes sessions in reverse order (most recent first).\n */\n async closeAll(): Promise<void> {\n const ids = this.listSessions().reverse();\n for (const id of ids) {\n try {\n await this.closeSession(id);\n } catch {\n // Continue closing other sessions even if one fails\n }\n }\n }\n}\n\n/**\n * Simple in-memory session manager for testing or lightweight use cases.\n *\n * Sessions are just stored objects with no special cleanup logic.\n *\n * @example\n * ```typescript\n * const manager = new SimpleSessionManager<MyData>();\n * const id = await manager.createSession({ value: 42 });\n * const data = manager.requireSession(id); // { value: 42 }\n * await manager.closeSession(id);\n * ```\n */\nexport class SimpleSessionManager<TSession> extends BaseSessionManager<TSession, TSession> {\n /**\n * Create a session by storing the provided data.\n */\n async createSession(data?: TSession): Promise<string> {\n const id = this.generateId(\"s\");\n if (data !== undefined) {\n this.sessions.set(id, data);\n }\n return id;\n }\n\n /**\n * Close a session by removing it from the map.\n */\n async closeSession(id: string): Promise<void> {\n this.sessions.delete(id);\n }\n\n /**\n * Set session data directly.\n */\n setSession(id: string, data: TSession): void {\n this.sessions.set(id, data);\n }\n}\n","/**\n * Subagent creation helper for gadget authors.\n *\n * Simplifies the common pattern of creating subagents from within gadgets.\n * Handles:\n * - Getting host exports (AgentBuilder, LLMist) from context\n * - Model resolution with \"inherit\" support\n * - Parent context sharing for cost tracking\n * - Common configuration options\n *\n * @module agent/subagent\n *\n * @example\n * ```typescript\n * import { createSubagent, Gadget, z } from \"llmist\";\n * import type { ExecutionContext } from \"llmist\";\n *\n * class BrowseWeb extends Gadget({\n * name: \"BrowseWeb\",\n * schema: z.object({\n * task: z.string(),\n * url: z.string().url(),\n * model: z.string().optional(),\n * }),\n * }) {\n * async execute(params: this[\"params\"], ctx?: ExecutionContext) {\n * const agent = createSubagent(ctx!, {\n * name: \"BrowseWeb\",\n * gadgets: [Navigate, Click, Screenshot],\n * systemPrompt: BROWSER_SYSTEM_PROMPT,\n * model: params.model, // Optional override\n * maxIterations: 15,\n * }).ask(params.task);\n *\n * for await (const event of agent.run()) {\n * // Process events...\n * }\n *\n * return result;\n * }\n * }\n * ```\n */\n\nimport type { AbstractGadget } from \"../gadgets/gadget.js\";\nimport type { ExecutionContext, HostExports } from \"../gadgets/types.js\";\nimport { resolveSubagentModel, resolveValue } from \"../utils/config-resolver.js\";\nimport type { AgentBuilder } from \"./builder.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n/**\n * Options for creating a subagent.\n */\nexport interface SubagentOptions {\n /**\n * Name of the subagent (used for config resolution).\n * Should match the gadget name in CLI config, e.g., \"BrowseWeb\".\n */\n name: string;\n\n /**\n * Gadgets to register with the subagent.\n */\n gadgets: AbstractGadget[];\n\n /**\n * System prompt for the subagent.\n */\n systemPrompt?: string;\n\n /**\n * Model to use. If not provided, inherits from parent or uses default.\n * Can be a runtime parameter from gadget params.\n */\n model?: string;\n\n /**\n * Default model if no other source provides one.\n * @default \"sonnet\"\n */\n defaultModel?: string;\n\n /**\n * Maximum iterations for the agent loop.\n */\n maxIterations?: number;\n\n /**\n * Default max iterations if not specified.\n * @default 15\n */\n defaultMaxIterations?: number;\n\n /**\n * Agent hooks for observers, interceptors, controllers.\n */\n hooks?: AgentHooks;\n\n /**\n * Temperature for LLM calls.\n */\n temperature?: number;\n}\n\n/**\n * Get host exports from execution context.\n *\n * This helper ensures gadgets use the same llmist version as the host CLI,\n * avoiding the \"dual-package problem\" where different versions have\n * incompatible classes.\n *\n * @param ctx - Execution context from gadget execute()\n * @returns Host exports (AgentBuilder, LLMist, etc.)\n * @throws Error if host exports not available\n */\nfunction getHostExports(ctx: ExecutionContext): HostExports {\n if (!ctx?.hostExports) {\n throw new Error(\n \"hostExports not available. Subagent gadgets must be run via llmist agent. \" +\n \"Ensure you are using llmist >= 6.2.0 and running through the CLI or AgentBuilder.\",\n );\n }\n return ctx.hostExports;\n}\n\n/**\n * Create a subagent from within a gadget.\n *\n * This helper simplifies the common pattern of creating nested agents.\n * It automatically:\n * - Gets the correct AgentBuilder from host exports\n * - Resolves model with \"inherit\" support from CLI config\n * - Shares the parent's execution tree for cost tracking\n * - Forwards the abort signal for proper cancellation\n * - Inherits human input handler (for 2FA, CAPTCHAs, etc.)\n *\n * @param ctx - ExecutionContext passed to gadget's execute()\n * @param options - Subagent configuration options\n * @returns Configured AgentBuilder ready for .ask()\n *\n * @example\n * ```typescript\n * // Basic usage\n * const agent = createSubagent(ctx, {\n * name: \"BrowseWeb\",\n * gadgets: [Navigate, Click],\n * }).ask(\"Go to google.com\");\n *\n * // With all options\n * const agent = createSubagent(ctx, {\n * name: \"BrowseWeb\",\n * gadgets: [Navigate, Click, Screenshot],\n * systemPrompt: \"You are a browser automation agent...\",\n * model: params.model, // Runtime override\n * defaultModel: \"sonnet\",\n * maxIterations: 20,\n * hooks: {\n * observers: {\n * onLLMCallReady: () => refreshPageState(),\n * },\n * },\n * }).ask(params.task);\n *\n * for await (const event of agent.run()) {\n * // Events flow through shared tree automatically\n * }\n *\n * // Human input bubbles up automatically:\n * // If a gadget throws HumanInputRequiredException,\n * // the parent's onHumanInput handler will be called\n * ```\n */\nexport function createSubagent(\n ctx: ExecutionContext,\n options: SubagentOptions,\n): AgentBuilder {\n const {\n name,\n gadgets,\n systemPrompt,\n model: runtimeModel,\n defaultModel = \"sonnet\",\n maxIterations: runtimeMaxIterations,\n defaultMaxIterations = 15,\n hooks,\n temperature,\n } = options;\n\n // Get host's AgentBuilder to ensure tree sharing works correctly\n const { AgentBuilder, LLMist } = getHostExports(ctx);\n\n // Create LLMist client for the subagent\n const client = new LLMist();\n\n // Resolve model with config hierarchy support\n const model = resolveSubagentModel(ctx, name, runtimeModel, defaultModel);\n\n // Resolve max iterations\n const maxIterations = resolveValue(ctx, name, {\n runtime: runtimeMaxIterations,\n subagentKey: \"maxIterations\",\n defaultValue: defaultMaxIterations,\n });\n\n // Build the subagent\n let builder = new AgentBuilder(client)\n .withModel(model)\n .withGadgets(...gadgets)\n .withMaxIterations(maxIterations)\n .withParentContext(ctx); // Share tree, forward signal\n\n // Inherit human input capability from parent context\n // This allows subagents to bubble up input requests (e.g., 2FA codes)\n if (ctx.requestHumanInput) {\n builder = builder.onHumanInput(ctx.requestHumanInput);\n }\n\n // Apply optional configuration\n if (systemPrompt) {\n builder = builder.withSystem(systemPrompt);\n }\n\n if (hooks) {\n builder = builder.withHooks(hooks);\n }\n\n if (temperature !== undefined) {\n builder = builder.withTemperature(temperature);\n }\n\n // Forward logger from parent context if available\n if (ctx.logger) {\n builder = builder.withLogger(ctx.logger);\n }\n\n return builder;\n}\n\n/**\n * Check if an execution context has valid host exports.\n *\n * Useful for conditional logic when gadgets may run standalone or via agent.\n *\n * @param ctx - Execution context\n * @returns True if host exports are available\n */\nexport function hasHostExports(ctx?: ExecutionContext): boolean {\n return ctx?.hostExports !== undefined;\n}\n","/**\n * Package manifest types for llmist gadget packages.\n *\n * These types define the structure of the `llmist` field in package.json\n * for gadget packages. This enables:\n * - Preset-based gadget loading\n * - Subagent discovery\n * - Factory function support\n * - Session management metadata\n *\n * @module package/manifest\n *\n * @example package.json\n * ```json\n * {\n * \"name\": \"dhalsim\",\n * \"llmist\": {\n * \"gadgets\": \"./dist/index.js\",\n * \"factory\": \"./dist/index.js\",\n * \"presets\": {\n * \"minimal\": [\"Navigate\", \"GetFullPageContent\"],\n * \"readonly\": [\"Navigate\", \"GetFullPageContent\", \"Screenshot\"],\n * \"all\": \"*\"\n * },\n * \"subagents\": {\n * \"BrowseWeb\": {\n * \"entryPoint\": \"./dist/index.js\",\n * \"export\": \"Dhalsim\",\n * \"description\": \"Autonomous web browser agent\",\n * \"defaultModel\": \"sonnet\",\n * \"maxIterations\": 15\n * }\n * },\n * \"session\": {\n * \"factory\": \"getSessionManager\",\n * \"type\": \"browser\"\n * }\n * }\n * }\n * ```\n */\n\n/**\n * Subagent definition in the manifest.\n */\nexport interface SubagentManifestEntry {\n /**\n * Entry point file path relative to package root.\n * @example \"./dist/index.js\"\n */\n entryPoint: string;\n\n /**\n * Export name from the entry point.\n * @example \"Dhalsim\" or \"BrowseWeb\"\n */\n export: string;\n\n /**\n * Human-readable description of what this subagent does.\n */\n description?: string;\n\n /**\n * List of gadget names this subagent uses internally.\n * Useful for documentation and dependency tracking.\n */\n uses?: string[];\n\n /**\n * Default model for this subagent.\n * Can be \"inherit\" to use parent's model.\n * @default \"inherit\"\n */\n defaultModel?: string;\n\n /**\n * Default maximum iterations.\n * @default 15\n */\n maxIterations?: number;\n}\n\n/**\n * Session factory metadata in the manifest.\n */\nexport interface SessionManifestEntry {\n /**\n * Export name of the session factory function.\n * @example \"getSessionManager\"\n */\n factory: string;\n\n /**\n * Type of session for categorization.\n * @example \"browser\", \"api\", \"database\"\n */\n type: string;\n}\n\n/**\n * Preset definition - either an array of gadget names or \"*\" for all.\n */\nexport type PresetDefinition = string[] | \"*\";\n\n/**\n * llmist package manifest structure.\n *\n * This is the shape of the `llmist` field in package.json\n * for gadget packages.\n */\nexport interface LLMistPackageManifest {\n /**\n * Entry point for all gadgets.\n * The module should export gadgets or a gadgets array.\n * @example \"./dist/index.js\"\n */\n gadgets?: string;\n\n /**\n * Entry point for factory functions.\n * Should export `createGadgetsByPreset(preset)` and/or `createGadgetsByName(names)`.\n * @example \"./dist/index.js\"\n */\n factory?: string;\n\n /**\n * Subagent definitions.\n * Key is the subagent name as it appears in CLI config.\n */\n subagents?: Record<string, SubagentManifestEntry>;\n\n /**\n * Preset definitions.\n * Key is preset name, value is array of gadget names or \"*\" for all.\n * @example { \"minimal\": [\"Navigate\", \"Screenshot\"], \"all\": \"*\" }\n */\n presets?: Record<string, PresetDefinition>;\n\n /**\n * Session factory metadata.\n */\n session?: SessionManifestEntry;\n}\n\n/**\n * Factory function types that packages can export.\n */\nexport interface GadgetFactoryExports {\n /**\n * Create gadgets by preset name.\n */\n createGadgetsByPreset?: (preset: string, config?: unknown) => unknown;\n\n /**\n * Create gadgets by specific names.\n */\n createGadgetsByName?: (names: string[], config?: unknown) => unknown;\n\n /**\n * Create all gadgets with optional config.\n */\n createGadgets?: (config?: unknown) => unknown;\n}\n\n/**\n * Read and parse the llmist manifest from a package.json object.\n *\n * @param packageJson - Parsed package.json object\n * @returns Manifest or undefined if not present\n *\n * @example\n * ```typescript\n * import { readFileSync } from \"fs\";\n *\n * const pkg = JSON.parse(readFileSync(\"package.json\", \"utf-8\"));\n * const manifest = parseManifest(pkg);\n *\n * if (manifest?.presets?.minimal) {\n * console.log(\"Minimal preset:\", manifest.presets.minimal);\n * }\n * ```\n */\nexport function parseManifest(\n packageJson: Record<string, unknown>,\n): LLMistPackageManifest | undefined {\n const llmist = packageJson.llmist;\n if (!llmist || typeof llmist !== \"object\") {\n return undefined;\n }\n return llmist as LLMistPackageManifest;\n}\n\n/**\n * Check if a manifest has a specific preset.\n */\nexport function hasPreset(\n manifest: LLMistPackageManifest | undefined,\n presetName: string,\n): boolean {\n return manifest?.presets?.[presetName] !== undefined;\n}\n\n/**\n * Get gadget names for a preset.\n * Returns undefined if preset not found, empty array if preset is invalid.\n */\nexport function getPresetGadgets(\n manifest: LLMistPackageManifest | undefined,\n presetName: string,\n): string[] | \"*\" | undefined {\n const preset = manifest?.presets?.[presetName];\n if (preset === undefined) return undefined;\n return preset;\n}\n\n/**\n * Check if a manifest has subagent definitions.\n */\nexport function hasSubagents(manifest: LLMistPackageManifest | undefined): boolean {\n return manifest?.subagents !== undefined && Object.keys(manifest.subagents).length > 0;\n}\n\n/**\n * Get subagent entry by name.\n */\nexport function getSubagent(\n manifest: LLMistPackageManifest | undefined,\n name: string,\n): SubagentManifestEntry | undefined {\n return manifest?.subagents?.[name];\n}\n\n/**\n * List all subagent names in a manifest.\n */\nexport function listSubagents(manifest: LLMistPackageManifest | undefined): string[] {\n if (!manifest?.subagents) return [];\n return Object.keys(manifest.subagents);\n}\n\n/**\n * List all preset names in a manifest.\n */\nexport function listPresets(manifest: LLMistPackageManifest | undefined): string[] {\n if (!manifest?.presets) return [];\n return Object.keys(manifest.presets);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IACa,qBACA,mBACA,mBAQA,6BAGA,qCAGA,iBAGA;AApBb;AAAA;AAAA;AACO,IAAM,sBAAsB;AAC5B,IAAM,oBAAoB;AAC1B,IAAM,oBAAoB;AAQ1B,IAAM,8BAA8B;AAGpC,IAAM,sCAAsC;AAG5C,IAAM,kBAAkB;AAGxB,IAAM,0BAA0B;AAAA;AAAA;;;ACpBvC,IAsBa,qCAkBA,0BAoBA,gCAcA,6BAaA;AAvFb,IAAAA,kBAAA;AAAA;AAAA;AAsBO,IAAM,sCAAsC;AAkB5C,IAAM,2BAA2B;AAoBjC,IAAM,iCAAiC;AAcvC,IAAM,8BAA8B;AAapC,IAAM,oCAAoC;AAAA;AAAA;;;AC6B1C,SAAS,WAAW,MAA4C;AACrE,SAAO,KAAK,SAAS;AACvB;AAKO,SAAS,YAAY,MAA6C;AACvE,SAAO,KAAK,SAAS;AACvB;AAKO,SAAS,YAAY,MAA6C;AACvE,SAAO,KAAK,SAAS;AACvB;AA4BO,SAAS,KAAK,SAAkC;AACrD,SAAO,EAAE,MAAM,QAAQ,MAAM,QAAQ;AACvC;AAaO,SAAS,gBAAgB,MAAc,WAA4C;AACxF,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,EAAE,MAAM,UAAU,WAAW,KAAK;AAAA,EAC5C;AACF;AAaO,SAAS,aAAa,KAA+B;AAC1D,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,EAAE,MAAM,OAAO,IAAI;AAAA,EAC7B;AACF;AAsCO,SAAS,oBAAoB,MAAiD;AACnF,QAAM,QAAQ,gBAAgB,SAAS,OAAO,OAAO,KAAK,IAAI;AAE9D,aAAW,EAAE,OAAO,OAAO,SAAS,KAAK,mBAAmB;AAC1D,QAAI,MAAM,UAAU,MAAM,QAAQ;AAChC,UAAI,UAAU;AACd,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAI,MAAM,CAAC,MAAM,MAAM,CAAC,GAAG;AACzB,oBAAU;AACV;AAAA,QACF;AAAA,MACF;AACA,UAAI,SAAS;AAEX,YAAI,aAAa,cAAc;AAE7B,cAAI,MAAM,UAAU,IAAI;AACtB,kBAAM,aACJ,MAAM,CAAC,MAAM,MAAQ,MAAM,CAAC,MAAM,MAAQ,MAAM,EAAE,MAAM,MAAQ,MAAM,EAAE,MAAM;AAChF,gBAAI,CAAC,WAAY;AAAA,UACnB;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,oBAAoB,MAAiD;AACnF,QAAM,QAAQ,gBAAgB,SAAS,OAAO,OAAO,KAAK,IAAI;AAE9D,aAAW,EAAE,OAAO,OAAO,SAAS,KAAK,mBAAmB;AAC1D,QAAI,MAAM,UAAU,MAAM,QAAQ;AAChC,UAAI,UAAU;AACd,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAI,MAAM,CAAC,MAAM,MAAM,CAAC,GAAG;AACzB,oBAAU;AACV;AAAA,QACF;AAAA,MACF;AACA,UAAI,SAAS;AAEX,YAAI,aAAa,aAAa;AAE5B,cAAI,MAAM,UAAU,IAAI;AACtB,kBAAM,aACJ,MAAM,CAAC,MAAM,MAAQ,MAAM,CAAC,MAAM,MAAQ,MAAM,EAAE,MAAM,MAAQ,MAAM,EAAE,MAAM;AAChF,gBAAI,CAAC,WAAY;AAAA,UACnB;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,SAAS,MAA4C;AACnE,MAAI,OAAO,SAAS,UAAU;AAC5B,WAAO;AAAA,EACT;AACA,SAAO,OAAO,KAAK,IAAI,EAAE,SAAS,QAAQ;AAC5C;AAeO,SAAS,gBACd,QACA,WACkB;AAClB,QAAM,eAAe,aAAa,oBAAoB,MAAM;AAC5D,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM,SAAS,MAAM;AAAA,IACvB;AAAA,EACF;AACF;AAaO,SAAS,gBAAgB,MAAc,WAA4C;AACxF,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ,EAAE,MAAM,UAAU,WAAW,KAAK;AAAA,EAC5C;AACF;AAeO,SAAS,gBACd,QACA,WACkB;AAClB,QAAM,eAAe,aAAa,oBAAoB,MAAM;AAC5D,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,WAAW;AAAA,MACX,MAAM,SAAS,MAAM;AAAA,IACvB;AAAA,EACF;AACF;AAYO,SAAS,UAAU,OAAwB;AAChD,SAAO,MAAM,WAAW,OAAO;AACjC;AAcO,SAAS,aAAa,KAAwD;AACnF,QAAM,QAAQ,IAAI,MAAM,4BAA4B;AACpD,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,EAAE,UAAU,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,EAAE;AAC9C;AA3aA,IA2MM,mBAWA;AAtNN;AAAA;AAAA;AA2MA,IAAM,oBAAyE;AAAA,MAC7E,EAAE,OAAO,CAAC,KAAM,KAAM,GAAI,GAAG,UAAU,aAAa;AAAA,MACpD,EAAE,OAAO,CAAC,KAAM,IAAM,IAAM,EAAI,GAAG,UAAU,YAAY;AAAA,MACzD,EAAE,OAAO,CAAC,IAAM,IAAM,IAAM,EAAI,GAAG,UAAU,YAAY;AAAA;AAAA,MAEzD,EAAE,OAAO,CAAC,IAAM,IAAM,IAAM,EAAI,GAAG,UAAU,aAAa;AAAA,IAC5D;AAKA,IAAM,oBAAyE;AAAA;AAAA,MAE7E,EAAE,OAAO,CAAC,KAAM,GAAI,GAAG,UAAU,YAAY;AAAA,MAC7C,EAAE,OAAO,CAAC,KAAM,GAAI,GAAG,UAAU,YAAY;AAAA;AAAA,MAE7C,EAAE,OAAO,CAAC,IAAM,IAAM,EAAI,GAAG,UAAU,YAAY;AAAA;AAAA,MAEnD,EAAE,OAAO,CAAC,IAAM,KAAM,KAAM,EAAI,GAAG,UAAU,YAAY;AAAA;AAAA,MAEzD,EAAE,OAAO,CAAC,IAAM,IAAM,IAAM,EAAI,GAAG,UAAU,YAAY;AAAA;AAAA,MAEzD,EAAE,OAAO,CAAC,IAAM,IAAM,KAAM,GAAI,GAAG,UAAU,aAAa;AAAA;AAAA,MAE1D,EAAE,OAAO,CAAC,KAAM,IAAM,IAAM,EAAI,GAAG,UAAU,aAAa;AAAA,IAC5D;AAAA;AAAA;;;AC1IA,SAAS,oBAAoB,OAAwB;AACnD,QAAM,aAAa,MAAM,YAAY;AAGrC,MAAI,cAAc,UAAU,GAAG;AAC7B,WAAO;AAAA,EACT;AAGA,SAAO,qBAAqB,KAAK,CAAC,YAAY,QAAQ,KAAK,KAAK,CAAC;AACnE;AAkCO,SAAS,aAAa,OAAe,UAA+B,CAAC,GAAW;AAErF,MAAI,MAAM,SAAS,GAAG,GAAG;AACvB,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,MAAM,YAAY;AACrC,MAAI,cAAc,UAAU,GAAG;AAC7B,WAAO,cAAc,UAAU;AAAA,EACjC;AAGA,QAAM,aAAa,MAAM,YAAY;AAGrC,MAAI,WAAW,WAAW,KAAK,GAAG;AAChC,WAAO,UAAU,KAAK;AAAA,EACxB;AAGA,MAAI,WAAW,WAAW,QAAQ,GAAG;AACnC,WAAO,aAAa,KAAK;AAAA,EAC3B;AAGA,MAAI,WAAW,WAAW,QAAQ,GAAG;AACnC,WAAO,UAAU,KAAK;AAAA,EACxB;AAGA,MAAI,WAAW,MAAM,MAAM,GAAG;AAC5B,WAAO,UAAU,KAAK;AAAA,EACxB;AAGA,MAAI,CAAC,oBAAoB,KAAK,GAAG;AAC/B,QAAI,QAAQ,QAAQ;AAClB,YAAM,IAAI;AAAA,QACR,kBAAkB,KAAK,iGACwB,KAAK;AAAA,MACtD;AAAA,IACF;AAEA,QAAI,CAAC,QAAQ,QAAQ;AACnB,cAAQ;AAAA,QACN,gCAAsB,KAAK,8BAA8B,KAAK;AAAA,MAGhE;AAAA,IACF;AAAA,EACF;AAIA,SAAO,UAAU,KAAK;AACxB;AAeO,SAAS,kBAAkB,OAAwB;AACxD,SAAO,MAAM,SAAS,GAAG;AAC3B;AAeO,SAAS,YAAY,OAAmC;AAC7D,QAAM,iBAAiB,MAAM,QAAQ,GAAG;AACxC,MAAI,mBAAmB,IAAI;AACzB,WAAO;AAAA,EACT;AACA,SAAO,MAAM,MAAM,GAAG,cAAc;AACtC;AAeO,SAAS,WAAW,OAAuB;AAChD,QAAM,iBAAiB,MAAM,QAAQ,GAAG;AACxC,MAAI,mBAAmB,IAAI;AACzB,WAAO;AAAA,EACT;AACA,SAAO,MAAM,MAAM,iBAAiB,CAAC;AACvC;AAzPA,IAwBa,eAqDP;AA7EN;AAAA;AAAA;AAwBO,IAAM,gBAAwC;AAAA;AAAA,MAEnD,MAAM;AAAA,MACN,OAAO;AAAA,MACP,cAAc;AAAA,MACd,MAAM;AAAA;AAAA,MACN,UAAU;AAAA,MACV,UAAU;AAAA,MACV,aAAa;AAAA,MACb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,WAAW;AAAA;AAAA,MAGX,QAAQ;AAAA,MACR,iBAAiB;AAAA,MACjB,OAAO;AAAA,MACP,gBAAgB;AAAA,MAChB,MAAM;AAAA,MACN,eAAe;AAAA;AAAA,MAGf,OAAO;AAAA,MACP,gBAAgB;AAAA,MAChB,cAAc;AAAA,MACd,cAAc;AAAA,MACd,KAAK;AAAA,IACP;AAwBA,IAAM,uBAAuB;AAAA,MAC3B;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,IACF;AAAA;AAAA;;;ACvEO,SAAS,qBAAqB,QAAoB,YAA0B;AACjF,MAAI;AACJ,MAAI;AACF,iBAAe,eAAa,QAAQ,EAAE,QAAQ,UAAU,CAAC;AAAA,EAC3D,SAAS,OAAO;AACd,UAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,UAAM,IAAI;AAAA,MACR,WAAW,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAMA,YAAY;AAAA;AAAA;AAAA,IAGnC;AAAA,EACF;AACA,QAAM,SAAS,iBAAiB,UAAU;AAE1C,MAAI,OAAO,SAAS,GAAG;AACrB,UAAM,YAAY,OAAO,KAAK,IAAI;AAClC,UAAM,IAAI;AAAA,MACR,WAAW,UAAU;AAAA,sBACI,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAkBpC;AAAA,EACF;AACF;AAWA,SAAS,iBAAiB,QAAa,OAAiB,CAAC,GAAa;AACpE,QAAM,SAAmB,CAAC;AAE1B,MAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,aAAa;AACtB,eAAW,aAAa,OAAO,OAAO,OAAO,WAAW,GAAG;AACzD,aAAO,KAAK,GAAG,iBAAiB,WAAW,CAAC,CAAC,CAAC;AAAA,IAChD;AAAA,EACF;AAGA,MAAI,OAAO,YAAY;AACrB,eAAW,CAAC,UAAU,UAAU,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AACtE,YAAM,WAAW,CAAC,GAAG,MAAM,QAAQ;AAGnC,UAAI,UAAU,UAAU,GAAG;AACzB,eAAO,KAAK,SAAS,KAAK,GAAG,KAAK,QAAQ;AAAA,MAC5C;AAGA,aAAO,KAAK,GAAG,iBAAiB,YAAY,QAAQ,CAAC;AAAA,IACvD;AAAA,EACF;AAGA,MAAI,OAAO,OAAO;AAChB,UAAM,WAAW,CAAC,GAAG,MAAM,IAAI;AAC/B,QAAI,UAAU,OAAO,KAAK,GAAG;AAC3B,aAAO,KAAK,SAAS,KAAK,GAAG,CAAC;AAAA,IAChC;AACA,WAAO,KAAK,GAAG,iBAAiB,OAAO,OAAO,QAAQ,CAAC;AAAA,EACzD;AAGA,MAAI,OAAO,OAAO;AAEhB,WAAO,MAAM,QAAQ,CAAC,WAAgB,UAAkB;AACtD,aAAO,KAAK,GAAG,iBAAiB,WAAW,CAAC,GAAG,MAAM,SAAS,KAAK,GAAG,CAAC,CAAC;AAAA,IAC1E,CAAC;AAAA,EACH;AAEA,MAAI,OAAO,OAAO;AAEhB,WAAO,MAAM,QAAQ,CAAC,WAAgB,UAAkB;AACtD,aAAO,KAAK,GAAG,iBAAiB,WAAW,CAAC,GAAG,MAAM,SAAS,KAAK,GAAG,CAAC,CAAC;AAAA,IAC1E,CAAC;AAAA,EACH;AAEA,MAAI,OAAO,OAAO;AAEhB,WAAO,MAAM,QAAQ,CAAC,WAAgB,UAAkB;AACtD,aAAO,KAAK,GAAG,iBAAiB,WAAW,CAAC,GAAG,MAAM,SAAS,KAAK,GAAG,CAAC,CAAC;AAAA,IAC1E,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAiBA,SAAS,UAAU,MAAoB;AACrC,MAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,KAAK,SAAS;AAC9B,QAAM,SAAS,KAAK,SAAS;AAC7B,QAAM,WAAW,KAAK,UAAU,UAAa,KAAK,UAAU,UAAa,KAAK,UAAU;AAGxF,MAAI,WAAW,UAAU,UAAU;AACjC,WAAO;AAAA,EACT;AAGA,QAAM,OAAO,OAAO,KAAK,IAAI;AAC7B,QAAM,eAAe,CAAC,eAAe,SAAS,WAAW,UAAU;AACnE,QAAM,kBAAkB,KAAK,MAAM,CAAC,QAAQ,aAAa,SAAS,GAAG,CAAC;AAGtE,SAAO,mBAAmB,KAAK,WAAW;AAC5C;AArKA,IACA;AADA;AAAA;AAAA;AACA,QAAmB;AAAA;AAAA;;;ACDnB,IASa;AATb;AAAA;AAAA;AACA;AAQO,IAAM,iBAAN,MAAM,gBAAe;AAAA,MACT,UAAU,oBAAI,IAA4B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAwB3D,OAAO,KAAK,SAA0E;AACpF,cAAM,WAAW,IAAI,gBAAe;AAEpC,YAAI,MAAM,QAAQ,OAAO,GAAG;AAE1B,mBAAS,aAAa,OAAO;AAAA,QAC/B,OAAO;AAEL,qBAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,GAAG;AACpD,kBAAM,WAAW,OAAO,WAAW,aAAa,IAAI,OAAO,IAAI;AAC/D,qBAAS,SAAS,MAAM,QAAQ;AAAA,UAClC;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcA,aAAa,SAAgC;AAC3C,mBAAW,UAAU,SAAS;AAC5B,gBAAM,WAAW,OAAO,WAAW,aAAa,IAAI,OAAO,IAAI;AAC/D,eAAK,gBAAgB,QAAQ;AAAA,QAC/B;AACA,eAAO;AAAA,MACT;AAAA;AAAA,MAGA,SAAS,MAAc,QAA8B;AACnD,cAAM,iBAAiB,KAAK,YAAY;AACxC,YAAI,KAAK,QAAQ,IAAI,cAAc,GAAG;AACpC,gBAAM,IAAI,MAAM,WAAW,IAAI,yBAAyB;AAAA,QAC1D;AAGA,YAAI,OAAO,iBAAiB;AAC1B,+BAAqB,OAAO,iBAAiB,IAAI;AAAA,QACnD;AAEA,aAAK,QAAQ,IAAI,gBAAgB,MAAM;AAAA,MACzC;AAAA;AAAA,MAGA,gBAAgB,QAA8B;AAC5C,cAAM,OAAO,OAAO,QAAQ,OAAO,YAAY;AAC/C,aAAK,SAAS,MAAM,MAAM;AAAA,MAC5B;AAAA;AAAA,MAGA,IAAI,MAA0C;AAC5C,eAAO,KAAK,QAAQ,IAAI,KAAK,YAAY,CAAC;AAAA,MAC5C;AAAA;AAAA,MAGA,IAAI,MAAuB;AACzB,eAAO,KAAK,QAAQ,IAAI,KAAK,YAAY,CAAC;AAAA,MAC5C;AAAA;AAAA,MAGA,WAAqB;AACnB,eAAO,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAAA,MACvC;AAAA;AAAA,MAGA,SAA2B;AACzB,eAAO,MAAM,KAAK,KAAK,QAAQ,OAAO,CAAC;AAAA,MACzC;AAAA;AAAA,MAGA,WAAW,MAAuB;AAChC,eAAO,KAAK,QAAQ,OAAO,KAAK,YAAY,CAAC;AAAA,MAC/C;AAAA;AAAA,MAGA,QAAc;AACZ,aAAK,QAAQ,MAAM;AAAA,MACrB;AAAA,IACF;AAAA;AAAA;;;ACzHA,IAgOa;AAhOb;AAAA;AAAA;AAgOO,IAAM,gBAAN,MAAoB;AAAA,MACjB,QAAQ,oBAAI,IAA2B;AAAA,MACvC,UAAoB,CAAC;AAAA,MACrB,iBAAiB,oBAAI,IAA4C;AAAA,MACjE,iBAAiB;AAAA,MACjB,uBAAuB,oBAAI,IAAoB;AAAA;AAAA,MAG/C,aAA+B,CAAC;AAAA,MAChC,eAAuD,CAAC;AAAA,MACxD,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA,MAMN;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA;AAAA,MAEhB,YAAY,SAAgE;AAC1E,aAAK,YAAY,SAAS,aAAa;AACvC,aAAK,eAAe,SAAS,gBAAgB;AAAA,MAC/C;AAAA;AAAA;AAAA;AAAA,MAMQ,kBAAkB,WAAmB,UAAiC;AAC5E,YAAI,UAAU;AAEZ,iBAAO,OAAO,QAAQ,IAAI,SAAS;AAAA,QACrC;AACA,eAAO,OAAO,SAAS;AAAA,MACzB;AAAA,MAEQ,kBAAkB;AAAA,MAClB,iBAAiB,cAA8B;AACrD,eAAO,UAAU,YAAY,IAAI,EAAE,KAAK,eAAe;AAAA,MACzD;AAAA;AAAA;AAAA;AAAA,MAMQ,KAAK,OAA6B;AAExC,cAAM,YAAY,KAAK,eAAe,IAAI,MAAM,IAAI;AACpD,YAAI,WAAW;AACb,qBAAW,YAAY,WAAW;AAChC,gBAAI;AACF,uBAAS,KAAK;AAAA,YAChB,SAAS,OAAO;AACd,sBAAQ,MAAM,+BAA+B,MAAM,IAAI,KAAK,KAAK;AAAA,YACnE;AAAA,UACF;AAAA,QACF;AAGA,cAAM,eAAe,KAAK,eAAe,IAAI,GAAG;AAChD,YAAI,cAAc;AAChB,qBAAW,YAAY,cAAc;AACnC,gBAAI;AACF,uBAAS,KAAK;AAAA,YAChB,SAAS,OAAO;AACd,sBAAQ,MAAM,qCAAqC,KAAK;AAAA,YAC1D;AAAA,UACF;AAAA,QACF;AAGA,YAAI,KAAK,aAAa,SAAS,GAAG;AAChC,gBAAM,SAAS,KAAK,aAAa,MAAM;AACvC,cAAI,OAAQ,QAAO,KAAK;AAAA,QAC1B,OAAO;AACL,eAAK,WAAW,KAAK,KAAK;AAAA,QAC5B;AAAA,MACF;AAAA,MAEQ,qBAAqB,MAO3B;AACA,eAAO;AAAA,UACL,SAAS,EAAE,KAAK;AAAA,UAChB,WAAW,KAAK,IAAI;AAAA,UACpB,QAAQ,KAAK;AAAA,UACb,UAAU,KAAK;AAAA,UACf,OAAO,KAAK;AAAA,UACZ,MAAM,KAAK;AAAA,QACb;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,WAAW,QAAuC;AAChD,cAAM,WAAW,OAAO,YAAY,KAAK;AACzC,cAAM,SAAS,WAAW,KAAK,MAAM,IAAI,QAAQ,IAAI;AAErD,cAAM,QAAQ,SAAS,OAAO,QAAQ,IAAI,KAAK;AAC/C,cAAM,OAAO,SAAS,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC;AAE1C,cAAM,KAAK,KAAK,kBAAkB,OAAO,WAAW,QAAQ;AAC5D,aAAK,KAAK,EAAE;AAEZ,cAAM,OAAoB;AAAA,UACxB;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW,KAAK,IAAI;AAAA,UACpB,aAAa;AAAA,UACb,WAAW,OAAO;AAAA,UAClB,OAAO,OAAO;AAAA,UACd,SAAS,OAAO;AAAA,UAChB,UAAU;AAAA,UACV,UAAU,CAAC;AAAA,QACb;AAEA,aAAK,MAAM,IAAI,IAAI,IAAI;AAEvB,YAAI,CAAC,UAAU;AACb,eAAK,QAAQ,KAAK,EAAE;AAAA,QACtB,WAAW,QAAQ;AACjB,iBAAO,SAAS,KAAK,EAAE;AAAA,QACzB;AAEA,aAAK,KAAK;AAAA,UACR,MAAM;AAAA,UACN,GAAG,KAAK,qBAAqB,IAAI;AAAA,UACjC,WAAW,KAAK;AAAA,UAChB,OAAO,KAAK;AAAA,UACZ,SAAS,KAAK;AAAA,QAChB,CAAC;AAED,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,kBAAkB,QAAgB,OAAqB;AACrD,cAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,YAAI,CAAC,QAAQ,KAAK,SAAS,YAAY;AACrC,gBAAM,IAAI,MAAM,4BAA4B,MAAM,EAAE;AAAA,QACtD;AAEA,QAAC,KAAqB,YAAY;AAElC,aAAK,KAAK;AAAA,UACR,MAAM;AAAA,UACN,GAAG,KAAK,qBAAqB,IAAI;AAAA,UACjC;AAAA,QACF,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA,MAKA,gBAAgB,QAAgB,QAAqC;AACnE,cAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,YAAI,CAAC,QAAQ,KAAK,SAAS,YAAY;AACrC,gBAAM,IAAI,MAAM,4BAA4B,MAAM,EAAE;AAAA,QACtD;AAEA,cAAM,UAAU;AAChB,gBAAQ,cAAc,KAAK,IAAI;AAC/B,YAAI,OAAO,aAAa,OAAW,SAAQ,WAAW,OAAO;AAC7D,YAAI,OAAO,MAAO,SAAQ,QAAQ,OAAO;AACzC,YAAI,OAAO,iBAAiB,OAAW,SAAQ,eAAe,OAAO;AACrE,YAAI,OAAO,SAAS,OAAW,SAAQ,OAAO,OAAO;AAErD,aAAK,KAAK;AAAA,UACR,MAAM;AAAA,UACN,GAAG,KAAK,qBAAqB,IAAI;AAAA,UACjC,UAAU,QAAQ;AAAA,UAClB,OAAO,QAAQ;AAAA,UACf,cAAc,QAAQ;AAAA,UACtB,MAAM,QAAQ;AAAA,QAChB,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA,MAKA,YAAY,QAAgB,OAAc,WAA0B;AAClE,cAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,YAAI,CAAC,QAAQ,KAAK,SAAS,YAAY;AACrC,gBAAM,IAAI,MAAM,4BAA4B,MAAM,EAAE;AAAA,QACtD;AAEA,cAAM,UAAU;AAChB,gBAAQ,cAAc,KAAK,IAAI;AAE/B,aAAK,KAAK;AAAA,UACR,MAAM;AAAA,UACN,GAAG,KAAK,qBAAqB,IAAI;AAAA,UACjC;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA,MAKA,UAAU,QAAqC;AAC7C,cAAM,WAAW,OAAO,YAAY,KAAK,oBAAoB,KAAK,KAAK;AACvE,cAAM,SAAS,WAAW,KAAK,MAAM,IAAI,QAAQ,IAAI;AAErD,cAAM,QAAQ,SAAS,OAAO,QAAQ,IAAI,KAAK;AAC/C,cAAM,OAAO,SAAS,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC;AAE1C,cAAM,KAAK,KAAK,iBAAiB,OAAO,YAAY;AACpD,aAAK,KAAK,EAAE;AAEZ,cAAM,OAAmB;AAAA,UACvB;AAAA,UACA,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA,WAAW,KAAK,IAAI;AAAA,UACpB,aAAa;AAAA,UACb,cAAc,OAAO;AAAA,UACrB,MAAM,OAAO;AAAA,UACb,YAAY,OAAO;AAAA,UACnB,cAAc,OAAO,gBAAgB,CAAC;AAAA,UACtC,OAAO;AAAA,UACP,UAAU,CAAC;AAAA,UACX,YAAY;AAAA,QACd;AAEA,aAAK,MAAM,IAAI,IAAI,IAAI;AACvB,aAAK,qBAAqB,IAAI,OAAO,cAAc,EAAE;AAErD,YAAI,QAAQ;AACV,iBAAO,SAAS,KAAK,EAAE;AAAA,QACzB;AAEA,aAAK,KAAK;AAAA,UACR,MAAM;AAAA,UACN,GAAG,KAAK,qBAAqB,IAAI;AAAA,UACjC,cAAc,KAAK;AAAA,UACnB,MAAM,KAAK;AAAA,UACX,YAAY,KAAK;AAAA,UACjB,cAAc,KAAK;AAAA,QACrB,CAAC;AAED,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,YAAY,QAAsB;AAChC,cAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,YAAI,CAAC,QAAQ,KAAK,SAAS,UAAU;AACnC,gBAAM,IAAI,MAAM,0BAA0B,MAAM,EAAE;AAAA,QACpD;AAEA,cAAM,aAAa;AACnB,mBAAW,QAAQ;AAEnB,aAAK,KAAK;AAAA,UACR,MAAM;AAAA,UACN,GAAG,KAAK,qBAAqB,IAAI;AAAA,UACjC,cAAc,WAAW;AAAA,UACzB,MAAM,WAAW;AAAA,QACnB,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA,MAKA,eAAe,QAAgB,QAAoC;AACjE,cAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,YAAI,CAAC,QAAQ,KAAK,SAAS,UAAU;AACnC,gBAAM,IAAI,MAAM,0BAA0B,MAAM,EAAE;AAAA,QACpD;AAEA,cAAM,aAAa;AACnB,mBAAW,cAAc,KAAK,IAAI;AAClC,mBAAW,QAAQ,OAAO,QAAQ,WAAW;AAC7C,YAAI,OAAO,WAAW,OAAW,YAAW,SAAS,OAAO;AAC5D,YAAI,OAAO,MAAO,YAAW,QAAQ,OAAO;AAC5C,YAAI,OAAO,oBAAoB,OAAW,YAAW,kBAAkB,OAAO;AAC9E,YAAI,OAAO,SAAS,OAAW,YAAW,OAAO,OAAO;AACxD,YAAI,OAAO,MAAO,YAAW,QAAQ,OAAO;AAG5C,mBAAW,aAAa,WAAW,SAAS,KAAK,CAAC,YAAY;AAC5D,gBAAM,QAAQ,KAAK,MAAM,IAAI,OAAO;AACpC,iBAAO,OAAO,SAAS;AAAA,QACzB,CAAC;AAED,YAAI,OAAO,OAAO;AAChB,eAAK,KAAK;AAAA,YACR,MAAM;AAAA,YACN,GAAG,KAAK,qBAAqB,IAAI;AAAA,YACjC,cAAc,WAAW;AAAA,YACzB,MAAM,WAAW;AAAA,YACjB,OAAO,OAAO;AAAA,YACd,iBAAiB,OAAO,mBAAmB;AAAA,UAC7C,CAAC;AAAA,QACH,OAAO;AACL,eAAK,KAAK;AAAA,YACR,MAAM;AAAA,YACN,GAAG,KAAK,qBAAqB,IAAI;AAAA,YACjC,cAAc,WAAW;AAAA,YACzB,MAAM,WAAW;AAAA,YACjB,QAAQ,OAAO,UAAU;AAAA,YACzB,iBAAiB,OAAO,mBAAmB;AAAA,YAC3C,MAAM,OAAO;AAAA,YACb,OAAO,OAAO;AAAA,UAChB,CAAC;AAAA,QACH;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,WACE,QACA,kBACA,uBACA,QACM;AACN,cAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,YAAI,CAAC,QAAQ,KAAK,SAAS,UAAU;AACnC,gBAAM,IAAI,MAAM,0BAA0B,MAAM,EAAE;AAAA,QACpD;AAEA,cAAM,aAAa;AACnB,mBAAW,cAAc,KAAK,IAAI;AAClC,mBAAW,QAAQ;AACnB,mBAAW,mBAAmB;AAC9B,mBAAW,QAAQ;AAGnB,cAAM,QACJ,WAAW,oBACP,0BACA,cAAc,gBAAgB,YAAY,qBAAqB;AAErE,aAAK,KAAK;AAAA,UACR,MAAM;AAAA,UACN,GAAG,KAAK,qBAAqB,IAAI;AAAA,UACjC,cAAc,WAAW;AAAA,UACzB,MAAM,WAAW;AAAA,UACjB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,SAAS,SAAiB,eAA6B;AACrD,cAAM,OAAO,KAAK,MAAM,IAAI,aAAa;AACzC,YAAI,CAAC,MAAM;AACT,gBAAM,IAAI,MAAM,mBAAmB,aAAa,EAAE;AAAA,QACpD;AAEA,aAAK,KAAK;AAAA,UACR,MAAM;AAAA,UACN,GAAG,KAAK,qBAAqB,IAAI;AAAA,UACjC;AAAA,QACF,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,QAAQ,IAAuC;AAC7C,eAAO,KAAK,MAAM,IAAI,EAAE;AAAA,MAC1B;AAAA;AAAA;AAAA;AAAA,MAKA,sBAAsB,cAA8C;AAClE,cAAM,SAAS,KAAK,qBAAqB,IAAI,YAAY;AACzD,YAAI,CAAC,OAAQ,QAAO;AACpB,cAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,eAAO,MAAM,SAAS,WAAY,OAAsB;AAAA,MAC1D;AAAA;AAAA;AAAA;AAAA,MAKA,WAA4B;AAC1B,eAAO,KAAK,QACT,IAAI,CAAC,OAAO,KAAK,MAAM,IAAI,EAAE,CAAC,EAC9B,OAAO,CAAC,SAAgC,SAAS,MAAS;AAAA,MAC/D;AAAA;AAAA;AAAA;AAAA,MAKA,YAAY,IAA6B;AACvC,cAAM,OAAO,KAAK,MAAM,IAAI,EAAE;AAC9B,YAAI,CAAC,KAAM,QAAO,CAAC;AACnB,eAAO,KAAK,SACT,IAAI,CAAC,YAAY,KAAK,MAAM,IAAI,OAAO,CAAC,EACxC,OAAO,CAAC,UAAkC,UAAU,MAAS;AAAA,MAClE;AAAA;AAAA;AAAA;AAAA,MAKA,aAAa,IAA6B;AACxC,cAAM,OAAO,KAAK,MAAM,IAAI,EAAE;AAC9B,YAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,cAAM,YAA6B,CAAC;AACpC,YAAI,YAAY,KAAK;AACrB,eAAO,WAAW;AAChB,gBAAM,WAAW,KAAK,MAAM,IAAI,SAAS;AACzC,cAAI,UAAU;AACZ,sBAAU,QAAQ,QAAQ;AAC1B,wBAAY,SAAS;AAAA,UACvB,OAAO;AACL;AAAA,UACF;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,eAAe,IAAY,MAA2C;AACpE,cAAM,OAAO,KAAK,MAAM,IAAI,EAAE;AAC9B,YAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,cAAM,cAA+B,CAAC;AACtC,cAAM,QAAQ,CAAC,GAAG,KAAK,QAAQ;AAE/B,eAAO,MAAM,SAAS,GAAG;AACvB,gBAAM,UAAU,MAAM,IAAI;AAC1B,gBAAM,QAAQ,KAAK,MAAM,IAAI,OAAO;AACpC,cAAI,OAAO;AACT,gBAAI,CAAC,QAAQ,MAAM,SAAS,MAAM;AAChC,0BAAY,KAAK,KAAK;AAAA,YACxB;AACA,kBAAM,KAAK,GAAG,MAAM,QAAQ;AAAA,UAC9B;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,sBAA0C;AAExC,iBAAS,IAAI,KAAK,QAAQ,SAAS,GAAG,KAAK,GAAG,KAAK;AACjD,gBAAM,OAAO,KAAK,MAAM,IAAI,KAAK,QAAQ,CAAC,CAAC;AAC3C,cAAI,MAAM,SAAS,cAAc,CAAC,KAAK,aAAa;AAClD,mBAAO,KAAK;AAAA,UACd;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,eAAuB;AACrB,YAAI,QAAQ;AACZ,mBAAW,QAAQ,KAAK,MAAM,OAAO,GAAG;AACtC,cAAI,KAAK,SAAS,cAAe,KAAqB,MAAM;AAC1D,qBAAU,KAAqB;AAAA,UACjC,WAAW,KAAK,SAAS,YAAa,KAAoB,MAAM;AAC9D,qBAAU,KAAoB;AAAA,UAChC;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,eAAe,QAAwB;AACrC,cAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,YAAI,CAAC,KAAM,QAAO;AAElB,YAAI,QAAQ;AAGZ,YAAI,KAAK,SAAS,cAAe,KAAqB,MAAM;AAC1D,mBAAU,KAAqB;AAAA,QACjC,WAAW,KAAK,SAAS,YAAa,KAAoB,MAAM;AAC9D,mBAAU,KAAoB;AAAA,QAChC;AAGA,mBAAW,cAAc,KAAK,eAAe,MAAM,GAAG;AACpD,cAAI,WAAW,SAAS,cAAe,WAA2B,MAAM;AACtE,qBAAU,WAA2B;AAAA,UACvC,WAAW,WAAW,SAAS,YAAa,WAA0B,MAAM;AAC1E,qBAAU,WAA0B;AAAA,UACtC;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,iBAAoE;AAClE,YAAI,QAAQ;AACZ,YAAI,SAAS;AACb,YAAI,SAAS;AAEb,mBAAW,QAAQ,KAAK,MAAM,OAAO,GAAG;AACtC,cAAI,KAAK,SAAS,YAAY;AAC5B,kBAAM,UAAU;AAChB,gBAAI,QAAQ,OAAO;AACjB,uBAAS,QAAQ,MAAM;AACvB,wBAAU,QAAQ,MAAM;AACxB,wBAAU,QAAQ,MAAM,qBAAqB;AAAA,YAC/C;AAAA,UACF;AAAA,QACF;AAEA,eAAO,EAAE,OAAO,QAAQ,OAAO;AAAA,MACjC;AAAA;AAAA;AAAA;AAAA,MAKA,iBAAiB,QAAmE;AAClF,cAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,YAAI,CAAC,KAAM,QAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,EAAE;AAEnD,YAAI,QAAQ;AACZ,YAAI,SAAS;AACb,YAAI,SAAS;AAEb,cAAM,iBAAiB,CAAC,MAAM,GAAG,KAAK,eAAe,MAAM,CAAC;AAE5D,mBAAW,KAAK,gBAAgB;AAC9B,cAAI,EAAE,SAAS,YAAY;AACzB,kBAAM,UAAU;AAChB,gBAAI,QAAQ,OAAO;AACjB,uBAAS,QAAQ,MAAM;AACvB,wBAAU,QAAQ,MAAM;AACxB,wBAAU,QAAQ,MAAM,qBAAqB;AAAA,YAC/C;AAAA,UACF;AAAA,QACF;AAEA,eAAO,EAAE,OAAO,QAAQ,OAAO;AAAA,MACjC;AAAA;AAAA;AAAA;AAAA,MAKA,gBAAgB,QAAqC;AACnD,cAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,YAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,cAAM,QAA6B,CAAC;AACpC,cAAM,iBAAkC,KAAK,SAAS,WAAW,CAAC,IAAI,IAAI,CAAC;AAC3E,uBAAe,KAAK,GAAG,KAAK,eAAe,QAAQ,QAAQ,CAAC;AAE5D,mBAAW,KAAK,gBAAgB;AAC9B,cAAI,EAAE,SAAS,UAAU;AACvB,kBAAM,aAAa;AACnB,gBAAI,WAAW,OAAO;AACpB,oBAAM,KAAK,GAAG,WAAW,KAAK;AAAA,YAChC;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,kBAAkB,QAAyB;AACzC,cAAM,OAAO,KAAK,MAAM,IAAI,MAAM;AAClC,YAAI,CAAC,KAAM,QAAO;AAClB,YAAI,CAAC,KAAK,YAAa,QAAO;AAE9B,mBAAW,cAAc,KAAK,eAAe,MAAM,GAAG;AACpD,cAAI,CAAC,WAAW,YAAa,QAAO;AAAA,QACtC;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,eAAsD;AACpD,YAAI,WAAW;AACf,YAAI,UAAU;AAEd,mBAAW,QAAQ,KAAK,MAAM,OAAO,GAAG;AACtC,cAAI,KAAK,SAAS,WAAY;AAAA,mBACrB,KAAK,SAAS,SAAU;AAAA,QACnC;AAEA,eAAO,EAAE,UAAU,QAAQ;AAAA,MAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAuBA,GAAG,MAA0B,UAAqC;AAChE,YAAI,CAAC,KAAK,eAAe,IAAI,IAAI,GAAG;AAClC,eAAK,eAAe,IAAI,MAAM,oBAAI,IAAI,CAAC;AAAA,QACzC;AACA,cAAM,YAAY,KAAK,eAAe,IAAI,IAAI;AAC9C,kBAAU,IAAI,QAAQ;AAEtB,eAAO,MAAM;AACX,oBAAU,OAAO,QAAQ;AAAA,QAC3B;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,MAAM,UAAqC;AACzC,eAAO,KAAK,GAAG,KAAK,QAAQ;AAAA,MAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,OAAO,SAAyC;AAC9C,eAAO,CAAC,KAAK,aAAa;AAExB,iBAAO,KAAK,WAAW,SAAS,GAAG;AACjC,kBAAM,KAAK,WAAW,MAAM;AAAA,UAC9B;AAEA,cAAI,KAAK,YAAa;AAGtB,gBAAM,QAAQ,MAAM,IAAI,QAAwB,CAAC,YAAY;AAE3D,gBAAI,KAAK,WAAW,SAAS,GAAG;AAC9B,sBAAQ,KAAK,WAAW,MAAM,CAAE;AAAA,YAClC,OAAO;AACL,mBAAK,aAAa,KAAK,OAAO;AAAA,YAChC;AAAA,UACF,CAAC;AAED,gBAAM;AAAA,QACR;AAGA,eAAO,KAAK,WAAW,SAAS,GAAG;AACjC,gBAAM,KAAK,WAAW,MAAM;AAAA,QAC9B;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,WAAiB;AACf,aAAK,cAAc;AAEnB,mBAAW,UAAU,KAAK,cAAc;AAAA,QAExC;AACA,aAAK,eAAe,CAAC;AAAA,MACvB;AAAA;AAAA;AAAA;AAAA,MAKA,aAAsB;AACpB,eAAO,KAAK;AAAA,MACd;AAAA,IACF;AAAA;AAAA;;;ACzxBO,SAAS,sBACd,UACA,cACA,SACQ;AACR,QAAM,WAAW,YAAY;AAC7B,SAAO,OAAO,aAAa,aAAa,SAAS,OAAO,IAAI;AAC9D;AAKO,SAAS,qBACd,OACA,SACU;AACV,QAAM,WAAW,SAAS,gBAAgB;AAE1C,MAAI,MAAM,QAAQ,QAAQ,GAAG;AAC3B,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,aAAa,YAAY;AAClC,UAAM,SAAS,SAAS,OAAO;AAC/B,WAAO,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AAAA,EACjD;AAEA,SAAO,CAAC,QAAQ;AAClB;AAWO,SAAS,oBACd,UACA,cACA,SACQ;AACR,QAAM,WAAW,YAAY;AAE7B,MAAI,OAAO,aAAa,YAAY;AAClC,WAAO,SAAS,OAAO;AAAA,EACzB;AAGA,SAAO,SACJ,QAAQ,kBAAkB,OAAO,QAAQ,SAAS,CAAC,EACnD,QAAQ,sBAAsB,OAAO,QAAQ,aAAa,CAAC,EAC3D,QAAQ,kBAAkB,OAAO,QAAQ,SAAS,CAAC;AACxD;AAxNA,IAqHa,eASA;AA9Hb;AAAA;AAAA;AAqHO,IAAM,gBAAgB;AAAA,MAC3B,qBAAqB;AAAA,MAErB,uBAAuB;AAAA,IACzB;AAKO,IAAM,kBAQT;AAAA,MACF,iBAAiB;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,EAAE,KAAK,IAAI;AAAA,MAEX,eAAe;AAAA,MAEf,mBAAmB,CAAC,QAClB,oBAAoB,IAAI,SAAS;AAAA,MAEnC,OAAO,MAAM;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MAEA,gBAAgB;AAAA,IAClB;AAAA;AAAA;;;AChHO,SAAS,wBAAwB,SAAwC;AAC9E,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;AAAA,EACzC;AACA,SAAO;AACT;AASO,SAAS,mBAAmB,SAAiC;AAClE,MAAI,OAAO,YAAY,UAAU;AAC/B,WAAO;AAAA,EACT;AACA,SAAO,QACJ,OAAO,CAAC,SAAkC,KAAK,SAAS,MAAM,EAC9D,IAAI,CAAC,SAAS,KAAK,IAAI,EACvB,KAAK,EAAE;AACZ;AAlEA,IAoEa;AApEb;AAAA;AAAA;AAEA;AAOA;AAWA;AAgDO,IAAM,oBAAN,MAAwB;AAAA,MACZ,WAAyB,CAAC;AAAA,MACnC,cAAsB;AAAA,MACtB,YAAoB;AAAA,MACpB,YAAoB;AAAA,MACpB;AAAA,MAER,YAAY,cAAqC;AAC/C,aAAK,eAAe,gBAAgB,CAAC;AAAA,MACvC;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,aAAa,aAAqB,WAAmB,WAA0B;AAC7E,aAAK,cAAc;AACnB,aAAK,YAAY;AACjB,YAAI,WAAW;AACb,eAAK,YAAY;AAAA,QACnB;AACA,eAAO;AAAA,MACT;AAAA,MAEA,UAAU,SAAiB,UAA0C;AACnE,aAAK,SAAS,KAAK,EAAE,MAAM,UAAU,SAAS,SAAS,CAAC;AACxD,eAAO;AAAA,MACT;AAAA,MAEA,WACE,SACA,SACM;AAEN,YAAI,SAAS,aAAa;AACxB,eAAK,cAAc,QAAQ;AAAA,QAC7B;AACA,YAAI,SAAS,WAAW;AACtB,eAAK,YAAY,QAAQ;AAAA,QAC3B;AACA,YAAI,SAAS,WAAW;AACtB,eAAK,YAAY,QAAQ;AAAA,QAC3B;AAEA,cAAM,UAAU;AAAA,UACd,aAAa,KAAK;AAAA,UAClB,WAAW,KAAK;AAAA,UAChB,WAAW,KAAK;AAAA,UAChB,aAAa,QAAQ;AAAA,UACrB,aAAa,QAAQ,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,YAAY,IAAI;AAAA,QAC9D;AAEA,cAAM,QAAkB,CAAC;AAGzB,cAAM,kBAAkB;AAAA,UACtB,KAAK,aAAa;AAAA,UAClB,gBAAgB;AAAA,UAChB;AAAA,QACF;AACA,cAAM,KAAK,eAAe;AAE1B,cAAM,KAAK,KAAK,oBAAoB,OAAO,CAAC;AAC5C,cAAM,KAAK,KAAK,kBAAkB,OAAO,CAAC;AAE1C,aAAK,SAAS,KAAK,EAAE,MAAM,UAAU,SAAS,MAAM,KAAK,EAAE,EAAE,CAAC;AAC9D,eAAO;AAAA,MACT;AAAA,MAEQ,oBAAoB,SAAmC;AAC7D,cAAM,QAAkB,CAAC;AACzB,cAAM,KAAK,uBAAuB;AAClC,cAAM,KAAK,uBAAuB;AAElC,mBAAW,UAAU,SAAS;AAC5B,gBAAM,aAAa,OAAO,QAAQ,OAAO,YAAY;AACrD,gBAAM,cAAc,OAAO,eAAe;AAAA,YACxC,WAAW,KAAK;AAAA,YAChB,aAAa,KAAK;AAAA,YAClB,WAAW,KAAK;AAAA,UAClB,CAAC;AAGD,gBAAM,eAAe;AACrB,gBAAM,cAAc,YAAY,QAAQ,YAAY;AAEpD,gBAAM,eACJ,gBAAgB,KAAK,YAAY,UAAU,GAAG,WAAW,IAAI,aAC7D,KAAK;AACP,gBAAM,SACJ,gBAAgB,KAAK,YAAY,UAAU,cAAc,aAAa,MAAM,EAAE,KAAK,IAAI;AAEzF,gBAAM,KAAK;AAAA,UAAa,UAAU,EAAE;AACpC,gBAAM,KAAK;AAAA,EAAK,WAAW,EAAE;AAC7B,cAAI,QAAQ;AACV,kBAAM,KAAK;AAAA;AAAA;AAAA,EAA4B,MAAM,EAAE;AAAA,UACjD;AACA,gBAAM,KAAK,SAAS;AAAA,QACtB;AAEA,eAAO,MAAM,KAAK,EAAE;AAAA,MACtB;AAAA,MAEQ,kBAAkB,SAMf;AACT,cAAM,QAAkB,CAAC;AAGzB,cAAM,oBAAoB;AAAA,UACxB,KAAK,aAAa;AAAA,UAClB,gBAAgB;AAAA,UAChB;AAAA,QACF;AAEA,cAAM,KAAK,2BAA2B;AACtC,cAAM,KAAK,2BAA2B;AAGtC,cAAM,gBAAgB;AAAA,UACpB,KAAK,aAAa;AAAA,UAClB,gBAAgB;AAAA,UAChB;AAAA,QACF;AACA,cAAM,KAAK;AAAA,YAAe,aAAa;AAAA,CAAI;AAG3C,cAAM,KAAK,WAAW;AACtB,cAAM,KAAK;AAAA,qBAAwB,KAAK,WAAW,aAAa;AAChE,cAAM,KAAK;AAAA,gBAAmB,KAAK,WAAW,mBAAmB;AACjE,cAAM,KAAK;AAAA,0BAA6B,KAAK,WAAW,6BAA6B;AACrF,cAAM,KAAK;AAAA,OAAU,iBAAiB,EAAE;AACxC,cAAM,KAAK;AAAA,mBAAsB,KAAK,SAAS,EAAE;AAEjD,cAAM,KAAK,KAAK,qBAAqB,OAAO,CAAC;AAC7C,cAAM,KAAK,KAAK,kBAAkB,OAAO,CAAC;AAE1C,cAAM,KAAK,IAAI;AAEf,eAAO,MAAM,KAAK,EAAE;AAAA,MACtB;AAAA,MAEQ,qBAAqB,SAMlB;AAET,YAAI,KAAK,aAAa,gBAAgB;AACpC,iBAAO,KAAK,aAAa,eAAe,OAAO;AAAA,QACjD;AAEA,cAAM,QAAkB,CAAC;AAGzB,cAAM,gBAAgB,GAAG,KAAK,WAAW;AAAA,EAC3C,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAEZ,cAAM,KAAK;AAAA;AAAA;AAAA;AAAA,EAAmC,aAAa,EAAE;AAG7D,cAAM,kBAAkB,GAAG,KAAK,WAAW;AAAA,EAC7C,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA,EACd,KAAK,WAAW;AAAA,EAChB,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA,EAId,KAAK,SAAS;AAEZ,cAAM,KAAK;AAAA;AAAA;AAAA;AAAA,EAAsC,eAAe,EAAE;AAGlE,cAAM,oBAAoB,GAAG,KAAK,WAAW;AAAA,EAC/C,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA,EACd,KAAK,WAAW;AAAA,EAChB,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA,EACd,KAAK,WAAW;AAAA,EAChB,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAEZ,cAAM,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAIb,iBAAiB,EAAE;AAGjB,cAAM,KAAK;AAAA;AAAA;AAAA,oBAGK,KAAK,SAAS;AAAA;AAAA,EAEhC,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,+BAYe,KAAK,SAAS;AAAA;AAAA,6BAEhB,KAAK,SAAS,OAAO,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAK9D,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,EAKd,KAAK,SAAS;AAAA;AAAA,EAEd,KAAK,SAAS;AAAA;AAAA,2CAE2B;AAEvC,eAAO,MAAM,KAAK,EAAE;AAAA,MACtB;AAAA,MAEQ,kBAAkB,SAMf;AACT,cAAM,QAAkB,CAAC;AACzB,cAAM,KAAK,YAAY;AAGvB,cAAM,QAAQ,qBAAqB,KAAK,aAAa,OAAO,OAAO;AAEnE,mBAAW,QAAQ,OAAO;AACxB,gBAAM,KAAK;AAAA,MAAS,IAAI,EAAE;AAAA,QAC5B;AAEA,eAAO,MAAM,KAAK,EAAE;AAAA,MACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAqBA,QAAQ,SAAyB,UAA0C;AACzE,aAAK,SAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,SAAS,CAAC;AACtD,eAAO;AAAA,MACT;AAAA,MAEA,aAAa,SAAiB,UAA0C;AACtE,aAAK,SAAS,KAAK,EAAE,MAAM,aAAa,SAAS,SAAS,CAAC;AAC3D,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAkBA,iBACE,aACA,WACA,UACM;AACN,cAAM,cACJ,OAAO,cAAc,WAAW,OAAO,KAAK,WAAW,QAAQ,IAAI;AACrE,cAAM,eAAe,YAAY,oBAAoB,WAAW;AAEhE,YAAI,CAAC,cAAc;AACjB,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,cAAM,UAAyB;AAAA,UAC7B,KAAK,WAAW;AAAA,UAChB;AAAA,YACE,MAAM;AAAA,YACN,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,WAAW;AAAA,cACX,MAAM,SAAS,WAAW;AAAA,YAC5B;AAAA,UACF;AAAA,QACF;AAEA,aAAK,SAAS,KAAK,EAAE,MAAM,QAAQ,QAAQ,CAAC;AAC5C,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBA,oBAAoB,aAAqB,UAAwB;AAC/D,cAAM,UAAyB,CAAC,KAAK,WAAW,GAAG,aAAa,QAAQ,CAAC;AACzE,aAAK,SAAS,KAAK,EAAE,MAAM,QAAQ,QAAQ,CAAC;AAC5C,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAkBA,iBACE,aACA,WACA,UACM;AACN,cAAM,cACJ,OAAO,cAAc,WAAW,OAAO,KAAK,WAAW,QAAQ,IAAI;AAErE,cAAM,UAAyB,CAAC,KAAK,WAAW,GAAG,gBAAgB,aAAa,QAAQ,CAAC;AACzF,aAAK,SAAS,KAAK,EAAE,MAAM,QAAQ,QAAQ,CAAC;AAC5C,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAiBA,kBAAkB,OAA4B;AAC5C,aAAK,SAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,MAAM,CAAC;AACnD,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAeA,oBACE,QACA,YACA,QACA,cACA,OACA,UACA;AACA,cAAM,WAAW,KAAK,sBAAsB,YAAY,EAAE;AAG1D,aAAK,SAAS,KAAK;AAAA,UACjB,MAAM;AAAA,UACN,SAAS,GAAG,KAAK,WAAW,GAAG,MAAM,IAAI,YAAY;AAAA,EAAK,QAAQ;AAAA,EAAK,KAAK,SAAS;AAAA,QACvF,CAAC;AAGD,YAAI,SAAS,MAAM,SAAS,KAAK,YAAY,SAAS,SAAS,GAAG;AAEhE,gBAAM,SAAS,MAAM,IAAI,CAAC,GAAG,MAAM,WAAW,SAAS,CAAC,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,KAAK,IAAI;AACnF,gBAAM,cAAc,WAAW,YAAY,MAAM,MAAM;AAAA,EAAK,MAAM;AAGlE,gBAAM,QAAuB,CAAC,KAAK,WAAW,CAAC;AAC/C,qBAAW,QAAQ,OAAO;AAExB,gBAAI,KAAK,SAAS,SAAS;AACzB,oBAAM,KAAK,gBAAgB,KAAK,MAAM,KAAK,QAAyB,CAAC;AAAA,YACvE,WAAW,KAAK,SAAS,SAAS;AAChC,oBAAM,KAAK,gBAAgB,KAAK,MAAM,KAAK,QAAyB,CAAC;AAAA,YACvE;AAAA,UAGF;AACA,eAAK,SAAS,KAAK,EAAE,MAAM,QAAQ,SAAS,MAAM,CAAC;AAAA,QACrD,OAAO;AAEL,eAAK,SAAS,KAAK;AAAA,YACjB,MAAM;AAAA,YACN,SAAS,WAAW,YAAY,MAAM,MAAM;AAAA,UAC9C,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,sBAAsB,QAAiC,QAAwB;AACrF,cAAM,QAAkB,CAAC;AAEzB,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,gBAAM,WAAW,SAAS,GAAG,MAAM,IAAI,GAAG,KAAK;AAE/C,cAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,kBAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,oBAAM,WAAW,GAAG,QAAQ,IAAI,KAAK;AACrC,kBAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,sBAAM,KAAK,KAAK,sBAAsB,MAAiC,QAAQ,CAAC;AAAA,cAClF,OAAO;AACL,sBAAM,KAAK,GAAG,KAAK,SAAS,GAAG,QAAQ,EAAE;AACzC,sBAAM,KAAK,OAAO,IAAI,CAAC;AAAA,cACzB;AAAA,YACF,CAAC;AAAA,UACH,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,kBAAM,KAAK,KAAK,sBAAsB,OAAkC,QAAQ,CAAC;AAAA,UACnF,OAAO;AACL,kBAAM,KAAK,GAAG,KAAK,SAAS,GAAG,QAAQ,EAAE;AACzC,kBAAM,KAAK,OAAO,KAAK,CAAC;AAAA,UAC1B;AAAA,QACF;AAEA,eAAO,MAAM,KAAK,IAAI;AAAA,MACxB;AAAA,MAEA,QAAsB;AACpB,eAAO,CAAC,GAAG,KAAK,QAAQ;AAAA,MAC1B;AAAA,IACF;AAAA;AAAA;;;AC/hBA,SAAS,kBAA0B;AACjC,aAAO,2BAAK,wBAAQ,GAAG,WAAW,KAAK;AACzC;AA1CA,IA2BA,oBACA,iBACA,gBACA,kBAiBM,mBAuCO;AAtFb;AAAA;AAAA;AA2BA,yBAA4B;AAC5B,sBAAqC;AACrC,qBAAwB;AACxB,uBAAqB;AAiBrB,IAAM,oBAA4C;AAAA;AAAA,MAEhD,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa;AAAA,MACb,cAAc;AAAA,MACd,iBAAiB;AAAA,MACjB,aAAa;AAAA,MACb,cAAc;AAAA;AAAA,MAEd,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa;AAAA;AAAA,MAEb,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa;AAAA,MACb,mBAAmB;AAAA,MACnB,mBAAmB;AAAA;AAAA,MAEnB,mBAAmB;AAAA,MACnB,oBAAoB;AAAA,MACpB,cAAc;AAAA,MACd,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,mBAAmB;AAAA,IACrB;AASO,IAAM,aAAN,MAAiB;AAAA,MACL,QAAQ,oBAAI,IAAyB;AAAA,MACrC;AAAA,MACT,UAAU;AAAA,MACV,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQtB,YAAY,WAAoB;AAC9B,cAAM,KAAK,iBAAa,gCAAY,CAAC,EAAE,SAAS,KAAK;AACrD,aAAK,gBAAY,uBAAK,gBAAgB,GAAG,SAAS,EAAE,EAAE;AAAA,MACxD;AAAA;AAAA;AAAA;AAAA,MAKA,eAAuB;AACrB,eAAO,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAc,YAA2B;AACvC,YAAI,KAAK,YAAa;AAEtB,YAAI;AACF,oBAAM,uBAAM,KAAK,WAAW,EAAE,WAAW,KAAK,CAAC;AAC/C,eAAK,cAAc;AAAA,QACrB,SAAS,OAAO;AACd,gBAAM,IAAI;AAAA,YACR,0CAA0C,KAAK,SAAS,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,UACrH;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,aAAqB;AAC3B,cAAM,QAAQ;AACd,YAAI,KAAK;AACT,cAAM,YAAQ,gCAAY,CAAC;AAC3B,iBAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,gBAAM,MAAM,MAAM,CAAC,IAAI,MAAM,MAAM;AAAA,QACrC;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,aAAa,UAA0B;AAC7C,eAAO,kBAAkB,QAAQ,KAAK;AAAA,MACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA,MAAM,MAAM,OAA0B,YAA0C;AAC9E,cAAM,KAAK,UAAU;AAErB,cAAM,KAAK,KAAK,WAAW;AAC3B,cAAM,MAAM,KAAK,aAAa,MAAM,QAAQ;AAE5C,cAAM,WACJ,MAAM,YAAY,GAAG,UAAU,IAAI,OAAO,EAAE,KAAK,OAAO,EAAE,SAAS,GAAG,GAAG,CAAC,GAAG,GAAG;AAClF,cAAM,eAAW,uBAAK,KAAK,WAAW,QAAQ;AAG9C,cAAM,SAAS,OAAO,KAAK,MAAM,MAAM,QAAQ;AAE/C,YAAI;AACF,oBAAM,2BAAU,UAAU,MAAM;AAAA,QAClC,SAAS,OAAO;AACd,gBAAM,IAAI;AAAA,YACR,0CAA0C,QAAQ,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,UAC/G;AAAA,QACF;AAEA,cAAM,SAAsB;AAAA,UAC1B;AAAA,UACA,MAAM,MAAM;AAAA,UACZ,MAAM;AAAA,UACN,UAAU,MAAM;AAAA,UAChB,WAAW,OAAO;AAAA,UAClB,aAAa,MAAM;AAAA,UACnB,UAAU,MAAM;AAAA,UAChB;AAAA,UACA,WAAW,oBAAI,KAAK;AAAA,QACtB;AAEA,aAAK,MAAM,IAAI,IAAI,MAAM;AACzB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,IAAI,IAAqC;AACvC,eAAO,KAAK,MAAM,IAAI,EAAE;AAAA,MAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,QAAQ,IAAgC;AACtC,eAAO,KAAK,MAAM,IAAI,EAAE,GAAG;AAAA,MAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,KAAK,MAAiC;AACpC,cAAM,MAAM,MAAM,KAAK,KAAK,MAAM,OAAO,CAAC;AAC1C,YAAI,MAAM;AACR,iBAAO,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI;AAAA,QAChD;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,IAAI,OAAe;AACjB,eAAO,KAAK,MAAM;AAAA,MACpB;AAAA;AAAA;AAAA;AAAA,MAKA,IAAI,IAAqB;AACvB,eAAO,KAAK,MAAM,IAAI,EAAE;AAAA,MAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,QAAc;AACZ,aAAK,MAAM,MAAM;AACjB,aAAK,UAAU;AAAA,MACjB;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAM,UAAyB;AAC7B,YAAI,KAAK,aAAa;AACpB,cAAI;AACF,sBAAM,oBAAG,KAAK,WAAW,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,UAC3D,QAAQ;AAAA,UAER;AACA,eAAK,cAAc;AAAA,QACrB;AACA,aAAK,MAAM;AAAA,MACb;AAAA,IACF;AAAA;AAAA;;;AC1QA,IA0Ba,sBAoCA,6BAuCA,kBAyCA;AA9Ib;AAAA;AAAA;AA0BO,IAAM,uBAAN,cAAmC,MAAM;AAAA,MAC9C,YAAY,SAAkB;AAC5B,cAAM,WAAW,iCAAiC;AAClD,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AA+BO,IAAM,8BAAN,cAA0C,MAAM;AAAA,MACrC;AAAA,MAEhB,YAAY,UAAkB;AAC5B,cAAM,yBAAyB,QAAQ,EAAE;AACzC,aAAK,OAAO;AACZ,aAAK,WAAW;AAAA,MAClB;AAAA,IACF;AA+BO,IAAM,mBAAN,cAA+B,MAAM;AAAA,MAC1B;AAAA,MACA;AAAA,MAEhB,YAAY,YAAoB,WAAmB;AACjD,cAAM,WAAW,UAAU,mCAAmC,SAAS,IAAI;AAC3E,aAAK,OAAO;AACZ,aAAK,aAAa;AAClB,aAAK,YAAY;AAAA,MACnB;AAAA,IACF;AA+BO,IAAM,iBAAN,cAA6B,MAAM;AAAA,MACxC,YAAY,SAAkB;AAC5B,cAAM,WAAW,8BAA8B;AAC/C,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAAA;AAAA;;;ACrIA,SAAS,cAAc,OAAoC;AACzD,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,KAAK,EAAE,YAAY;AAE5C,MAAI,eAAe,IAAI;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,OAAO,UAAU;AACtC,MAAI,OAAO,SAAS,YAAY,GAAG;AACjC,WAAO,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,MAAM,YAAY,CAAC,CAAC;AAAA,EAC1D;AAEA,SAAO,iBAAiB,UAAU;AACpC;AAkCA,SAAS,gBAAgB,OAAqC;AAC5D,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,aAAa,MAAM,KAAK,EAAE,YAAY;AAC5C,MAAI,eAAe,UAAU,eAAe,IAAK,QAAO;AACxD,MAAI,eAAe,WAAW,eAAe,IAAK,QAAO;AACzD,SAAO;AACT;AAiBO,SAAS,UAAU,KAAqB;AAE7C,SAAO,IAAI,QAAQ,mBAAmB,EAAE;AAC1C;AAmCO,SAAS,aAAa,UAAyB,CAAC,GAAoB;AACzE,QAAM,cAAc,cAAc,QAAQ,IAAI,gBAAgB;AAC9D,QAAM,aAAa,QAAQ,IAAI,iBAAiB,KAAK,KAAK;AAC1D,QAAM,cAAc,gBAAgB,QAAQ,IAAI,gBAAgB;AAEhE,QAAM,WAAW,QAAQ,YAAY,eAAe;AACpD,QAAM,cAAc,QAAQ,QAAQ;AACpC,QAAM,OAAO,QAAQ,QAAQ;AAE7B,QAAM,WAAW,QAAQ,YAAY,eAAe;AAGpD,MAAI,eAAe,CAAC,sBAAsB,sBAAsB,aAAa;AAC3E,QAAI;AAEF,UAAI,qBAAqB;AACvB,4BAAoB,IAAI;AACxB,8BAAsB;AAAA,MACxB;AAEA,wCAAU,2BAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAGlD,YAAM,QAAQ,WAAW,MAAM;AAC/B,gCAAsB,kCAAkB,YAAY,EAAE,MAAM,CAAC;AAC7D,0BAAoB;AACpB,2BAAqB;AACrB,wBAAkB;AAClB,2BAAqB;AAGrB,0BAAoB,GAAG,SAAS,CAAC,UAAU;AACzC;AACA,YAAI,CAAC,oBAAoB;AACvB,kBAAQ,MAAM,kCAAkC,MAAM,OAAO,EAAE;AAC/D,+BAAqB;AAAA,QACvB;AACA,YAAI,mBAAmB,iCAAiC;AACtD,kBAAQ;AAAA,YACN,sCAAsC,eAAe;AAAA,UACvD;AACA,+BAAqB,IAAI;AACzB,gCAAsB;AAAA,QACxB;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,cAAQ,MAAM,gDAAgD,KAAK;AAAA,IACrE;AAAA,EACF;AAIA,QAAM,iBAAiB,QAAQ,mBAAmB;AAElD,QAAM,SAAS,IAAI,oBAAgB;AAAA,IACjC;AAAA,IACA;AAAA,IACA,MAAM,iBAAiB,WAAW;AAAA;AAAA,IAElC,8BAA8B,kBAAkB,gBAAgB;AAAA,IAChE,mBAAmB;AAAA;AAAA,IAEnB,WAAW,iBACP;AAAA,MACE,oBAAoB,CAClB,eACA,SACA,eACG;AAEH,YAAI,CAAC,oBAAqB;AAI1B,cAAM,OAAO,UAAU,aAAa;AACpC,cAAM,OAAO,QAAQ;AAAA,UAAI,CAAC,QACxB,OAAO,QAAQ,WAAW,UAAU,GAAG,IAAI,KAAK,UAAU,GAAG;AAAA,QAC/D;AACA,cAAM,OAAO,GAAG,IAAI,GAAG,KAAK,KAAK,GAAG,CAAC;AAAA;AAGrC,4BAAoB,MAAM,IAAI;AAAA,MAChC;AAAA,IACF,IACA;AAAA,EACN,CAAC;AAED,SAAO;AACT;AAtNA,oBACAC,mBACA,cAEM,kBAsEF,mBACA,qBACA,oBACA,iBACA,oBACE,iCAGA,cA0IO;AA5Nb;AAAA;AAAA;AAAA,qBAA+D;AAC/D,IAAAA,oBAAwB;AACxB,mBAAqC;AAErC,IAAM,mBAA2C;AAAA,MAC/C,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAgEA,IAAI,qBAAqB;AACzB,IAAI,kBAAkB;AACtB,IAAI,qBAAqB;AACzB,IAAM,kCAAkC;AAGxC,IAAM,eACJ;AAyIK,IAAM,gBAAgB,aAAa;AAAA;AAAA;;;AC9KnC,SAAS,mBACd,QACA,SACyB;AACzB,QAAM,aAAe,gBAAa,QAAQ,WAAW,EAAE,QAAQ,UAAU,CAAC;AAG1E,QAAM,aAAa,0BAA0B,QAAQ,UAAU;AAE/D,MAAI,WAAW,SAAS,GAAG;AACzB,kBAAc;AAAA,MACZ,mCAAmC,WAAW,MAAM;AAAA,IAEtD;AAGA,WAAO,kBAAkB,QAAQ,UAAU;AAAA,EAC7C;AAEA,SAAO;AACT;AAMA,SAAS,0BACP,QACA,YACU;AACV,QAAM,aAAuB,CAAC;AAE9B,WAAS,YAAY,WAAuB,MAAe,MAAoB;AAC7E,QAAI,CAAC,aAAa,OAAO,cAAc,SAAU;AAEjD,UAAM,MAAM,UAAU;AACtB,UAAM,UAAU;AAGhB,QAAI,KAAK,eAAe,CAAC,SAAS,aAAa;AAC7C,iBAAW,KAAK,QAAQ,MAAM;AAAA,IAChC;AAGA,QAAI,KAAK,aAAa,eAAe,KAAK,OAAO;AAC/C,YAAM,QACJ,OAAO,IAAI,UAAU,aAChB,IAAI,MAA2C,IAChD,IAAI;AACV,iBAAW,CAAC,KAAK,WAAW,KAAK,OAAO,QAAQ,KAAmC,GAAG;AACpF,cAAM,aAAa,SAAS;AAC5B,cAAM,WAAW,aAAa,GAAG;AACjC,oBAAY,aAAa,UAAU,OAAO,GAAG,IAAI,IAAI,GAAG,KAAK,GAAG;AAAA,MAClE;AAAA,IACF;AAGA,QAAI,KAAK,aAAa,cAAc,KAAK,MAAM;AAC7C,kBAAY,IAAI,MAAoB,SAAS,OAAO,OAAO,GAAG,IAAI,OAAO,IAAI;AAAA,IAC/E;AAGA,SAAK,KAAK,aAAa,iBAAiB,KAAK,aAAa,kBAAkB,KAAK,WAAW;AAC1F,kBAAY,IAAI,WAAyB,MAAM,IAAI;AAAA,IACrD;AAGA,QAAI,KAAK,aAAa,gBAAgB,KAAK,WAAW;AACpD,kBAAY,IAAI,WAAyB,MAAM,IAAI;AAAA,IACrD;AAAA,EACF;AAEA,cAAY,QAAQ,YAAY,EAAE;AAClC,SAAO;AACT;AAMA,SAAS,kBACP,QACA,YACyB;AACzB,WAAS,MAAM,WAAuB,MAAwB;AAC5D,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAE9C,UAAM,MAAM,UAAU;AACtB,UAAM,UAAU;AAChB,UAAM,SAAkC,EAAE,GAAG,QAAQ;AAGrD,QAAI,KAAK,eAAe,CAAC,QAAQ,aAAa;AAC5C,aAAO,cAAc,IAAI;AAAA,IAC3B;AAGA,QAAI,KAAK,aAAa,eAAe,KAAK,SAAS,QAAQ,YAAY;AACrE,YAAM,QACJ,OAAO,IAAI,UAAU,aAChB,IAAI,MAA2C,IAChD,IAAI;AACV,YAAM,aAAa,QAAQ;AAC3B,aAAO,aAAa,EAAE,GAAG,WAAW;AACpC,iBAAW,CAAC,KAAK,WAAW,KAAK,OAAO,QAAQ,KAAmC,GAAG;AACpF,YAAI,WAAW,GAAG,GAAG;AACnB,UAAC,OAAO,WAAuC,GAAG,IAAI,MAAM,aAAa,WAAW,GAAG,CAAC;AAAA,QAC1F;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,aAAa,cAAc,KAAK,QAAQ,QAAQ,OAAO;AAC9D,aAAO,QAAQ,MAAM,IAAI,MAAoB,QAAQ,KAAK;AAAA,IAC5D;AAGA,SAAK,KAAK,aAAa,iBAAiB,KAAK,aAAa,kBAAkB,KAAK,WAAW;AAC1F,aAAO,MAAM,IAAI,WAAyB,IAAI;AAAA,IAChD;AAGA,QAAI,KAAK,aAAa,gBAAgB,KAAK,WAAW;AACpD,aAAO,MAAM,IAAI,WAAyB,IAAI;AAAA,IAChD;AAEA,WAAO;AAAA,EACT;AAEA,SAAO,MAAM,QAAQ,UAAU;AACjC;AAhLA,IAkBAC;AAlBA;AAAA;AAAA;AAkBA,IAAAA,KAAmB;AACnB;AAAA;AAAA;;;ACHA,SAAS,4BACP,QACA,SAAiB,IACjB,YAAoB,mBACZ;AACR,QAAM,QAAkB,CAAC;AAEzB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAM,WAAW,SAAS,GAAG,MAAM,IAAI,GAAG,KAAK;AAE/C,QAAI,MAAM,QAAQ,KAAK,GAAG;AAExB,YAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,cAAM,WAAW,GAAG,QAAQ,IAAI,KAAK;AACrC,YAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAE7C,gBAAM,KAAK,4BAA4B,MAAiC,UAAU,SAAS,CAAC;AAAA,QAC9F,OAAO;AACL,gBAAM,KAAK,GAAG,SAAS,GAAG,QAAQ,EAAE;AACpC,gBAAM,KAAK,OAAO,IAAI,CAAC;AAAA,QACzB;AAAA,MACF,CAAC;AAAA,IACH,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AAEtD,YAAM,KAAK,4BAA4B,OAAkC,UAAU,SAAS,CAAC;AAAA,IAC/F,OAAO;AAEL,YAAM,KAAK,GAAG,SAAS,GAAG,QAAQ,EAAE;AACpC,YAAM,KAAK,OAAO,KAAK,CAAC;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAMA,SAAS,gBACP,KACA,SACA,YACA,SAAS,IACD;AACR,QAAM,OAAO,QAAQ;AACrB,QAAM,cAAc,QAAQ;AAC5B,QAAM,aAAa,QAAQ;AAE3B,MAAI,OAAO,GAAG,MAAM,KAAK,GAAG;AAG5B,MAAI,SAAS,SAAS;AACpB,UAAM,QAAQ,QAAQ;AACtB,UAAM,WAAW,OAAO,QAAQ;AAChC,YAAQ,cAAc,QAAQ;AAAA,EAChC,WAAW,SAAS,YAAY,QAAQ,YAAY;AAClD,YAAQ;AAAA,EACV,OAAO;AACL,YAAQ,KAAK,IAAI;AAAA,EACnB;AAGA,MAAI,cAAc,WAAW,IAAI;AAC/B,YAAQ;AAAA,EACV;AAGA,MAAI,aAAa;AACf,YAAQ,KAAK,WAAW;AAAA,EAC1B;AAGA,MAAI,YAAY;AACd,YAAQ,cAAc,WAAW,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC;AAAA,EAClE;AAEA,SAAO;AACT;AAOA,SAAS,wBACP,QACA,SAAS,IACT,SAAS,MACD;AACR,QAAM,QAAkB,CAAC;AACzB,QAAM,aAAc,OAAO,cAAc,CAAC;AAC1C,QAAM,WAAY,OAAO,YAAY,CAAC;AAGtC,MAAI,UAAU,WAAW,IAAI;AAC3B,UAAM,gBAAqC,CAAC;AAC5C,UAAM,gBAAqC,CAAC;AAE5C,eAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,UAAU,GAAG;AACpD,UAAI,SAAS,SAAS,GAAG,GAAG;AAC1B,sBAAc,KAAK,CAAC,KAAK,IAAI,CAAC;AAAA,MAChC,OAAO;AACL,sBAAc,KAAK,CAAC,KAAK,IAAI,CAAC;AAAA,MAChC;AAAA,IACF;AAEA,UAAM,WAAW,cAAc;AAC/B,UAAM,WAAW,cAAc;AAG/B,QAAI,WAAW,KAAK,WAAW,GAAG;AAChC,YAAM,QAAkB,CAAC;AACzB,UAAI,WAAW,EAAG,OAAM,KAAK,GAAG,QAAQ,WAAW;AACnD,UAAI,WAAW,EAAG,OAAM,KAAK,GAAG,QAAQ,WAAW;AACnD,YAAM,KAAK,MAAM,KAAK,IAAI,CAAC;AAC3B,YAAM,KAAK,EAAE;AAAA,IACf;AAGA,QAAI,WAAW,GAAG;AAChB,YAAM,KAAK,sBAAsB;AACjC,iBAAW,CAAC,KAAK,IAAI,KAAK,eAAe;AACvC,cAAM,KAAK,gBAAgB,KAAK,MAAiC,MAAM,EAAE,CAAC;AAE1E,cAAM,UAAU;AAChB,YAAI,QAAQ,SAAS,YAAY,QAAQ,YAAY;AACnD,gBAAM,KAAK,wBAAwB,SAAS,MAAM,KAAK,CAAC;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AAGA,QAAI,WAAW,GAAG;AAChB,UAAI,WAAW,EAAG,OAAM,KAAK,EAAE;AAC/B,YAAM,KAAK,sBAAsB;AACjC,iBAAW,CAAC,KAAK,IAAI,KAAK,eAAe;AACvC,cAAM,KAAK,gBAAgB,KAAK,MAAiC,OAAO,EAAE,CAAC;AAE3E,cAAM,UAAU;AAChB,YAAI,QAAQ,SAAS,YAAY,QAAQ,YAAY;AACnD,gBAAM,KAAK,wBAAwB,SAAS,MAAM,KAAK,CAAC;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AAEA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAGA,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,UAAU,GAAG;AACpD,UAAM,aAAa,SAAS,SAAS,GAAG;AACxC,UAAM,KAAK,gBAAgB,KAAK,MAAiC,YAAY,MAAM,CAAC;AAEpF,UAAM,UAAU;AAChB,QAAI,QAAQ,SAAS,YAAY,QAAQ,YAAY;AACnD,YAAM,KAAK,wBAAwB,SAAS,SAAS,MAAM,KAAK,CAAC;AAAA,IACnE;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAjLA,IA0LsB;AA1LtB;AAAA;AAAA;AAEA;AACA;AACA;AACA;AAqLO,IAAe,iBAAf,MAA8B;AAAA;AAAA;AAAA;AAAA;AAAA,MAKnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAuEA,eAAe,KAA8B;AAC3C,YAAI,KAAK,QAAQ,SAAS;AACxB,gBAAM,IAAI,eAAe;AAAA,QAC3B;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAmCA,QAAQ,KAAmC,SAA2C;AACpF,YAAI,CAAC,KAAK,OAAQ;AAElB,cAAM,cAAc,MAAM;AACxB,cAAI;AACF,kBAAM,SAAS,QAAQ;AACvB,gBAAI,UAAU,OAAO,WAAW,YAAY,WAAW,QAAQ;AAC7D,cAAC,OAAyB,MAAM,MAAM;AAAA,cAAC,CAAC;AAAA,YAC1C;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF;AAEA,YAAI,IAAI,OAAO,SAAS;AAEtB,sBAAY;AACZ;AAAA,QACF;AAEA,YAAI,OAAO,iBAAiB,SAAS,aAAa,EAAE,MAAM,KAAK,CAAC;AAAA,MAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA4BA,4BAA4B,KAAyC;AACnE,cAAM,aAAa,IAAI,gBAAgB;AAEvC,YAAI,KAAK,QAAQ;AACf,cAAI,IAAI,OAAO,SAAS;AACtB,uBAAW,MAAM,IAAI,OAAO,MAAM;AAAA,UACpC,OAAO;AACL,gBAAI,OAAO;AAAA,cACT;AAAA,cACA,MAAM;AACJ,2BAAW,MAAM,IAAI,OAAO,MAAM;AAAA,cACpC;AAAA,cACA,EAAE,MAAM,KAAK;AAAA,YACf;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,IAAI,cAAsB;AACxB,eAAO,KAAK,eAAe;AAAA,MAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,eACE,oBACQ;AAER,cAAM,UACJ,OAAO,uBAAuB,WAC1B,EAAE,WAAW,mBAAmB,IAChC;AACN,cAAM,QAAkB,CAAC;AAGzB,cAAM,KAAK,KAAK,WAAW;AAE3B,YAAI,KAAK,iBAAiB;AAExB,gBAAM,aAAa,KAAK,QAAQ,KAAK,YAAY;AACjD,+BAAqB,KAAK,iBAAiB,UAAU;AAErD,gBAAM,aAAa,mBAAmB,KAAK,iBAAiB;AAAA,YAC1D,QAAQ;AAAA,UACV,CAAC;AAGD,gBAAM,KAAK,iBAAiB;AAC5B,gBAAM,KAAK,wBAAwB,UAAU,CAAC;AAAA,QAChD;AAGA,YAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;AAC7C,gBAAM,KAAK,eAAe;AAG1B,gBAAM,qBAAqB,SAAS,aAAa;AACjD,gBAAM,uBAAuB,SAAS,eAAe;AACrD,gBAAM,qBAAqB,SAAS,aAAa;AACjD,gBAAM,aAAa,KAAK,QAAQ,KAAK,YAAY;AAEjD,eAAK,SAAS,QAAQ,CAAC,SAAS,UAAU;AAExC,gBAAI,QAAQ,GAAG;AACb,oBAAM,KAAK,EAAE;AACb,oBAAM,KAAK,KAAK;AAChB,oBAAM,KAAK,EAAE;AAAA,YACf;AAGA,gBAAI,QAAQ,SAAS;AACnB,oBAAM,KAAK,KAAK,QAAQ,OAAO,EAAE;AAAA,YACnC;AAGA,kBAAM,KAAK,GAAG,oBAAoB,GAAG,UAAU,EAAE;AAGjD,kBAAM;AAAA,cACJ,4BAA4B,QAAQ,QAAmC,IAAI,kBAAkB;AAAA,YAC/F;AAGA,kBAAM,KAAK,kBAAkB;AAG7B,gBAAI,QAAQ,WAAW,QAAW;AAChC,oBAAM,KAAK,EAAE;AACb,oBAAM,KAAK,kBAAkB;AAC7B,oBAAM,KAAK,QAAQ,MAAM;AAAA,YAC3B;AAAA,UACF,CAAC;AAAA,QACH;AAEA,eAAO,MAAM,KAAK,IAAI;AAAA,MACxB;AAAA,IACF;AAAA;AAAA;;;AC7WO,SAAS,aACd,QACgB;AAAA,EAChB,MAAM,sBAAsB,eAAe;AAAA,IACzC,OAAO,OAAO;AAAA,IACd,cAAc,OAAO;AAAA,IACrB,kBAAkB,OAAO;AAAA,IACzB,YAAY,OAAO;AAAA,IACnB,WAAW,OAAO;AAAA,IAElB,QACE,QACA,KACoD;AAEpD,aAAO,OAAO,QAAQ,QAAgC,GAAG;AAAA,IAC3D;AAAA,EACF;AAEA,SAAO,IAAI,cAAc;AAC3B;AA9IA;AAAA;AAAA;AAwBA;AAAA;AAAA;;;ACOA,SAAS,aAAa,OAAiB,SAAkC;AACvE,QAAM,QAAQ,IAAI,OAAO,QAAQ,KAAK;AAEtC,MAAI,CAAC,QAAQ,SAAS;AAEpB,WAAO,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,KAAK,IAAI,CAAC;AAAA,EACjD;AAGA,QAAM,eAAe,oBAAI,IAAY;AAGrC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI,MAAM,KAAK,MAAM,CAAC,CAAC,GAAG;AAExB,YAAM,QAAQ,KAAK,IAAI,GAAG,IAAI,QAAQ,MAAM;AAC5C,YAAM,MAAM,KAAK,IAAI,MAAM,SAAS,GAAG,IAAI,QAAQ,KAAK;AACxD,eAAS,IAAI,OAAO,KAAK,KAAK,KAAK;AACjC,qBAAa,IAAI,CAAC;AAAA,MACpB;AAAA,IACF;AAAA,EACF;AAGA,SAAO,MAAM,OAAO,CAAC,GAAG,UAAU,aAAa,IAAI,KAAK,CAAC;AAC3D;AAKA,SAAS,cAAc,OAAiB,UAAqC;AAC3E,MAAI,SAAS;AACb,aAAW,WAAW,UAAU;AAC9B,aAAS,aAAa,QAAQ,OAAO;AAAA,EACvC;AACA,SAAO;AACT;AAUA,SAAS,eAAe,OAAiB,OAAyB;AAChE,QAAM,UAAU,MAAM,KAAK;AAG3B,MAAI,QAAQ,SAAS,GAAG,KAAK,CAAC,QAAQ,WAAW,GAAG,GAAG;AACrD,UAAM,IAAI,SAAS,QAAQ,MAAM,GAAG,EAAE,GAAG,EAAE;AAC3C,QAAI,CAAC,MAAM,CAAC,KAAK,IAAI,GAAG;AACtB,aAAO,MAAM,MAAM,GAAG,CAAC;AAAA,IACzB;AAAA,EACF;AAGA,MAAI,QAAQ,WAAW,GAAG,KAAK,CAAC,QAAQ,SAAS,KAAK,CAAC,GAAG;AACxD,UAAM,IAAI,SAAS,SAAS,EAAE;AAC9B,QAAI,CAAC,MAAM,CAAC,KAAK,IAAI,GAAG;AACtB,aAAO,MAAM,MAAM,CAAC;AAAA,IACtB;AAAA,EACF;AAGA,QAAM,aAAa,QAAQ,MAAM,eAAe;AAChD,MAAI,YAAY;AACd,UAAM,QAAQ,SAAS,WAAW,CAAC,GAAG,EAAE;AACxC,UAAM,MAAM,SAAS,WAAW,CAAC,GAAG,EAAE;AACtC,QAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,GAAG,KAAK,QAAQ,KAAK,OAAO,OAAO;AAE7D,aAAO,MAAM,MAAM,QAAQ,GAAG,GAAG;AAAA,IACnC;AAAA,EACF;AAGA,SAAO;AACT;AA6CO,SAAS,yBACd,OACA,iBAAyB,0BACzB;AACA,SAAO,aAAa;AAAA,IAClB,MAAM;AAAA,IACN,aACE;AAAA,IAGF,QAAQ,aAAE,OAAO;AAAA,MACf,IAAI,aAAE,OAAO,EAAE,SAAS,uDAAuD;AAAA,MAC/E,UAAU,aACP,MAAM,aAAa,EACnB,SAAS,EACT;AAAA,QACC;AAAA,MAEF;AAAA,MACF,OAAO,aACJ,OAAO,EACP,SAAS,EACT;AAAA,QACC;AAAA,MAEF;AAAA,IACJ,CAAC;AAAA,IACD,UAAU;AAAA,MACR;AAAA,QACE,SAAS;AAAA,QACT,QAAQ,EAAE,IAAI,mBAAmB,OAAO,MAAM;AAAA,MAChD;AAAA,MACA;AAAA,QACE,SAAS;AAAA,QACT,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,UAAU,CAAC,EAAE,OAAO,qBAAqB,SAAS,MAAM,QAAQ,GAAG,OAAO,EAAE,CAAC;AAAA,QAC/E;AAAA,MACF;AAAA,MACA;AAAA,QACE,SAAS;AAAA,QACT,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,UAAU,CAAC,EAAE,OAAO,UAAU,SAAS,OAAO,QAAQ,GAAG,OAAO,EAAE,CAAC;AAAA,UACnE,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,SAAS;AAAA,QACT,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,UAAU;AAAA,YACR,EAAE,OAAO,QAAQ,SAAS,MAAM,QAAQ,GAAG,OAAO,EAAE;AAAA,YACpD,EAAE,OAAO,aAAa,SAAS,OAAO,QAAQ,GAAG,OAAO,EAAE;AAAA,UAC5D;AAAA,UACA,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,IACA,SAAS,CAAC,EAAE,IAAI,UAAU,MAAM,MAAM;AACpC,YAAM,SAAS,MAAM,IAAI,EAAE;AAC3B,UAAI,CAAC,QAAQ;AACX,eAAO,oCAAoC,EAAE,qBAAqB,MAAM,OAAO,EAAE,KAAK,IAAI,KAAK,QAAQ;AAAA,MACzG;AAEA,UAAI,QAAQ,OAAO,QAAQ,MAAM,IAAI;AAGrC,UAAI,YAAY,SAAS,SAAS,GAAG;AACnC,gBAAQ;AAAA,UACN;AAAA,UACA,SAAS,IAAI,CAAC,OAAO;AAAA,YACnB,OAAO,EAAE;AAAA,YACT,SAAS,EAAE,WAAW;AAAA,YACtB,QAAQ,EAAE,UAAU;AAAA,YACpB,OAAO,EAAE,SAAS;AAAA,UACpB,EAAE;AAAA,QACJ;AAAA,MACF;AAGA,UAAI,OAAO;AACT,gBAAQ,eAAe,OAAO,KAAK;AAAA,MACrC;AAGA,UAAI,SAAS,MAAM,KAAK,IAAI;AAC5B,YAAM,aAAa,OAAO;AAC1B,YAAM,gBAAgB,MAAM;AAE5B,UAAI,kBAAkB,GAAG;AACvB,eAAO,qDAAqD,UAAU;AAAA,MACxE;AAGA,UAAI,kBAAkB;AACtB,UAAI,gBAAgB;AACpB,UAAI,OAAO,SAAS,gBAAgB;AAClC,0BAAkB;AAClB,YAAI,kBAAkB;AACtB,wBAAgB;AAEhB,mBAAW,QAAQ,OAAO;AACxB,cAAI,gBAAgB,SAAS,KAAK,SAAS,IAAI,eAAgB;AAC/D,6BAAmB,OAAO;AAC1B;AAAA,QACF;AAEA,iBAAS;AAAA,MACX;AAGA,UAAI;AACJ,UAAI,iBAAiB;AACnB,cAAM,iBAAiB,gBAAgB;AACvC,iBACE,YAAY,aAAa,OAAO,UAAU;AAAA,OAClC,eAAe,eAAe,CAAC,+DAA+D,gBAAgB,CAAC,IAAI,gBAAgB,GAAG;AAAA;AAAA,MAClJ,WAAW,gBAAgB,YAAY;AACrC,iBAAS,YAAY,aAAa,OAAO,UAAU;AAAA;AAAA,MACrD,OAAO;AACL,iBAAS,gBAAgB,UAAU;AAAA;AAAA,MACrC;AAEA,aAAO,SAAS;AAAA,IAClB;AAAA,EACF,CAAC;AACH;AAzRA,IAOA,YA2GM,eAqBA;AAvIN;AAAA;AAAA;AAOA,iBAAkB;AAElB;AAyGA,IAAM,gBAAgB,aAAE,OAAO;AAAA,MAC7B,OAAO,aAAE,OAAO,EAAE,SAAS,6BAA6B;AAAA,MACxD,SAAS,aACN,QAAQ,EACR,QAAQ,IAAI,EACZ,SAAS,4DAA4D;AAAA,MACxE,QAAQ,aACL,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,QAAQ,CAAC,EACT,SAAS,gDAAgD;AAAA,MAC5D,OAAO,aACJ,OAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,QAAQ,CAAC,EACT,SAAS,+CAA+C;AAAA,IAC7D,CAAC;AAGD,IAAM,2BAA2B;AAAA;AAAA;;;AC3H1B,SAAS,gBAAgB,KAAgD;AAC9E,SAAO,QAAQ;AACjB;AAdA,IAMa;AANb;AAAA;AAAA;AAMO,IAAM,qBAAqB,uBAAO,oBAAoB;AAAA;AAAA;;;AC+GtD,SAAS,mBAAmB,QAA2C;AAC5E,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,GAAG,qBAAqB;AAAA,EACnC;AAEA,SAAO;AAAA,IACL,SAAS,OAAO,WAAW,qBAAqB;AAAA,IAChD,SAAS,OAAO,WAAW,qBAAqB;AAAA,IAChD,YAAY,OAAO,cAAc,qBAAqB;AAAA,IACtD,YAAY,OAAO,cAAc,qBAAqB;AAAA,IACtD,QAAQ,OAAO,UAAU,qBAAqB;AAAA,IAC9C,WAAW,OAAO,aAAa,qBAAqB;AAAA,IACpD,SAAS,OAAO;AAAA,IAChB,oBAAoB,OAAO;AAAA,IAC3B,aAAa,OAAO;AAAA,EACtB;AACF;AAoBO,SAAS,iBAAiB,OAAuB;AACtD,QAAM,UAAU,MAAM,QAAQ,YAAY;AAC1C,QAAM,OAAO,MAAM;AAGnB,MAAI,QAAQ,SAAS,KAAK,KAAK,QAAQ,SAAS,YAAY,KAAK,QAAQ,SAAS,YAAY,GAAG;AAC/F,WAAO;AAAA,EACT;AAGA,MACE,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,uBAAuB,KACxC,QAAQ,SAAS,aAAa,KAC9B,QAAQ,SAAS,qBAAqB,KACtC,QAAQ,SAAS,iBAAiB,GAClC;AACA,WAAO;AAAA,EACT;AAGA,MACE,QAAQ,SAAS,SAAS,KAC1B,QAAQ,SAAS,WAAW,KAC5B,QAAQ,SAAS,WAAW,GAC5B;AACA,WAAO;AAAA,EACT;AAGA,MACE,QAAQ,SAAS,YAAY,KAC7B,QAAQ,SAAS,cAAc,KAC/B,QAAQ,SAAS,WAAW,KAC5B,QAAQ,SAAS,YAAY,KAC7B,QAAQ,SAAS,SAAS,GAC1B;AACA,WAAO;AAAA,EACT;AAGA,MACE,SAAS,wBACT,SAAS,oBACT,SAAS,yBACT,SAAS,6BACT,SAAS,mBACT;AACA,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,SAAS,YAAY,KAAK,QAAQ,SAAS,UAAU,GAAG;AAClE,WAAO;AAAA,EACT;AAGA,MACE,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,KAAK,KACtB,QAAQ,SAAS,gBAAgB,KACjC,QAAQ,SAAS,cAAc,KAC/B,QAAQ,SAAS,WAAW,KAC5B,QAAQ,SAAS,SAAS,KAC1B,QAAQ,SAAS,gBAAgB,KACjC,SAAS,yBACT,SAAS,qBACT,SAAS,mBACT,SAAS,yBACT;AACA,WAAO;AAAA,EACT;AAGA,SAAO;AACT;AAsBO,SAAS,eAAe,OAAsB;AACnD,QAAM,UAAU,MAAM;AACtB,QAAM,OAAO,MAAM;AAGnB,MAAI,QAAQ,SAAS,oBAAoB,KAAK,QAAQ,SAAS,KAAK,GAAG;AACrE,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,YAAY,EAAE,SAAS,YAAY,KAAK,QAAQ,YAAY,EAAE,SAAS,YAAY,GAAG;AAChG,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,YAAY,EAAE,SAAS,YAAY,KAAK,QAAQ,YAAY,EAAE,SAAS,UAAU,GAAG;AAC9F,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,SAAS,KAAK,KAAK,QAAQ,YAAY,EAAE,SAAS,uBAAuB,GAAG;AACtF,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,SAAS,KAAK,KAAK,QAAQ,YAAY,EAAE,SAAS,aAAa,GAAG;AAC5E,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,SAAS,KAAK,KAAK,QAAQ,YAAY,EAAE,SAAS,qBAAqB,GAAG;AACpF,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,SAAS,KAAK,KAAK,QAAQ,YAAY,EAAE,SAAS,iBAAiB,GAAG;AAChF,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,YAAY,EAAE,SAAS,SAAS,KAAK,QAAQ,YAAY,EAAE,SAAS,WAAW,GAAG;AAC5F,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,YAAY,EAAE,SAAS,cAAc,GAAG;AAClD,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,YAAY,EAAE,SAAS,YAAY,GAAG;AAChD,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,YAAY,EAAE,SAAS,WAAW,GAAG;AAC/C,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,SAAS,KAAK,KAAK,QAAQ,YAAY,EAAE,SAAS,cAAc,KAAK,SAAS,uBAAuB;AAC/G,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,SAAS,KAAK,KAAK,QAAQ,YAAY,EAAE,SAAS,WAAW,KAAK,SAAS,yBAAyB;AAC9G,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,SAAS,KAAK,KAAK,SAAS,mBAAmB;AAEzD,UAAM,QAAQ,QAAQ,MAAM,kCAAkC;AAC9D,QAAI,OAAO;AACT,aAAO,gBAAgB,MAAM,CAAC,EAAE,KAAK,CAAC;AAAA,IACxC;AACA,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,YAAY,EAAE,SAAS,gBAAgB,KAAK,QAAQ,YAAY,EAAE,SAAS,QAAQ,GAAG;AAChG,WAAO;AAAA,EACT;AAIA,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,OAAO;AAEjC,UAAM,mBAAmB,QAAQ,OAAO,WAAW,QAAQ;AAC3D,QAAI,OAAO,qBAAqB,YAAY,iBAAiB,SAAS,GAAG;AACvE,aAAO,iBAAiB,KAAK;AAAA,IAC/B;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,QAAM,YAAY,QAAQ,MAAM,8CAA8C;AAC9E,MAAI,WAAW;AACb,WAAO,UAAU,CAAC,EAAE,KAAK;AAAA,EAC3B;AAGA,MAAI,QAAQ,SAAS,KAAK;AAExB,UAAM,YAAY,QAAQ,MAAM,SAAS,EAAE,CAAC;AAC5C,QAAI,aAAa,UAAU,SAAS,MAAM,UAAU,SAAS,KAAK;AAChE,aAAO,UAAU,KAAK;AAAA,IACxB;AACA,WAAO,QAAQ,MAAM,GAAG,GAAG,EAAE,KAAK,IAAI;AAAA,EACxC;AAGA,SAAO;AACT;AAtWA,IAmGa;AAnGb;AAAA;AAAA;AAmGO,IAAM,uBAGT;AAAA,MACF,SAAS;AAAA,MACT,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,WAAW;AAAA,IACb;AAAA;AAAA;;;AC+DO,SAAS,wBAAwB,SAA2B,CAAC,GAA6B;AAC/F,QAAM,UACJ,OAAO,2BAA2B,0BAA0B;AAC9D,QAAM,SAAS,OAAO,iBAAiB,0BAA0B;AAGjE,MAAI,UAAU,SAAS;AACrB,YAAQ;AAAA,MACN,sCAAsC,MAAM,kDAAkD,OAAO;AAAA,IACvG;AAAA,EACF;AAGA,QAAM,WAAW,OAAO,YAAY,0BAA0B;AAC9D,QAAM,eACJ,OAAO,aAAa,YAAY,UAAU,WACrC,SAAS,OACV;AAEN,SAAO;AAAA,IACL,SAAS,OAAO,WAAW,0BAA0B;AAAA,IACrD,UAAU;AAAA,IACV,yBAAyB;AAAA,IACzB,eAAe;AAAA,IACf,qBACE,OAAO,uBAAuB,0BAA0B;AAAA,IAC1D,oBAAoB,OAAO;AAAA,IAC3B,qBAAqB,OAAO,uBAAuB;AAAA,IACnD,cAAc,OAAO;AAAA,EACvB;AACF;AA1MA,IAqIa,2BAaA;AAlJb;AAAA;AAAA;AAqIO,IAAM,4BAET;AAAA,MACF,SAAS;AAAA,MACT,UAAU;AAAA,MACV,yBAAyB;AAAA,MACzB,eAAe;AAAA,MACf,qBAAqB;AAAA,IACvB;AAKO,IAAM,+BAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACxBrC,SAAS,eAAe,UAAuC;AACpE,QAAM,QAAuB,CAAC;AAC9B,MAAI,cAA4B,CAAC;AAEjC,aAAW,OAAO,UAAU;AAC1B,QAAI,IAAI,SAAS,UAAU,YAAY,SAAS,GAAG;AAEjD,YAAM,KAAK;AAAA,QACT,UAAU;AAAA,QACV,eAAe,mBAAmB,WAAW;AAAA,MAC/C,CAAC;AACD,oBAAc,CAAC,GAAG;AAAA,IACpB,OAAO;AACL,kBAAY,KAAK,GAAG;AAAA,IACtB;AAAA,EACF;AAGA,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,KAAK;AAAA,MACT,UAAU;AAAA,MACV,eAAe,mBAAmB,WAAW;AAAA,IAC/C,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAKA,SAAS,mBAAmB,UAAgC;AAC1D,SAAO,KAAK,KAAK,SAAS,OAAO,CAAC,KAAK,QAAQ,OAAO,IAAI,SAAS,UAAU,IAAI,CAAC,IAAI,CAAC;AACzF;AAKO,SAAS,aAAa,OAAoC;AAC/D,SAAO,MAAM,QAAQ,CAAC,SAAS,KAAK,QAAQ;AAC9C;AAlKA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAuBM,4BAYO;AAnCb;AAAA;AAAA;AAYA;AAWA,IAAM,6BACJ;AAWK,IAAM,wBAAN,MAA0D;AAAA,MACtD,OAAO;AAAA,MAEhB,MAAM,QACJ,UACA,QACA,SAC2B;AAC3B,cAAM,QAAQ,eAAe,QAAQ;AACrC,cAAM,gBAAgB,KAAK,IAAI,OAAO,qBAAqB,MAAM,MAAM;AAGvE,YAAI,MAAM,UAAU,eAAe;AACjC,iBAAO;AAAA,YACL;AAAA,YACA,cAAc,KAAK;AAAA,YACnB,UAAU;AAAA,cACR,eAAe,SAAS;AAAA,cACxB,gBAAgB,SAAS;AAAA,cACzB,cAAc,QAAQ;AAAA,cACtB,aAAa,QAAQ;AAAA,YACvB;AAAA,UACF;AAAA,QACF;AAGA,cAAM,cAAc,MAAM,MAAM,CAAC,aAAa;AAC9C,cAAM,eAAe,MAAM,SAAS;AAGpC,cAAM,mBAA+B;AAAA,UACnC,MAAM;AAAA,UACN,SAAS,2BAA2B,QAAQ,WAAW,aAAa,SAAS,CAAC;AAAA,QAChF;AAGA,cAAM,oBAAkC,CAAC,kBAAkB,GAAG,aAAa,WAAW,CAAC;AAGvF,cAAM,cAAc,KAAK;AAAA,UACvB,kBAAkB,OAAO,CAAC,KAAK,QAAQ,OAAO,IAAI,SAAS,UAAU,IAAI,CAAC,IAAI;AAAA,QAChF;AAEA,eAAO;AAAA,UACL,UAAU;AAAA,UACV,cAAc,KAAK;AAAA,UACnB,UAAU;AAAA,YACR,eAAe,SAAS;AAAA,YACxB,gBAAgB,kBAAkB;AAAA,YAClC,cAAc,QAAQ;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACzFA,IA6Ba;AA7Bb;AAAA;AAAA;AAYA;AAiBO,IAAM,wBAAN,MAA0D;AAAA,MACtD,OAAO;AAAA,MAEhB,MAAM,QACJ,UACA,QACA,SAC2B;AAC3B,cAAM,QAAQ,eAAe,QAAQ;AACrC,cAAM,gBAAgB,KAAK,IAAI,OAAO,qBAAqB,MAAM,MAAM;AAGvE,YAAI,MAAM,UAAU,eAAe;AACjC,iBAAO;AAAA,YACL;AAAA,YACA,cAAc,KAAK;AAAA,YACnB,UAAU;AAAA,cACR,eAAe,SAAS;AAAA,cACxB,gBAAgB,SAAS;AAAA,cACzB,cAAc,QAAQ;AAAA,cACtB,aAAa,QAAQ;AAAA,YACvB;AAAA,UACF;AAAA,QACF;AAGA,cAAM,mBAAmB,MAAM,MAAM,GAAG,CAAC,aAAa;AACtD,cAAM,cAAc,MAAM,MAAM,CAAC,aAAa;AAG9C,cAAM,0BAA0B,KAAK,sBAAsB,aAAa,gBAAgB,CAAC;AAGzF,cAAM,UAAU,MAAM,KAAK,gBAAgB,yBAAyB,QAAQ,OAAO;AAGnF,cAAM,iBAA6B;AAAA,UACjC,MAAM;AAAA,UACN,SAAS;AAAA,EAAoC,OAAO;AAAA;AAAA,QACtD;AAGA,cAAM,oBAAkC,CAAC,gBAAgB,GAAG,aAAa,WAAW,CAAC;AAGrF,cAAM,cAAc,KAAK;AAAA,UACvB,kBAAkB,OAAO,CAAC,KAAK,QAAQ,OAAO,IAAI,SAAS,UAAU,IAAI,CAAC,IAAI;AAAA,QAChF;AAEA,eAAO;AAAA,UACL,UAAU;AAAA,UACV;AAAA,UACA,cAAc,KAAK;AAAA,UACnB,UAAU;AAAA,YACR,eAAe,SAAS;AAAA,YACxB,gBAAgB,kBAAkB;AAAA,YAClC,cAAc,QAAQ;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKQ,sBAAsB,UAAgC;AAC5D,eAAO,SACJ,IAAI,CAAC,QAAQ;AACZ,gBAAM,OAAO,IAAI,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,IAAI,KAAK,MAAM,CAAC;AAChE,iBAAO,GAAG,IAAI,KAAK,IAAI,OAAO;AAAA,QAChC,CAAC,EACA,KAAK,MAAM;AAAA,MAChB;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,gBACZ,cACA,QACA,SACiB;AACjB,cAAM,QAAQ,OAAO,sBAAsB,QAAQ;AACnD,cAAM,SAAS,GAAG,OAAO,mBAAmB;AAAA;AAAA,EAAO,YAAY;AAG/D,cAAM,WAAW,MAAM,QAAQ,OAAO,SAAS,QAAQ;AAAA,UACrD;AAAA,UACA,aAAa;AAAA;AAAA,QACf,CAAC;AAED,eAAO,SAAS,KAAK;AAAA,MACvB;AAAA,IACF;AAAA;AAAA;;;AC1HA,IA0BM,6BAUO;AApCb;AAAA;AAAA;AAaA;AAMA;AACA;AAMA,IAAM,8BAA8B;AAU7B,IAAM,iBAAN,MAAmD;AAAA,MAC/C,OAAO;AAAA,MAEC,gBAAgB,IAAI,sBAAsB;AAAA,MAC1C,gBAAgB,IAAI,sBAAsB;AAAA,MAE3D,MAAM,QACJ,UACA,QACA,SAC2B;AAC3B,cAAM,QAAQ,eAAe,QAAQ;AACrC,cAAM,gBAAgB,KAAK,IAAI,OAAO,qBAAqB,MAAM,MAAM;AAGvE,YAAI,MAAM,UAAU,eAAe;AACjC,iBAAO;AAAA,YACL;AAAA,YACA,cAAc,KAAK;AAAA,YACnB,UAAU;AAAA,cACR,eAAe,SAAS;AAAA,cACxB,gBAAgB,SAAS;AAAA,cACzB,cAAc,QAAQ;AAAA,cACtB,aAAa,QAAQ;AAAA,YACvB;AAAA,UACF;AAAA,QACF;AAGA,cAAM,mBAAmB,MAAM,SAAS;AAGxC,YAAI,mBAAmB,6BAA6B;AAElD,iBAAO,KAAK,cAAc,QAAQ,UAAU,QAAQ,OAAO;AAAA,QAC7D;AAGA,eAAO,KAAK,cAAc,QAAQ,UAAU,QAAQ,OAAO;AAAA,MAC7D;AAAA,IACF;AAAA;AAAA;;;AC5EA;AAAA;AAAA;AASA;AACA;AACA;AAAA;AAAA;;;AC6BA,SAAS,eAAe,MAAkC;AACxD,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,IAAI,sBAAsB;AAAA,IACnC,KAAK;AACH,aAAO,IAAI,sBAAsB;AAAA,IACnC,KAAK;AACH,aAAO,IAAI,eAAe;AAAA,IAC5B;AACE,YAAM,IAAI,MAAM,gCAAgC,IAAI,EAAE;AAAA,EAC1D;AACF;AAnDA,IA8Da;AA9Db;AAAA;AAAA;AAWA;AAOA;AA4CO,IAAM,oBAAN,MAAwB;AAAA,MACZ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACT;AAAA;AAAA,MAGA,mBAAmB;AAAA,MACnB,mBAAmB;AAAA,MACnB,iBAAiB;AAAA,MAEzB,YAAY,QAAgB,OAAe,SAA2B,CAAC,GAAG;AACxE,aAAK,SAAS;AACd,aAAK,QAAQ;AACb,aAAK,SAAS,wBAAwB,MAAM;AAG5C,YAAI,OAAO,OAAO,aAAa,YAAY,aAAa,OAAO,UAAU;AACvE,eAAK,WAAW,OAAO;AAAA,QACzB,OAAO;AACL,eAAK,WAAW,eAAe,KAAK,OAAO,QAAQ;AAAA,QACrD;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,MAAM,gBACJ,cACA,WACiC;AACjC,YAAI,CAAC,KAAK,OAAO,SAAS;AACxB,iBAAO;AAAA,QACT;AAGA,YAAI,CAAC,KAAK,aAAa;AACrB,eAAK,cAAc,KAAK,OAAO,cAAc,eAAe,KAAK,KAAK;AACtE,cAAI,CAAC,KAAK,aAAa;AAGrB,mBAAO;AAAA,UACT;AAAA,QACF;AAGA,YAAI,CAAC,KAAK,OAAO,aAAa;AAC5B,iBAAO;AAAA,QACT;AACA,cAAM,WAAW,aAAa,YAAY;AAC1C,cAAM,gBAAgB,MAAM,KAAK,OAAO,YAAY,KAAK,OAAO,QAAQ;AACxE,aAAK,iBAAiB;AAGtB,cAAM,eAAgB,gBAAgB,KAAK,YAAY,gBAAiB;AAGxE,YAAI,eAAe,KAAK,OAAO,yBAAyB;AACtD,iBAAO;AAAA,QACT;AAGA,cAAM,kBAAkB,aAAa,mBAAmB;AACxD,cAAM,eAAe,aAAa,gBAAgB;AAClD,cAAM,gBAAgB,MAAM,KAAK,OAAO,YAAY,KAAK,OAAO,eAAe;AAC/E,cAAM,aAAa,MAAM,KAAK,OAAO,YAAY,KAAK,OAAO,YAAY;AAEzE,eAAO,KAAK,QAAQ,cAAc,WAAW;AAAA,UAC3C;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,eAAe,gBAAgB;AAAA,QACjC,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA,MAAM,QACJ,cACA,WACA,aACiC;AACjC,YAAI,CAAC,KAAK,aAAa;AACrB,eAAK,cAAc,KAAK,OAAO,cAAc,eAAe,KAAK,KAAK;AACtE,cAAI,CAAC,KAAK,aAAa;AACrB,mBAAO;AAAA,UACT;AAAA,QACF;AAGA,cAAM,kBAAkB,aAAa,mBAAmB,aAAa,mBAAmB;AACxF,cAAM,eAAe,aAAa,gBAAgB,aAAa,gBAAgB;AAC/E,cAAM,gBACJ,aAAa,iBAAkB,MAAM,KAAK,OAAO,YAAY,KAAK,OAAO,eAAe;AAC1F,cAAM,aACJ,aAAa,cAAe,MAAM,KAAK,OAAO,YAAY,KAAK,OAAO,YAAY;AACpF,cAAM,gBAAgB,aAAa,iBAAiB,gBAAgB;AAGpE,cAAM,oBAAoB,KAAK;AAAA,UAC5B,KAAK,YAAY,gBAAgB,KAAK,OAAO,gBAAiB;AAAA,QACjE;AACA,cAAM,sBAAsB,KAAK,IAAI,GAAG,oBAAoB,UAAU;AAGtE,cAAM,SAAS,MAAM,KAAK,SAAS,QAAQ,iBAAiB,KAAK,QAAQ;AAAA,UACvE,eAAe;AAAA,UACf,cAAc;AAAA,UACd,aAAa,KAAK;AAAA,UAClB,QAAQ,KAAK;AAAA,UACb,OAAO,KAAK,OAAO,sBAAsB,KAAK;AAAA,QAChD,CAAC;AAGD,qBAAa,eAAe,OAAO,QAAQ;AAG3C,cAAM,cAAc,MAAM,KAAK,OAAO,YAAY,KAAK,OAAO,aAAa,YAAY,CAAC;AACxF,cAAM,cAAc,gBAAgB;AAGpC,aAAK;AACL,aAAK,oBAAoB;AACzB,aAAK,iBAAiB;AAGtB,cAAM,QAAyB;AAAA,UAC7B,UAAU,OAAO;AAAA,UACjB,cAAc;AAAA,UACd,aAAa;AAAA,UACb,gBAAgB,gBAAgB,SAAS,aAAa;AAAA,UACtD,eAAe,OAAO,SAAS,SAAS,aAAa;AAAA,UACrD,SAAS,OAAO;AAAA,UAChB;AAAA,QACF;AAGA,YAAI,KAAK,OAAO,cAAc;AAC5B,cAAI;AACF,iBAAK,OAAO,aAAa,KAAK;AAAA,UAChC,SAAS,KAAK;AACZ,oBAAQ,KAAK,oDAAoD,GAAG;AAAA,UACtE;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,WAA4B;AAC1B,cAAM,gBAAgB,KAAK,aAAa,iBAAiB;AACzD,eAAO;AAAA,UACL,kBAAkB,KAAK;AAAA,UACvB,kBAAkB,KAAK;AAAA,UACvB,cAAc;AAAA,YACZ,QAAQ,KAAK;AAAA,YACb,SAAS,gBAAgB,IAAK,KAAK,iBAAiB,gBAAiB,MAAM;AAAA,UAC7E;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,YAAqB;AACnB,eAAO,KAAK,OAAO;AAAA,MACrB;AAAA,IACF;AAAA;AAAA;;;ACpPA,IA0Ba;AA1Bb;AAAA;AAAA;AAMA;AAoBO,IAAM,sBAAN,MAA0D;AAAA,MAC9C;AAAA,MACA;AAAA,MACT;AAAA,MACS;AAAA,MACA;AAAA,MACA;AAAA,MAEjB,YACE,cACA,iBACA,UAAsC,CAAC,GACvC;AACA,aAAK,eAAe;AACpB,aAAK,kBAAkB;AACvB,aAAK,iBAAiB,IAAI,kBAAkB;AAG5C,aAAK,cAAc,QAAQ;AAC3B,aAAK,YAAY,QAAQ;AACzB,aAAK,YAAY,QAAQ;AAGzB,YAAI,QAAQ,eAAe,QAAQ,WAAW;AAC5C,eAAK,eAAe,aAAa,QAAQ,aAAa,QAAQ,WAAW,QAAQ,SAAS;AAAA,QAC5F;AAAA,MACF;AAAA,MAEA,eAAe,SAA+B;AAC5C,aAAK,eAAe,QAAQ,OAAO;AAAA,MACrC;AAAA,MAEA,oBAAoB,SAAuB;AACzC,aAAK,eAAe,aAAa,OAAO;AAAA,MAC1C;AAAA,MAEA,oBACE,YACA,YACA,QACA,cACA,OACA,UACM;AACN,aAAK,eAAe,oBAAoB,YAAY,YAAY,QAAQ,cAAc,OAAO,QAAQ;AAAA,MACvG;AAAA,MAEA,cAA4B;AAC1B,eAAO,CAAC,GAAG,KAAK,cAAc,GAAG,KAAK,iBAAiB,GAAG,KAAK,eAAe,MAAM,CAAC;AAAA,MACvF;AAAA,MAEA,qBAAmC;AACjC,eAAO,KAAK,eAAe,MAAM;AAAA,MACnC;AAAA,MAEA,kBAAgC;AAC9B,eAAO,CAAC,GAAG,KAAK,cAAc,GAAG,KAAK,eAAe;AAAA,MACvD;AAAA,MAEA,eAAe,YAAgC;AAE7C,aAAK,iBAAiB,IAAI,kBAAkB;AAC5C,YAAI,KAAK,eAAe,KAAK,WAAW;AACtC,eAAK,eAAe,aAAa,KAAK,aAAa,KAAK,WAAW,KAAK,SAAS;AAAA,QACnF;AAGA,mBAAW,OAAO,YAAY;AAC5B,cAAI,IAAI,SAAS,QAAQ;AACvB,iBAAK,eAAe,QAAQ,IAAI,OAAO;AAAA,UACzC,WAAW,IAAI,SAAS,aAAa;AAEnC,iBAAK,eAAe,aAAa,mBAAmB,IAAI,OAAO,CAAC;AAAA,UAClE;AAAA,QAEF;AAAA,MACF;AAAA,MAEA,yBAAuC;AAGrC,eAAO,CAAC,GAAG,KAAK,iBAAiB,GAAG,KAAK,eAAe,MAAM,CAAC;AAAA,MACjE;AAAA,IACF;AAAA;AAAA;;;AC9CA,eAAsB,gBACpB,gBACA,UACe;AACf,mBAAiB,SAAS,gBAAgB;AACxC,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,YAAI,SAAS,QAAQ;AACnB,gBAAM,SAAS,OAAO,MAAM,OAAO;AAAA,QACrC;AACA;AAAA,MAEF,KAAK;AACH,YAAI,SAAS,cAAc;AACzB,gBAAM,SAAS,aAAa;AAAA,YAC1B,YAAY,MAAM,KAAK;AAAA,YACvB,cAAc,MAAM,KAAK;AAAA,YACzB,YAAY,MAAM,KAAK;AAAA,YACvB,eAAe,MAAM,KAAK;AAAA,YAC1B,cAAc,MAAM,KAAK;AAAA,UAC3B,CAAC;AAAA,QACH;AACA;AAAA,MAEF,KAAK;AACH,YAAI,SAAS,gBAAgB;AAC3B,gBAAM,SAAS,eAAe,MAAM,MAAM;AAAA,QAC5C;AACA;AAAA,MAEF,KAAK;AACH,YAAI,SAAS,sBAAsB;AACjC,gBAAM,SAAS,qBAAqB;AAAA,YAClC,UAAU,MAAM;AAAA,YAChB,YAAY,MAAM;AAAA,UACpB,CAAC;AAAA,QACH;AACA;AAAA,MAEF;AACE,YAAI,SAAS,SAAS;AACpB,gBAAM,SAAS,QAAQ,KAAK;AAAA,QAC9B;AACA;AAAA,IACJ;AAAA,EACF;AACF;AAoBA,eAAsB,cACpB,gBACA,SAcC;AACD,QAAM,SAAS;AAAA,IACb,MAAM,CAAC;AAAA,IACP,aAAa,CAAC;AAAA,IACd,eAAe,CAAC;AAAA,EAMlB;AAEA,mBAAiB,SAAS,gBAAgB;AACxC,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,YAAI,QAAQ,MAAM;AAChB,iBAAO,KAAK,KAAK,MAAM,OAAO;AAAA,QAChC;AACA;AAAA,MAEF,KAAK;AACH,YAAI,QAAQ,eAAe,MAAM,KAAK,YAAY;AAChD,iBAAO,YAAY,KAAK;AAAA,YACtB,YAAY,MAAM,KAAK;AAAA,YACvB,YAAY,MAAM,KAAK;AAAA,UACzB,CAAC;AAAA,QACH;AACA;AAAA,MAEF,KAAK;AACH,YAAI,QAAQ,eAAe;AACzB,iBAAO,cAAc,KAAK,MAAM,MAAM;AAAA,QACxC;AACA;AAAA,IACJ;AAAA,EACF;AAEA,SAAO;AACT;AAcA,eAAsB,YAAY,gBAA8D;AAC9F,QAAM,SAAmB,CAAC;AAE1B,mBAAiB,SAAS,gBAAgB;AACxC,QAAI,MAAM,SAAS,QAAQ;AACzB,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B;AAAA,EACF;AAEA,SAAO,OAAO,KAAK,EAAE;AACvB;AA/MA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAOAC,qBAoCa;AA3Cb;AAAA;AAAA;AAOA,IAAAA,sBAA4B;AAoCrB,IAAM,oBAAN,MAAwB;AAAA,MACrB,UAAU,oBAAI,IAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAShD,MAAM,YAAoB,SAAyB;AACjD,cAAM,KAAK,KAAK,WAAW,UAAU;AACrC,cAAM,UAAU,IAAI,YAAY;AAEhC,cAAM,SAAuB;AAAA,UAC3B;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU,QAAQ,OAAO,OAAO,EAAE;AAAA,UAClC,WAAW,QAAQ,MAAM,IAAI,EAAE;AAAA,UAC/B,WAAW,oBAAI,KAAK;AAAA,QACtB;AAEA,aAAK,QAAQ,IAAI,IAAI,MAAM;AAC3B,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,IAAI,IAAsC;AACxC,eAAO,KAAK,QAAQ,IAAI,EAAE;AAAA,MAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,IAAI,IAAqB;AACvB,eAAO,KAAK,QAAQ,IAAI,EAAE;AAAA,MAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,SAAmB;AACjB,eAAO,MAAM,KAAK,KAAK,QAAQ,KAAK,CAAC;AAAA,MACvC;AAAA;AAAA;AAAA;AAAA,MAKA,IAAI,OAAe;AACjB,eAAO,KAAK,QAAQ;AAAA,MACtB;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,QAAc;AACZ,aAAK,QAAQ,MAAM;AAAA,MACrB;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,WAAW,YAA4B;AAC7C,cAAM,UAAM,iCAAY,CAAC,EAAE,SAAS,KAAK;AACzC,eAAO,GAAG,UAAU,IAAI,GAAG;AAAA,MAC7B;AAAA,IACF;AAAA;AAAA;;;ACjGO,SAAS,4BAA4B,QAAmC;AAC7E,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,EAAE,YAAY,SAAS;AAClE,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,OAAO;AAC1B,MAAI,eAAe,aAAa,eAAe,QAAQ;AACrD,UAAM,IAAI;AAAA,MACR;AAAA,MACA,wBAAwB,UAAU;AAAA,IACpC;AAAA,EACF;AAEA,MAAI,eAAe,UAAU,CAAC,OAAO,mBAAmB;AACtD,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,2BAA2B,QAAkC;AAC3E,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,EAAE,YAAY,SAAS;AAClE,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,OAAO;AAC1B,QAAM,eAAe,CAAC,YAAY,mBAAmB,uBAAuB,mBAAmB;AAC/F,MAAI,CAAC,aAAa,SAAS,UAAU,GAAG;AACtC,UAAM,IAAI;AAAA,MACR;AAAA,MACA,wBAAwB,UAAU,qBAAqB,aAAa,KAAK,IAAI,CAAC;AAAA,IAChF;AAAA,EACF;AAEA,MAAI,eAAe,qBAAqB,eAAe,qBAAqB;AAC1E,QAAI,EAAE,cAAc,WAAW,CAAC,OAAO,YAAY,CAAC,MAAM,QAAQ,OAAO,QAAQ,GAAG;AAClF,YAAM,IAAI;AAAA,QACR;AAAA,QACA,mBAAmB,UAAU;AAAA,MAC/B;AAAA,IACF;AAEA,QAAI,OAAO,SAAS,WAAW,GAAG;AAChC,YAAM,IAAI;AAAA,QACR;AAAA,QACA,mBAAmB,UAAU;AAAA,MAC/B;AAAA,IACF;AAGA,aAAS,IAAI,GAAG,IAAI,OAAO,SAAS,QAAQ,KAAK;AAC/C,YAAM,MAAM,OAAO,SAAS,CAAC;AAC7B,UAAI,CAAC,OAAO,OAAO,QAAQ,UAAU;AACnC,cAAM,IAAI,oBAAoB,gBAAgB,oBAAoB,CAAC,oBAAoB;AAAA,MACzF;AACA,UAAI,CAAC,IAAI,QAAQ,CAAC,IAAI,SAAS;AAC7B,cAAM,IAAI;AAAA,UACR;AAAA,UACA,oBAAoB,CAAC;AAAA,QACvB;AAAA,MACF;AACA,UAAI,CAAC,CAAC,UAAU,QAAQ,WAAW,EAAE,SAAS,IAAI,IAAI,GAAG;AACvD,cAAM,IAAI;AAAA,UACR;AAAA,UACA,oBAAoB,CAAC,sBAAsB,IAAI,IAAI;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,eAAe,yBAAyB,eAAe,qBAAqB;AAC9E,QAAI,EAAE,qBAAqB,WAAW,CAAC,OAAO,iBAAiB;AAC7D,YAAM,IAAI;AAAA,QACR;AAAA,QACA,mBAAmB,UAAU;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,4BAA4B,QAAmC;AAC7E,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,EAAE,YAAY,SAAS;AAClE,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,OAAO;AAC1B,MAAI,eAAe,aAAa,eAAe,WAAW;AACxD,UAAM,IAAI;AAAA,MACR;AAAA,MACA,wBAAwB,UAAU;AAAA,IACpC;AAAA,EACF;AAEA,MAAI,eAAe,aAAa,CAAC,OAAO,kBAAkB;AACxD,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,oCAAoC,QAA2C;AAC7F,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,EAAE,YAAY,SAAS;AAClE,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,OAAO;AAC1B,MAAI,eAAe,aAAa,eAAe,QAAQ;AACrD,UAAM,IAAI;AAAA,MACR;AAAA,MACA,wBAAwB,UAAU;AAAA,IACpC;AAAA,EACF;AAEA,MAAI,eAAe,UAAU,CAAC,OAAO,iBAAiB;AACpD,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAKO,SAAS,mCAAmC,QAA0C;AAC3F,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY,EAAE,YAAY,SAAS;AAClE,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,aAAa,OAAO;AAC1B,MAAI,eAAe,cAAc,eAAe,WAAW;AACzD,UAAM,IAAI;AAAA,MACR;AAAA,MACA,wBAAwB,UAAU;AAAA,IACpC;AAAA,EACF;AAEA,MAAI,eAAe,aAAa,CAAC,OAAO,gBAAgB;AACtD,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAlMA,IAea;AAfb;AAAA;AAAA;AAeO,IAAM,sBAAN,cAAkC,MAAM;AAAA,MAC7C,YAAY,UAAkB,SAAiB;AAC7C,cAAM,uBAAuB,QAAQ,KAAK,OAAO,EAAE;AACnD,aAAK,OAAO;AAAA,MACd;AAAA,IACF;AAAA;AAAA;;;ACpBA,IASa;AATb;AAAA;AAAA;AASO,IAAM,mBAAgC;AAAA,MAC3C;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,QACb;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,QACb;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OACE;AAAA,QACJ;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,QACb;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,QACb;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,QACb;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,QACV;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,QACV;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,QACV;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA,MAEA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,QACb;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,QACb;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,QACb;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,iBAAiB;AAAA,QACnB;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,QACb;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACvTA,IAmBsB;AAnBtB;AAAA;AAAA;AAmBO,IAAe,sBAAf,MAA8D;AAAA,MAGnE,YAA+B,QAAiB;AAAjB;AAAA,MAAkB;AAAA;AAAA;AAAA;AAAA;AAAA,MAcjD,OAAO,OACL,SACA,YACA,MACW;AAEX,cAAM,mBAAmB,KAAK,gBAAgB,QAAQ,QAAQ;AAG9D,cAAM,UAAU,KAAK,gBAAgB,SAAS,YAAY,MAAM,gBAAgB;AAGhF,cAAM,YAAY,MAAM,KAAK,qBAAqB,SAAS,QAAQ,MAAM;AAGzE,eAAO,KAAK,wBAAwB,SAAS;AAAA,MAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWU,gBAAgB,UAAsC;AAC9D,eAAO;AAAA,MACT;AAAA,IAwCF;AAAA;AAAA;;;AChGO,SAAS,WAAW,KAAiC;AAC1D,MAAI,OAAO,YAAY,eAAe,OAAO,QAAQ,QAAQ,aAAa;AACxE,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,QAAQ,IAAI,GAAG;AAC7B,SAAO,OAAO,UAAU,WAAW,QAAQ;AAC7C;AAOO,SAAS,WAAW,OAA4C;AACrE,SAAO,OAAO,UAAU,YAAY,MAAM,KAAK,EAAE,SAAS;AAC5D;AAUO,SAAS,sBACd,YAEA,aACA,eACA,eACkB;AAClB,QAAM,SAAS,WAAW,UAAU;AACpC,MAAI,CAAC,WAAW,MAAM,GAAG;AACvB,WAAO;AAAA,EACT;AAGA,QAAM,SAAS,IAAI,YAAY,EAAE,QAAQ,OAAO,KAAK,GAAG,GAAG,cAAc,CAAC;AAE1E,SAAO,IAAI,cAAc,MAAM;AACjC;AAlDA;AAAA;AAAA;AAAA;AAAA;;;ACuVO,SAAS,iCAAmE;AACjF,SAAO,sBAAsB,qBAAqB,WAAAC,SAAW,yBAAyB;AACxF;AAzVA,gBAkBa;AAlBb;AAAA;AAAA;AAAA,iBAAsB;AAUtB;AAGA;AACA;AACA,IAAAC;AACA;AAEO,IAAM,4BAAN,cAAwC,oBAAoB;AAAA,MACxD,aAAa;AAAA,MAEtB,SAAS,YAAsC;AAC7C,eAAO,WAAW,aAAa,KAAK;AAAA,MACtC;AAAA,MAEA,gBAAgB;AACd,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAMA,wBAAwB,UAA2B;AACjD,eAAO;AAAA,MACT;AAAA,MAEA,MAAM,gBAAgC;AACpC,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAMA,yBAAyB,UAA2B;AAClD,eAAO;AAAA,MACT;AAAA,MAEA,MAAM,iBAAiC;AACrC,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,MAEU,gBACR,SACA,YACA,MACA,UAC8B;AAC9B,cAAM,iBAAiB,SAAS,OAAO,CAAC,YAAY,QAAQ,SAAS,QAAQ;AAK7E,cAAM,SACJ,eAAe,SAAS,IACpB,eAAe,IAAI,CAAC,GAAG,WAAW;AAAA,UAChC,MAAM;AAAA,UACN,MAAM,mBAAmB,EAAE,OAAO;AAAA;AAAA,UAElC,GAAI,UAAU,eAAe,SAAS,IAClC,EAAE,eAAe,EAAE,MAAM,YAAqB,EAAE,IAChD,CAAC;AAAA,QACP,EAAE,IACF;AAEN,cAAM,oBAAoB,SAAS;AAAA,UACjC,CAAC,YACC,QAAQ,SAAS;AAAA,QACrB;AAGA,cAAM,gBAAgB,kBAAkB;AAAA,UACtC,CAAC,SAAS,KAAK,QAAS,IAAI,SAAS,SAAS,MAAM;AAAA,UACpD;AAAA,QACF;AAIA,cAAM,eAAe,kBAAkB,IAAI,CAAC,SAAS,WAAW;AAAA,UAC9D,MAAM,QAAQ;AAAA,UACd,SAAS,KAAK;AAAA,YACZ,QAAQ;AAAA,YACR,QAAQ,SAAS,UAAU,UAAU;AAAA,UACvC;AAAA,QACF,EAAE;AAIF,cAAM,mBAAmB,MAAM,mBAAmB;AAElD,cAAM,UAAwC;AAAA,UAC5C,OAAO,WAAW;AAAA,UAClB;AAAA,UACA,UAAU;AAAA,UACV,YAAY,QAAQ,aAAa;AAAA,UACjC,aAAa,QAAQ;AAAA,UACrB,OAAO,QAAQ;AAAA,UACf,gBAAgB,QAAQ;AAAA,UACxB,QAAQ;AAAA,UACR,GAAG,QAAQ;AAAA,QACb;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,0BACN,SACA,iBACqB;AACrB,cAAM,QAAQ,wBAAwB,OAAO;AAE7C,eAAO,MAAM,IAAI,CAAC,MAAM,UAAU;AAChC,gBAAM,aAAa,UAAU,MAAM,SAAS;AAC5C,gBAAM,eACJ,mBAAmB,aAAa,EAAE,eAAe,EAAE,MAAM,YAAqB,EAAE,IAAI,CAAC;AAEvF,cAAI,KAAK,SAAS,QAAQ;AACxB,mBAAO;AAAA,cACL,MAAM;AAAA,cACN,MAAM,KAAK;AAAA,cACX,GAAG;AAAA,YACL;AAAA,UACF;AAEA,cAAI,KAAK,SAAS,SAAS;AACzB,mBAAO,KAAK,iBAAiB,MAAM,YAAY;AAAA,UACjD;AAEA,cAAI,KAAK,SAAS,SAAS;AACzB,kBAAM,IAAI;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,IAAI,MAAM,6BAA8B,KAAqB,IAAI,EAAE;AAAA,QAC3E,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA,MAKQ,iBACN,MACA,cACiB;AACjB,YAAI,KAAK,OAAO,SAAS,OAAO;AAC9B,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,YAAY,KAAK,OAAO;AAAA,YACxB,MAAM,KAAK,OAAO;AAAA,UACpB;AAAA,UACA,GAAG;AAAA,QACL;AAAA,MACF;AAAA,MAEA,MAAgB,qBACd,SACA,QAC4C;AAC5C,cAAM,SAAS,KAAK;AAEpB,cAAMC,UAAS,MAAM,OAAO,SAAS,OAAO,SAAS,SAAS,EAAE,OAAO,IAAI,MAAS;AACpF,eAAOA;AAAA,MACT;AAAA,MAEA,OAAiB,wBAAwB,UAA6C;AACpF,cAAMA,UAAS;AACf,YAAI,cAAc;AAClB,YAAI,oBAAoB;AACxB,YAAI,2BAA2B;AAE/B,yBAAiB,SAASA,SAAQ;AAGhC,cAAI,MAAM,SAAS,iBAAiB;AAClC,kBAAM,QAAQ,MAAM,QAAQ;AAM5B,gCAAoB,MAAM,2BAA2B;AACrD,uCAA2B,MAAM,+BAA+B;AAChE,0BAAc,MAAM,eAAe,oBAAoB;AAEvD,kBAAM;AAAA,cACJ,MAAM;AAAA,cACN,OAAO;AAAA,gBACL;AAAA,gBACA,cAAc;AAAA,gBACd,aAAa;AAAA,gBACb;AAAA,gBACA;AAAA,cACF;AAAA,cACA,UAAU;AAAA,YACZ;AACA;AAAA,UACF;AAEA,cAAI,MAAM,SAAS,yBAAyB,MAAM,MAAM,SAAS,cAAc;AAC7E,kBAAM,EAAE,MAAM,MAAM,MAAM,QAAQ,IAAI,UAAU,MAAM;AACtD;AAAA,UACF;AAEA,cAAI,MAAM,SAAS,iBAAiB;AAClC,kBAAM,QAAQ,MAAM,QAChB;AAAA,cACE;AAAA,cACA,cAAc,MAAM,MAAM;AAAA,cAC1B,aAAa,cAAc,MAAM,MAAM;AAAA,cACvC;AAAA,cACA;AAAA,YACF,IACA;AAEJ,gBAAI,MAAM,MAAM,eAAe,OAAO;AACpC,oBAAM;AAAA,gBACJ,MAAM;AAAA,gBACN,cAAc,MAAM,MAAM,eAAe;AAAA,gBACzC;AAAA,gBACA,UAAU;AAAA,cACZ;AAAA,YACF;AACA;AAAA,UACF;AAEA,cAAI,MAAM,SAAS,gBAAgB;AACjC,kBAAM,EAAE,MAAM,IAAI,cAAc,QAAQ,UAAU,MAAM;AAAA,UAC1D;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAyBA,MAAM,YACJ,UACA,YACA,OACiB;AACjB,cAAM,SAAS,KAAK;AAGpB,cAAM,iBAAiB,SAAS,OAAO,CAAC,YAAY,QAAQ,SAAS,QAAQ;AAC7E,cAAM,SACJ,eAAe,SAAS,IACpB,eAAe,IAAI,CAAC,MAAM,mBAAmB,EAAE,OAAO,CAAC,EAAE,KAAK,MAAM,IACpE;AAGN,cAAM,eAAe,SAClB;AAAA,UACC,CAAC,YACC,QAAQ,SAAS;AAAA,QACrB,EACC,IAAI,CAAC,aAAa;AAAA,UACjB,MAAM,QAAQ;AAAA,UACd,SAAS,KAAK,0BAA0B,QAAQ,SAAS,KAAK;AAAA,QAChE,EAAE;AAEJ,YAAI;AAEF,gBAAM,WAAW,MAAM,OAAO,SAAS,YAAY;AAAA,YACjD,OAAO,WAAW;AAAA,YAClB,UAAU;AAAA,YACV,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,UAC7B,CAAC;AAED,iBAAO,SAAS;AAAA,QAClB,SAAS,OAAO;AAEd,kBAAQ;AAAA,YACN,6BAA6B,WAAW,IAAI;AAAA,YAC5C;AAAA,UACF;AAGA,cAAI,aAAa;AACjB,cAAI,aAAa;AACjB,qBAAW,OAAO,UAAU;AAC1B,kBAAM,QAAQ,wBAAwB,IAAI,OAAO;AACjD,uBAAW,QAAQ,OAAO;AACxB,kBAAI,KAAK,SAAS,QAAQ;AACxB,8BAAc,KAAK,KAAK;AAAA,cAC1B,WAAW,KAAK,SAAS,SAAS;AAChC;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAIA,iBAAO,KAAK,KAAK,aAAa,wBAAwB,IAAI,aAAa;AAAA,QACzE;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACjKO,SAAS,wBAAwB,SAA6C;AACnF,SAAO,kBAAkB,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAC5D;AAKO,SAAS,mBAAmB,SAA0B;AAC3D,SAAO,kBAAkB,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAC5D;AAUO,SAAS,yBAAyB,SAAiB,OAAO,OAAO,IAAI,GAAuB;AACjG,QAAM,OAAO,wBAAwB,OAAO;AAC5C,MAAI,CAAC,KAAM,QAAO;AAGlB,MAAI,KAAK,QAAQ,aAAa,QAAW;AACvC,WAAO,KAAK,QAAQ,WAAW;AAAA,EACjC;AAGA,MAAI,KAAK,QAAQ,QAAQ;AACvB,UAAM,YAAY,KAAK,QAAQ,OAAO,IAAI;AAC1C,QAAI,OAAO,cAAc,UAAU;AACjC,aAAO,YAAY;AAAA,IACrB;AAAA,EACF;AAEA,SAAO;AACT;AAzNA,IAqBa,uBAIA,4BAKA;AA9Bb;AAAA;AAAA;AAqBO,IAAM,wBAAwB,CAAC,OAAO,OAAO,OAAO,QAAQ,MAAM;AAIlE,IAAM,6BAA6B,CAAC,OAAO,OAAO,OAAO,QAAQ,MAAM;AAKvE,IAAM,oBAAsC;AAAA;AAAA,MAEjD;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,QACA,gBAAgB,CAAC,GAAG,qBAAqB;AAAA,QACzC,WAAW;AAAA,QACX,aAAa;AAAA,QACb,UAAU;AAAA,UACR,eAAe;AAAA,QACjB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,QACA,gBAAgB,CAAC,GAAG,qBAAqB;AAAA,QACzC,WAAW;AAAA,QACX,aAAa;AAAA,QACb,UAAU;AAAA,UACR,eAAe;AAAA,QACjB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,QACA,gBAAgB,CAAC,GAAG,qBAAqB;AAAA,QACzC,WAAW;AAAA,QACX,aAAa;AAAA,QACb,UAAU;AAAA,UACR,eAAe;AAAA,QACjB;AAAA,MACF;AAAA;AAAA,MAEA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,QACA,gBAAgB,CAAC,GAAG,qBAAqB;AAAA,QACzC,WAAW;AAAA,QACX,aAAa;AAAA,QACb,UAAU;AAAA,UACR,eAAe;AAAA,QACjB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,QACA,gBAAgB,CAAC,GAAG,qBAAqB;AAAA,QACzC,WAAW;AAAA,QACX,aAAa;AAAA,QACb,UAAU;AAAA,UACR,eAAe;AAAA,QACjB;AAAA,MACF;AAAA;AAAA,MAEA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,QACA,gBAAgB,CAAC,GAAG,0BAA0B;AAAA,QAC9C,WAAW;AAAA,QACX,aAAa;AAAA,QACb,UAAU;AAAA,UACR,gBAAgB;AAAA,UAChB,eAAe;AAAA,QACjB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,QACA,gBAAgB,CAAC,GAAG,0BAA0B;AAAA,QAC9C,WAAW;AAAA,QACX,aAAa;AAAA,QACb,UAAU;AAAA,UACR,gBAAgB;AAAA,UAChB,eAAe;AAAA,QACjB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA;AAAA;AAAA,UAGP,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,UACR;AAAA,QACF;AAAA,QACA,gBAAgB,CAAC,MAAM,MAAM,IAAI;AAAA,QACjC,WAAW;AAAA,QACX,aAAa;AAAA,QACb,UAAU;AAAA,UACR,gBAAgB;AAAA,UAChB,eAAe;AAAA,QACjB;AAAA,MACF;AAAA;AAAA,MAEA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,UACR;AAAA,QACF;AAAA,QACA,gBAAgB,CAAC,MAAM,MAAM,IAAI;AAAA,QACjC,WAAW;AAAA,QACX,aAAa;AAAA,QACb,UAAU;AAAA,UACR,gBAAgB;AAAA,UAChB,eAAe;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC/KA,IAYa;AAZb;AAAA;AAAA;AAYO,IAAM,gBAA6B;AAAA;AAAA,MAExC;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA;AAAA,UACP,QAAQ;AAAA;AAAA,UACR,aAAa;AAAA;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OACE;AAAA,QACJ;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA;AAAA,UACP,QAAQ;AAAA;AAAA,UACR,aAAa;AAAA;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA;AAAA,QAEV;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACjFO,SAAS,yBAAyB,SAA8C;AACrF,SAAO,mBAAmB,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAC7D;AAKO,SAAS,oBAAoB,SAA0B;AAC5D,SAAO,mBAAmB,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAC7D;AAYO,SAAS,0BACd,SACA,gBACA,kBACoB;AACpB,QAAM,OAAO,yBAAyB,OAAO;AAC7C,MAAI,CAAC,KAAM,QAAO;AAGlB,MAAI,KAAK,QAAQ,cAAc,QAAW;AACxC,QAAI,qBAAqB,QAAW;AAClC,aAAO,mBAAmB,KAAK,QAAQ;AAAA,IACzC;AAGA,UAAM,gBAAgB,iBAAiB;AACvC,WAAO,gBAAgB,KAAK,QAAQ;AAAA,EACtC;AAEA,SAAO;AACT;AA7JA,IAuBa,mBAoCA,oBAKA;AAhEb;AAAA;AAAA;AAuBO,IAAM,oBAAoB;AAAA,MAC/B;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,IACF;AAKO,IAAM,qBAAoC,CAAC,OAAO,KAAK;AAKvD,IAAM,qBAAwC;AAAA,MACnD;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA;AAAA,UAEP,eAAe;AAAA;AAAA,UAEf,qBAAqB;AAAA;AAAA,UAErB,WAAW;AAAA,QACb;AAAA,QACA,QAAQ,CAAC,GAAG,iBAAiB;AAAA,QAC7B,SAAS;AAAA,QACT,gBAAgB;AAAA;AAAA,QAChB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU;AAAA,UACR,cAAc;AAAA,UACd,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA;AAAA,UAEP,eAAe;AAAA;AAAA,UAEf,qBAAqB;AAAA;AAAA,UAErB,WAAW;AAAA,QACb;AAAA,QACA,QAAQ,CAAC,GAAG,iBAAiB;AAAA,QAC7B,SAAS;AAAA,QACT,gBAAgB;AAAA;AAAA,QAChB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU;AAAA,UACR,cAAc;AAAA,UACd,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC/BA,SAAS,aACP,SACA,YACA,eACA,aACa;AACb,QAAM,WAAY,aAAa,cAAc,gBAAiB;AAC9D,QAAM,aAAc,cAAc,gBAAiB;AACnD,QAAM,WAAW,QAAQ;AACzB,QAAM,aAAa;AACnB,QAAM,WAAW,aAAa,WAAW;AAEzC,QAAM,SAAS,IAAI,YAAY,aAAa,QAAQ;AACpD,QAAM,OAAO,IAAI,SAAS,MAAM;AAChC,QAAM,QAAQ,IAAI,WAAW,MAAM;AAGnC,OAAK,UAAU,GAAG,YAAY,KAAK;AACnC,OAAK,UAAU,GAAG,UAAU,IAAI;AAChC,OAAK,UAAU,GAAG,YAAY,KAAK;AAGnC,OAAK,UAAU,IAAI,YAAY,KAAK;AACpC,OAAK,UAAU,IAAI,IAAI,IAAI;AAC3B,OAAK,UAAU,IAAI,GAAG,IAAI;AAC1B,OAAK,UAAU,IAAI,aAAa,IAAI;AACpC,OAAK,UAAU,IAAI,YAAY,IAAI;AACnC,OAAK,UAAU,IAAI,UAAU,IAAI;AACjC,OAAK,UAAU,IAAI,YAAY,IAAI;AACnC,OAAK,UAAU,IAAI,eAAe,IAAI;AAGtC,OAAK,UAAU,IAAI,YAAY,KAAK;AACpC,OAAK,UAAU,IAAI,UAAU,IAAI;AAGjC,QAAM,IAAI,SAAS,UAAU;AAE7B,SAAO;AACT;AAufO,SAAS,8BAA+D;AAC7E,SAAO,sBAAsB,kBAAkB,0BAAa,wBAAwB;AACtF;AAhnBA,kBA4DM,iBA6DO;AAzHb;AAAA;AAAA;AAAA,mBAAiE;AAWjE;AAGA;AACA,IAAAC;AACA;AAMA;AACA;AAMA;AA+BA,IAAM,kBAAgE;AAAA,MACpE,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,WAAW;AAAA,IACb;AAyDO,IAAM,2BAAN,cAAuC,oBAAoB;AAAA,MACvD,aAAa;AAAA,MAEtB,SAAS,YAAsC;AAC7C,eAAO,WAAW,aAAa,KAAK;AAAA,MACtC;AAAA,MAEA,gBAAgB;AACd,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAMA,qBAAuC;AACrC,eAAO;AAAA,MACT;AAAA,MAEA,wBAAwB,SAA0B;AAChD,eAAO,mBAAmB,OAAO;AAAA,MACnC;AAAA,MAEA,MAAM,cAAc,SAAiE;AACnF,cAAM,SAAS,KAAK;AACpB,cAAM,OAAO,wBAAwB,QAAQ,KAAK;AAClD,cAAM,gBAAgB,QAAQ,MAAM,WAAW,QAAQ;AAEvD,cAAM,cAAc,QAAQ,QAAQ,MAAM,eAAe;AACzD,cAAM,IAAI,QAAQ,KAAK;AAEvB,YAAI,eAAe;AAKjB,gBAAMC,YAAW,MAAM,OAAO,OAAO,eAAe;AAAA,YAClD,OAAO,QAAQ;AAAA,YACf,QAAQ,QAAQ;AAAA,YAChB,QAAQ;AAAA,cACN,gBAAgB;AAAA,cAChB;AAAA,cACA,gBAAgB,QAAQ,mBAAmB,aAAa,cAAc;AAAA,YACxE;AAAA,UACF,CAAC;AAED,gBAAMC,UAASD,UAAS,mBAAmB,CAAC;AAC5C,gBAAME,QAAO,yBAAyB,QAAQ,OAAO,aAAaD,QAAO,MAAM;AAE/E,iBAAO;AAAA;AAAA,YAEL,QAAQA,QAAO,IAAI,CAAC,SAAS;AAAA,cAC3B,SAAS,IAAI,OAAO,cAAc;AAAA,YACpC,EAAE;AAAA,YACF,OAAO,QAAQ;AAAA,YACf,OAAO;AAAA,cACL,iBAAiBA,QAAO;AAAA,cACxB,MAAM;AAAA,cACN,SAAS;AAAA,YACX;AAAA,YACA,MAAAC;AAAA,UACF;AAAA,QACF;AAEA,cAAM,WAAW,MAAM,OAAO,OAAO,gBAAgB;AAAA,UACnD,OAAO,QAAQ;AAAA,UACf,UAAU,CAAC,EAAE,MAAM,QAAQ,OAAO,CAAC,EAAE,MAAM,QAAQ,OAAO,CAAC,EAAE,CAAC;AAAA,UAC9D,QAAQ;AAAA,YACN,oBAAoB,CAAC,sBAAS,OAAO,sBAAS,IAAI;AAAA,UACpD;AAAA,QACF,CAAC;AAGD,cAAM,SAAoD,CAAC;AAC3D,cAAM,YAAY,SAAS,aAAa,CAAC;AACzC,YAAI,WAAW,SAAS,OAAO;AAC7B,qBAAW,QAAQ,UAAU,QAAQ,OAAO;AAC1C,gBAAI,gBAAgB,QAAQ,KAAK,YAAY;AAC3C,qBAAO,KAAK;AAAA,gBACV,SAAS,KAAK,WAAW;AAAA,cAC3B,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAEA,cAAM,OAAO,yBAAyB,QAAQ,OAAO,aAAa,OAAO,MAAM;AAE/E,eAAO;AAAA,UACL;AAAA,UACA,OAAO,QAAQ;AAAA,UACf,OAAO;AAAA,YACL,iBAAiB,OAAO;AAAA,YACxB,MAAM;AAAA,YACN,SAAS;AAAA,UACX;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAMA,sBAAyC;AACvC,eAAO;AAAA,MACT;AAAA,MAEA,yBAAyB,SAA0B;AACjD,eAAO,oBAAoB,OAAO;AAAA,MACpC;AAAA,MAEA,MAAM,eAAe,SAAmE;AACtF,cAAM,SAAS,KAAK;AACpB,cAAM,OAAO,yBAAyB,QAAQ,KAAK;AAEnD,cAAM,QAAQ,QAAQ,SAAS,MAAM,gBAAgB;AAGrD,cAAM,WAAW,MAAM,OAAO,OAAO,gBAAgB;AAAA,UACnD,OAAO,QAAQ;AAAA,UACf,UAAU;AAAA,YACR;AAAA,cACE,MAAM;AAAA,cACN,OAAO,CAAC,EAAE,MAAM,QAAQ,MAAM,CAAC;AAAA,YACjC;AAAA,UACF;AAAA,UACA,QAAQ;AAAA,YACN,oBAAoB,CAAC,sBAAS,KAAK;AAAA,YACnC,cAAc;AAAA,cACZ,aAAa;AAAA,gBACX,qBAAqB;AAAA,kBACnB,WAAW;AAAA,gBACb;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF,CAAC;AAGD,YAAI;AACJ,cAAM,YAAY,SAAS,aAAa,CAAC;AACzC,YAAI,WAAW,SAAS,OAAO;AAC7B,qBAAW,QAAQ,UAAU,QAAQ,OAAO;AAC1C,gBAAI,gBAAgB,QAAQ,KAAK,YAAY,MAAM;AAEjD,oBAAM,SAAS,KAAK,WAAW;AAC/B,oBAAM,SAAS,KAAK,MAAM;AAC1B,wBAAU,IAAI,WAAW,OAAO,MAAM;AACtC,uBAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,wBAAQ,CAAC,IAAI,OAAO,WAAW,CAAC;AAAA,cAClC;AACA;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,YAAI,CAAC,SAAS;AACZ,gBAAM,IAAI,MAAM,sCAAsC;AAAA,QACxD;AAGA,cAAM,YAAY,aAAa,SAAS,MAAO,IAAI,CAAC;AAEpD,cAAM,OAAO,0BAA0B,QAAQ,OAAO,QAAQ,MAAM,MAAM;AAE1E,eAAO;AAAA,UACL,OAAO;AAAA,UACP,OAAO,QAAQ;AAAA,UACf,OAAO;AAAA,YACL,gBAAgB,QAAQ,MAAM;AAAA,UAChC;AAAA,UACA;AAAA,UACA,QAAQ,MAAM,iBAAiB;AAAA,QACjC;AAAA,MACF;AAAA,MAEU,gBACR,SACA,YACA,OACA,UAKA;AAEA,cAAM,WAAW,KAAK,0BAA0B,QAAQ;AACxD,cAAM,mBAAmB,KAAK,sBAAsB,OAAO;AAG3D,cAAM,SAAkC;AAAA;AAAA;AAAA,UAGtC,GAAI,mBAAmB,EAAE,GAAG,iBAAiB,IAAI,CAAC;AAAA;AAAA,UAElD,YAAY;AAAA,YACV,uBAAuB;AAAA,cACrB,MAAM,uCAA0B;AAAA,YAClC;AAAA,UACF;AAAA,UACA,GAAG,QAAQ;AAAA,QACb;AAEA,eAAO;AAAA,UACL,OAAO,WAAW;AAAA,UAClB;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MAEA,MAAgB,qBACd,SAKA,QACqC;AACrC,cAAM,SAAS,KAAK;AAEpB,cAAM,iBAAiB,MAAM,OAAO,OAAO,sBAAsB;AAAA,UAC/D,GAAG;AAAA,UACH,QAAQ;AAAA,YACN,GAAG,QAAQ;AAAA,YACX,GAAI,SAAS,EAAE,aAAa,OAAO,IAAI,CAAC;AAAA,UAC1C;AAAA,QACF,CAAC;AACD,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBQ,0BAA0B,UAAyC;AACzE,cAAM,mBAAiF,CAAC;AAExF,mBAAW,WAAW,UAAU;AAC9B,cAAI,QAAQ,SAAS,UAAU;AAG7B,6BAAiB,KAAK;AAAA,cACpB,MAAM;AAAA,cACN,SAAS,mBAAmB,QAAQ,OAAO;AAAA,YAC7C,CAAC;AACD,6BAAiB,KAAK;AAAA,cACpB,MAAM;AAAA,cACN,SAAS;AAAA,YACX,CAAC;AAAA,UACH,OAAO;AACL,6BAAiB,KAAK;AAAA,cACpB,MAAM,QAAQ;AAAA,cACd,SAAS,QAAQ;AAAA,YACnB,CAAC;AAAA,UACH;AAAA,QACF;AAEA,eAAO,KAAK,yBAAyB,gBAAgB;AAAA,MACvD;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,yBACN,UACiB;AACjB,YAAI,SAAS,WAAW,GAAG;AACzB,iBAAO,CAAC;AAAA,QACV;AAEA,cAAM,SAA0B,CAAC;AACjC,YAAI,eAAqC;AAEzC,mBAAW,WAAW,UAAU;AAC9B,gBAAM,aAAa,gBAAgB,QAAQ,IAAI;AAC/C,gBAAM,cAAc,KAAK,qBAAqB,QAAQ,OAAO;AAE7D,cAAI,gBAAgB,aAAa,SAAS,YAAY;AAEpD,yBAAa,MAAM,KAAK,GAAG,WAAW;AAAA,UACxC,OAAO;AAEL,gBAAI,cAAc;AAChB,qBAAO,KAAK,YAAY;AAAA,YAC1B;AACA,2BAAe;AAAA,cACb,MAAM;AAAA,cACN,OAAO;AAAA,YACT;AAAA,UACF;AAAA,QACF;AAGA,YAAI,cAAc;AAChB,iBAAO,KAAK,YAAY;AAAA,QAC1B;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,qBAAqB,SAAuC;AAClE,cAAM,QAAQ,wBAAwB,OAAO;AAE7C,eAAO,MAAM,IAAI,CAAC,SAAS;AACzB,cAAI,KAAK,SAAS,QAAQ;AACxB,mBAAO,EAAE,MAAM,KAAK,KAAK;AAAA,UAC3B;AAEA,cAAI,KAAK,SAAS,SAAS;AACzB,gBAAI,KAAK,OAAO,SAAS,OAAO;AAC9B,oBAAM,IAAI;AAAA,gBACR;AAAA,cACF;AAAA,YACF;AACA,mBAAO;AAAA,cACL,YAAY;AAAA,gBACV,UAAU,KAAK,OAAO;AAAA,gBACtB,MAAM,KAAK,OAAO;AAAA,cACpB;AAAA,YACF;AAAA,UACF;AAEA,cAAI,KAAK,SAAS,SAAS;AACzB,mBAAO;AAAA,cACL,YAAY;AAAA,gBACV,UAAU,KAAK,OAAO;AAAA,gBACtB,MAAM,KAAK,OAAO;AAAA,cACpB;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,IAAI,MAAM,6BAA8B,KAAqB,IAAI,EAAE;AAAA,QAC3E,CAAC;AAAA,MACH;AAAA,MAEQ,sBAAsB,SAA+B;AAC3D,cAAM,SAAkC,CAAC;AAIzC,YAAI,OAAO,QAAQ,cAAc,UAAU;AACzC,iBAAO,kBAAkB,QAAQ;AAAA,QACnC;AAEA,YAAI,OAAO,QAAQ,gBAAgB,UAAU;AAC3C,iBAAO,cAAc,QAAQ;AAAA,QAC/B;AACA,YAAI,OAAO,QAAQ,SAAS,UAAU;AACpC,iBAAO,OAAO,QAAQ;AAAA,QACxB;AACA,YAAI,QAAQ,eAAe,QAAQ;AACjC,iBAAO,gBAAgB,QAAQ;AAAA,QACjC;AAEA,eAAO,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI,SAAS;AAAA,MACnD;AAAA,MAEA,OAAiB,wBAAwB,UAA6C;AACpF,cAAMC,UAAS;AACf,yBAAiB,SAASA,SAAQ;AAChC,gBAAMC,QAAO,KAAK,mBAAmB,KAAK;AAC1C,cAAIA,OAAM;AACR,kBAAM,EAAE,MAAAA,OAAM,UAAU,MAAM;AAAA,UAChC;AAEA,gBAAM,eAAe,KAAK,oBAAoB,KAAK;AACnD,gBAAM,QAAQ,KAAK,aAAa,KAAK;AAErC,cAAI,gBAAgB,OAAO;AACzB,kBAAM,EAAE,MAAM,IAAI,cAAc,OAAO,UAAU,MAAM;AAAA,UACzD;AAAA,QACF;AAAA,MACF;AAAA,MAEQ,mBAAmB,OAA4B;AACrD,YAAI,CAAC,OAAO,YAAY;AACtB,iBAAO;AAAA,QACT;AAEA,eAAO,MAAM,WACV,QAAQ,CAAC,cAAc,UAAU,SAAS,SAAS,CAAC,CAAC,EACrD,IAAI,CAAC,SAAS,KAAK,QAAQ,EAAE,EAC7B,KAAK,EAAE;AAAA,MACZ;AAAA,MAEQ,oBAAoB,OAAmC;AAC7D,cAAM,YAAY,OAAO,YAAY,KAAK,CAAC,SAAS,KAAK,YAAY;AACrE,eAAO,WAAW,gBAAgB;AAAA,MACpC;AAAA,MAEQ,aACN,OAGY;AACZ,cAAM,gBAAgB,OAAO;AAC7B,YAAI,CAAC,eAAe;AAClB,iBAAO;AAAA,QACT;AAEA,eAAO;AAAA,UACL,aAAa,cAAc,oBAAoB;AAAA,UAC/C,cAAc,cAAc,wBAAwB;AAAA,UACpD,aAAa,cAAc,mBAAmB;AAAA;AAAA,UAE9C,mBAAmB,cAAc,2BAA2B;AAAA,QAC9D;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAyBA,MAAM,YACJ,UACA,YACA,OACiB;AACjB,cAAM,SAAS,KAAK;AAIpB,cAAM,WAAW,KAAK,0BAA0B,QAAQ;AAGxD,YAAI,CAAC,YAAY,SAAS,WAAW,GAAG;AACtC,iBAAO;AAAA,QACT;AAEA,YAAI;AAEF,gBAAM,WAAW,MAAM,OAAO,OAAO,YAAY;AAAA,YAC/C,OAAO,WAAW;AAAA,YAClB;AAAA;AAAA;AAAA,UAGF,CAAC;AACD,iBAAO,SAAS,eAAe;AAAA,QACjC,SAAS,OAAO;AAEd,kBAAQ;AAAA,YACN,6BAA6B,WAAW,IAAI;AAAA,YAC5C;AAAA,UACF;AAGA,cAAI,aAAa;AACjB,cAAI,aAAa;AACjB,qBAAW,OAAO,UAAU;AAC1B,kBAAM,QAAQ,wBAAwB,IAAI,OAAO;AACjD,uBAAW,QAAQ,OAAO;AACxB,kBAAI,KAAK,SAAS,QAAQ;AACxB,8BAAc,KAAK,KAAK;AAAA,cAC1B,WAAW,KAAK,SAAS,WAAW,KAAK,SAAS,SAAS;AACzD;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAIA,iBAAO,KAAK,KAAK,aAAa,wBAAwB,IAAI,aAAa;AAAA,QACzE;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACnZO,SAAS,wBAAwB,SAA6C;AACnF,SAAO,kBAAkB,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAC5D;AAKO,SAAS,mBAAmB,SAA0B;AAC3D,SAAO,kBAAkB,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAC5D;AAWO,SAAS,yBACd,SACA,MACA,UAAU,YACV,IAAI,GACgB;AACpB,QAAM,OAAO,wBAAwB,OAAO;AAC5C,MAAI,CAAC,KAAM,QAAO;AAGlB,QAAM,YAAY,KAAK,QAAQ,SAAS,IAAI;AAC5C,MAAI,cAAc,OAAW,QAAO;AAEpC,MAAI;AAEJ,MAAI,OAAO,cAAc,UAAU;AAEjC,oBAAgB;AAAA,EAClB,OAAO;AAEL,oBAAgB,UAAU,OAAO;AACjC,QAAI,kBAAkB,OAAW,QAAO;AAAA,EAC1C;AAEA,SAAO,gBAAgB;AACzB;AAtQA,IAwCa,iBAIA,qBAQA,cAIA,kBAIA,cAMA;AAlEb;AAAA;AAAA;AAwCO,IAAM,kBAAkB,CAAC,aAAa,aAAa,aAAa,aAAa,MAAM;AAInF,IAAM,sBAAsB,CAAC,OAAO,UAAU,MAAM;AAQpD,IAAM,eAAe,CAAC,aAAa,aAAa,WAAW;AAI3D,IAAM,mBAAmB,CAAC,YAAY,IAAI;AAI1C,IAAM,eAAe,CAAC,WAAW,WAAW,WAAW;AAMvD,IAAM,oBAAsC;AAAA;AAAA,MAEjD;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,QAAQ;AAAA,YACN,aAAa,EAAE,KAAK,MAAO,QAAQ,MAAM,MAAM,KAAK;AAAA,YACpD,aAAa,EAAE,KAAK,OAAO,QAAQ,OAAO,MAAM,MAAM;AAAA,YACtD,aAAa,EAAE,KAAK,OAAO,QAAQ,OAAO,MAAM,MAAM;AAAA,YACtD,aAAa,EAAE,KAAK,OAAO,QAAQ,MAAM,MAAM,KAAK;AAAA,UACtD;AAAA,QACF;AAAA,QACA,gBAAgB,CAAC,GAAG,eAAe;AAAA,QACnC,oBAAoB,CAAC,GAAG,mBAAmB;AAAA,QAC3C,WAAW;AAAA,QACX,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,UAAU;AAAA,UACR,eAAe;AAAA,UACf,cAAc;AAAA,UACd,SAAS;AAAA,QACX;AAAA,MACF;AAAA;AAAA,MAEA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,QAAQ;AAAA,YACN,aAAa,EAAE,KAAK,OAAO,QAAQ,MAAM,MAAM,KAAK;AAAA,YACpD,aAAa,EAAE,KAAK,OAAO,QAAQ,MAAM,MAAM,KAAK;AAAA,YACpD,aAAa,EAAE,KAAK,OAAO,QAAQ,MAAM,MAAM,KAAK;AAAA,UACtD;AAAA,QACF;AAAA,QACA,gBAAgB,CAAC,aAAa,aAAa,WAAW;AAAA,QACtD,oBAAoB,CAAC,GAAG,mBAAmB;AAAA,QAC3C,WAAW;AAAA,QACX,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,UAAU;AAAA,UACR,eAAe;AAAA,UACf,cAAc;AAAA,QAChB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,QAAQ;AAAA,YACN,aAAa,EAAE,KAAK,MAAO,QAAQ,MAAM,MAAM,MAAM;AAAA,YACrD,aAAa,EAAE,KAAK,OAAQ,QAAQ,MAAM,MAAM,MAAM;AAAA,YACtD,aAAa,EAAE,KAAK,OAAQ,QAAQ,MAAM,MAAM,MAAM;AAAA,UACxD;AAAA,QACF;AAAA,QACA,gBAAgB,CAAC,aAAa,aAAa,WAAW;AAAA,QACtD,oBAAoB,CAAC,GAAG,mBAAmB;AAAA,QAC3C,WAAW;AAAA,QACX,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,UAAU;AAAA,UACR,eAAe;AAAA,UACf,cAAc;AAAA,QAChB;AAAA,MACF;AAAA;AAAA,MAEA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,QAAQ;AAAA,YACN,aAAa,EAAE,UAAU,KAAK,MAAM,EAAI;AAAA,YACxC,aAAa,EAAE,UAAU,KAAK,MAAM,EAAI;AAAA,YACxC,aAAa,EAAE,UAAU,KAAK,MAAM,IAAI;AAAA,UAC1C;AAAA,QACF;AAAA,QACA,gBAAgB,CAAC,aAAa,aAAa,WAAW;AAAA,QACtD,oBAAoB,CAAC,YAAY,MAAM;AAAA,QACvC,WAAW;AAAA,QACX,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,UAAU;AAAA,UACR,iBAAiB;AAAA,QACnB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,QAAQ;AAAA,YACN,aAAa,EAAE,UAAU,GAAK,MAAM,EAAI;AAAA,YACxC,aAAa,EAAE,UAAU,GAAK,MAAM,EAAI;AAAA,YACxC,aAAa,EAAE,UAAU,KAAK,MAAM,IAAI;AAAA,UAC1C;AAAA,QACF;AAAA,QACA,gBAAgB,CAAC,aAAa,aAAa,WAAW;AAAA,QACtD,oBAAoB,CAAC,YAAY,MAAM;AAAA,QACvC,WAAW;AAAA,QACX,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,UAAU;AAAA,UACR,iBAAiB;AAAA,UACjB,kBAAkB;AAAA,QACpB;AAAA,MACF;AAAA;AAAA,MAEA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,QAAQ;AAAA,YACN,aAAa,EAAE,UAAU,MAAM,IAAI,KAAK;AAAA,YACxC,aAAa,EAAE,UAAU,MAAM,IAAI,KAAK;AAAA,YACxC,aAAa,EAAE,UAAU,MAAM,IAAI,KAAK;AAAA,UAC1C;AAAA,QACF;AAAA,QACA,gBAAgB,CAAC,GAAG,YAAY;AAAA,QAChC,oBAAoB,CAAC,GAAG,gBAAgB;AAAA,QACxC,WAAW;AAAA;AAAA,QACX,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,UAAU;AAAA,UACR,eAAe;AAAA,QACjB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,QAAQ;AAAA,YACN,WAAW;AAAA,YACX,WAAW;AAAA,YACX,aAAa;AAAA,UACf;AAAA,QACF;AAAA,QACA,gBAAgB,CAAC,GAAG,YAAY;AAAA,QAChC,WAAW;AAAA,QACX,aAAa;AAAA,MACf;AAAA,IACF;AAAA;AAAA;;;ACpNA,IAYa;AAZb;AAAA;AAAA;AAYO,IAAM,gBAA6B;AAAA;AAAA,MAExC;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,QACV;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,mBAAmB;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,mBAAmB;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA;AAAA,QAEV;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,mBAAmB;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,mBAAmB;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,mBAAmB;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,mBAAmB;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,mBAAmB;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA;AAAA,MAGA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,QACV;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,UACnB,YAAY;AAAA,QACd;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,SAAS;AAAA,UACP,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,QACf;AAAA,QACA,iBAAiB;AAAA,QACjB,UAAU;AAAA,UACR,WAAW;AAAA,UACX,iBAAiB;AAAA,UACjB,QAAQ;AAAA,UACR,WAAW;AAAA,UACX,mBAAmB;AAAA,QACrB;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,qBAAqB;AAAA,QACvB;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC3YO,SAAS,yBAAyB,SAA8C;AACrF,SAAO,mBAAmB,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAC7D;AAKO,SAAS,oBAAoB,SAA0B;AAC5D,SAAO,mBAAmB,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAC7D;AAaO,SAAS,0BACd,SACA,gBACA,kBACoB;AACpB,QAAM,OAAO,yBAAyB,OAAO;AAC7C,MAAI,CAAC,KAAM,QAAO;AAGlB,MAAI,KAAK,QAAQ,iBAAiB,QAAW;AAC3C,WAAO,iBAAiB,KAAK,QAAQ;AAAA,EACvC;AAGA,MAAI,KAAK,QAAQ,cAAc,UAAa,qBAAqB,QAAW;AAC1E,WAAO,mBAAmB,KAAK,QAAQ;AAAA,EACzC;AAIA,MAAI,KAAK,QAAQ,cAAc,QAAW;AACxC,UAAM,gBAAgB,iBAAiB;AACvC,WAAO,gBAAgB,KAAK,QAAQ;AAAA,EACtC;AAEA,SAAO;AACT;AAlLA,IAca,mBAGA,4BAaA,oBAKA;AAnCb;AAAA;AAAA;AAcO,IAAM,oBAAoB,CAAC,SAAS,QAAQ,SAAS,QAAQ,QAAQ,SAAS;AAG9E,IAAM,6BAA6B;AAAA,MACxC,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAMO,IAAM,qBAAoC,CAAC,OAAO,QAAQ,OAAO,QAAQ,OAAO,KAAK;AAKrF,IAAM,qBAAwC;AAAA;AAAA,MAEnD;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA;AAAA,UAEP,cAAc;AAAA,QAChB;AAAA,QACA,QAAQ,CAAC,GAAG,iBAAiB;AAAA,QAC7B,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU;AAAA,UACR,mBAAmB;AAAA,QACrB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,cAAc;AAAA,QAChB;AAAA,QACA,QAAQ,CAAC,GAAG,iBAAiB;AAAA,QAC7B,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU;AAAA,UACR,mBAAmB;AAAA,QACrB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA;AAAA,UAEP,cAAc;AAAA,QAChB;AAAA,QACA,QAAQ,CAAC,GAAG,iBAAiB;AAAA,QAC7B,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU;AAAA,UACR,mBAAmB;AAAA,QACrB;AAAA,MACF;AAAA,MACA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA,UACP,cAAc;AAAA,QAChB;AAAA,QACA,QAAQ,CAAC,GAAG,iBAAiB;AAAA,QAC7B,SAAS;AAAA,QACT,gBAAgB;AAAA,QAChB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU;AAAA,UACR,mBAAmB;AAAA,QACrB;AAAA,MACF;AAAA;AAAA,MAEA;AAAA,QACE,UAAU;AAAA,QACV,SAAS;AAAA,QACT,aAAa;AAAA,QACb,SAAS;AAAA;AAAA,UAEP,eAAe;AAAA;AAAA,UAEf,qBAAqB;AAAA;AAAA,UAErB,WAAW;AAAA,QACb;AAAA,QACA,QAAQ,CAAC,GAAG,0BAA0B;AAAA,QACtC,SAAS;AAAA,QACT,gBAAgB;AAAA;AAAA,QAChB,cAAc;AAAA,QACd,eAAe;AAAA,QACf,UAAU;AAAA,UACR,mBAAmB;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC1EA,SAAS,cACP,OACA,kBACqC;AACrC,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,MAAI,oBAAoB,CAAC,OAAO,OAAO,OAAO,aAAa,GAAG;AAC5D,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,QAAQ,aAAa,CAAC;AAC1F;AA0YO,SAAS,8BAAyD;AACvE,SAAO,sBAAsB,kBAAkB,cAAAC,SAAQ,kBAAkB;AAC3E;AA5cA,mBAMA,iBAoCM,UAwBO;AAlEb;AAAA;AAAA;AAAA,oBAAmB;AAMnB,sBAAuD;AAWvD;AAGA;AACA,IAAAC;AAMA;AAMA;AACA;AAMA;AAEA,IAAM,WAAwE;AAAA,MAC5E,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,WAAW;AAAA,IACb;AAoBO,IAAM,qBAAN,cAAiC,oBAAoB;AAAA,MACjD,aAAa;AAAA,MAEtB,SAAS,YAAsC;AAC7C,eAAO,WAAW,aAAa,KAAK;AAAA,MACtC;AAAA,MAEA,gBAAgB;AACd,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAMA,qBAAuC;AACrC,eAAO;AAAA,MACT;AAAA,MAEA,wBAAwB,SAA0B;AAChD,eAAO,mBAAmB,OAAO;AAAA,MACnC;AAAA,MAEA,MAAM,cAAc,SAAiE;AACnF,cAAM,SAAS,KAAK;AACpB,cAAM,OAAO,wBAAwB,QAAQ,KAAK;AAElD,cAAM,OAAO,QAAQ,QAAQ,MAAM,eAAe;AAClD,cAAM,UAAU,QAAQ,WAAW,MAAM,kBAAkB;AAC3D,cAAM,IAAI,QAAQ,KAAK;AAGvB,cAAM,WAAW,QAAQ,UAAU;AACnC,cAAM,aAAa,QAAQ,MAAM,WAAW,WAAW;AAMvD,cAAM,gBAA8D;AAAA,UAClE,OAAO,QAAQ;AAAA,UACf,QAAQ,QAAQ;AAAA,UAChB;AAAA,UACA;AAAA,QACF;AAGA,YAAI,CAAC,YAAY,CAAC,YAAY;AAC5B,wBAAc,UAAU;AAAA,QAC1B;AAGA,YAAI,YAAY;AAAA,QAKhB,WAAW,CAAC,UAAU;AAEpB,wBAAc,kBAAkB,QAAQ,kBAAkB;AAAA,QAC5D;AAEA,cAAM,WAAW,MAAM,OAAO,OAAO,SAAS,aAAa;AAE3D,cAAM,OAAO,yBAAyB,QAAQ,OAAO,MAAM,SAAS,CAAC;AAErE,cAAM,SAAU,SAA0C,QAAQ,CAAC;AAEnE,eAAO;AAAA,UACL,QAAQ,OAAO,IAAI,CAAC,SAAS;AAAA,YAC3B,KAAK,IAAI;AAAA,YACT,SAAS,IAAI;AAAA,YACb,eAAe,IAAI;AAAA,UACrB,EAAE;AAAA,UACF,OAAO,QAAQ;AAAA,UACf,OAAO;AAAA,YACL,iBAAiB,OAAO;AAAA,YACxB;AAAA,YACA;AAAA,UACF;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAMA,sBAAyC;AACvC,eAAO;AAAA,MACT;AAAA,MAEA,yBAAyB,SAA0B;AACjD,eAAO,oBAAoB,OAAO;AAAA,MACpC;AAAA,MAEA,MAAM,eAAe,SAAmE;AACtF,cAAM,SAAS,KAAK;AACpB,cAAM,OAAO,yBAAyB,QAAQ,KAAK;AAEnD,cAAMC,UAAS,QAAQ,kBAAkB,MAAM,iBAAiB;AAChE,cAAM,QAAQ,QAAQ,SAAS,MAAM,gBAAgB;AAErD,cAAM,WAAW,MAAM,OAAO,MAAM,OAAO,OAAO;AAAA,UAChD,OAAO,QAAQ;AAAA,UACf,OAAO,QAAQ;AAAA,UACf;AAAA,UACA,iBAAiBA;AAAA,UACjB,OAAO,QAAQ,SAAS;AAAA,QAC1B,CAAC;AAED,cAAM,cAAc,MAAM,SAAS,YAAY;AAC/C,cAAM,OAAO,0BAA0B,QAAQ,OAAO,QAAQ,MAAM,MAAM;AAE1E,eAAO;AAAA,UACL,OAAO;AAAA,UACP,OAAO,QAAQ;AAAA,UACf,OAAO;AAAA,YACL,gBAAgB,QAAQ,MAAM;AAAA,UAChC;AAAA,UACA;AAAA,UACA,QAAAA;AAAA,QACF;AAAA,MACF;AAAA,MAEU,gBACR,SACA,YACA,MACA,UACwD;AACxD,cAAM,EAAE,WAAW,aAAa,MAAM,eAAe,MAAM,IAAI;AAG/D,cAAM,sBAAsB,MAAM,UAAU,wBAAwB;AACpE,cAAM,2BAA2B,OAAO,gBAAgB,YAAY;AACpE,cAAM,iBAAiB,cAAc,OAAO,wBAAwB;AAEpE,eAAO;AAAA,UACL,OAAO,WAAW;AAAA,UAClB,UAAU,SAAS,IAAI,CAAC,YAAY,KAAK,uBAAuB,OAAO,CAAC;AAAA;AAAA;AAAA,UAGxE,GAAI,cAAc,SAAY,EAAE,uBAAuB,UAAU,IAAI,CAAC;AAAA,UACtE,OAAO;AAAA,UACP,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,gBAAgB,EAAE,eAAe,KAAK;AAAA,UACtC,GAAI,kBAAkB,CAAC;AAAA,UACvB,GAAI,2BAA2B,EAAE,YAAY,IAAI,CAAC;AAAA,QACpD;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQQ,uBAAuB,SAAiD;AAC9E,cAAM,OAAO,SAAS,QAAQ,IAAI;AAGlC,YAAI,SAAS,QAAQ;AACnB,gBAAM,UAAU,KAAK,uBAAuB,QAAQ,OAAO;AAC3D,iBAAO;AAAA,YACL,MAAM;AAAA,YACN;AAAA,YACA,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,UAC/C;AAAA,QACF;AAGA,cAAM,cACJ,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,mBAAmB,QAAQ,OAAO;AAE5F,YAAI,SAAS,UAAU;AACrB,iBAAO;AAAA,YACL,MAAM;AAAA,YACN,SAAS;AAAA,YACT,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,UAC/C;AAAA,QACF;AAGA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,UACT,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,QAC/C;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,uBAAuB,SAA+D;AAE5F,YAAI,OAAO,YAAY,UAAU;AAC/B,iBAAO;AAAA,QACT;AAGA,eAAO,QAAQ,IAAI,CAAC,SAAS;AAC3B,cAAI,KAAK,SAAS,QAAQ;AACxB,mBAAO,EAAE,MAAM,QAAiB,MAAM,KAAK,KAAK;AAAA,UAClD;AAEA,cAAI,KAAK,SAAS,SAAS;AACzB,mBAAO,KAAK,iBAAiB,IAAI;AAAA,UACnC;AAEA,cAAI,KAAK,SAAS,SAAS;AACzB,kBAAM,IAAI;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,IAAI,MAAM,6BAA8B,KAAqB,IAAI,EAAE;AAAA,QAC3E,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,iBAAiB,MAAmD;AAC1E,YAAI,KAAK,OAAO,SAAS,OAAO;AAC9B,iBAAO;AAAA,YACL,MAAM;AAAA,YACN,WAAW,EAAE,KAAK,KAAK,OAAO,IAAI;AAAA,UACpC;AAAA,QACF;AAGA,eAAO;AAAA,UACL,MAAM;AAAA,UACN,WAAW;AAAA,YACT,KAAK,QAAQ,KAAK,OAAO,SAAS,WAAW,KAAK,OAAO,IAAI;AAAA,UAC/D;AAAA,QACF;AAAA,MACF;AAAA,MAEA,MAAgB,qBACd,SACA,QAC6C;AAC7C,cAAM,SAAS,KAAK;AAEpB,cAAMC,UAAS,MAAM,OAAO,KAAK,YAAY,OAAO,SAAS,SAAS,EAAE,OAAO,IAAI,MAAS;AAC5F,eAAOA;AAAA,MACT;AAAA,MAEA,OAAiB,wBAAwB,UAA6C;AACpF,cAAMA,UAAS;AACf,yBAAiB,SAASA,SAAQ;AAChC,gBAAMC,QAAO,MAAM,QAAQ,IAAI,CAAC,WAAW,OAAO,OAAO,WAAW,EAAE,EAAE,KAAK,EAAE;AAC/E,cAAIA,OAAM;AACR,kBAAM,EAAE,MAAAA,OAAM,UAAU,MAAM;AAAA,UAChC;AAEA,gBAAM,eAAe,MAAM,QAAQ,KAAK,CAAC,WAAW,OAAO,aAAa,GAAG;AAI3E,gBAAM,QAAQ,MAAM,QAChB;AAAA,YACE,aAAa,MAAM,MAAM;AAAA,YACzB,cAAc,MAAM,MAAM;AAAA,YAC1B,aAAa,MAAM,MAAM;AAAA,YACzB,mBACG,MAAM,MACJ,uBAAuB,iBAAiB;AAAA,UAC/C,IACA;AAEJ,cAAI,gBAAgB,OAAO;AACzB,kBAAM,EAAE,MAAM,IAAI,cAAc,OAAO,UAAU,MAAM;AAAA,UACzD;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAyBA,MAAM,YACJ,UACA,YACA,OACiB;AACjB,YAAI;AAGF,gBAAM,YAAY,WAAW;AAC7B,cAAI;AAEJ,cAAI;AACF,2BAAW,oCAAmB,SAAS;AAAA,UACzC,QAAQ;AAEN,2BAAW,oCAAmB,QAAQ;AAAA,UACxC;AAEA,cAAI;AACF,gBAAI,aAAa;AACjB,gBAAI,aAAa;AAMjB,uBAAW,WAAW,UAAU;AAE9B,4BAAc;AAEd,oBAAM,WAAW,SAAS,QAAQ,IAAI;AACtC,4BAAc,SAAS,OAAO,QAAQ,EAAE;AAGxC,oBAAM,cAAc,mBAAmB,QAAQ,OAAO;AACtD,4BAAc,SAAS,OAAO,WAAW,EAAE;AAG3C,oBAAM,QAAQ,wBAAwB,QAAQ,OAAO;AACrD,yBAAW,QAAQ,OAAO;AACxB,oBAAI,KAAK,SAAS,SAAS;AACzB;AAAA,gBACF;AAAA,cACF;AAEA,kBAAI,QAAQ,MAAM;AAChB,8BAAc,SAAS,OAAO,QAAQ,IAAI,EAAE;AAC5C,8BAAc;AAAA,cAChB;AAAA,YACF;AAEA,0BAAc;AAId,0BAAc,aAAa;AAE3B,mBAAO;AAAA,UACT,UAAE;AAEA,qBAAS,KAAK;AAAA,UAChB;AAAA,QACF,SAAS,OAAO;AAEd,kBAAQ;AAAA,YACN,6BAA6B,WAAW,IAAI;AAAA,YAC5C;AAAA,UACF;AAEA,cAAI,aAAa;AACjB,cAAI,aAAa;AACjB,qBAAW,OAAO,UAAU;AAC1B,kBAAM,QAAQ,wBAAwB,IAAI,OAAO;AACjD,uBAAW,QAAQ,OAAO;AACxB,kBAAI,KAAK,SAAS,QAAQ;AACxB,8BAAc,KAAK,KAAK;AAAA,cAC1B,WAAW,KAAK,SAAS,SAAS;AAChC;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAEA,iBAAO,KAAK,KAAK,aAAa,wBAAwB,IAAI,aAAa;AAAA,QACzE;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC3bO,SAAS,2BAA8C;AAC5D,QAAM,WAA8B,CAAC;AAErC,aAAW,YAAY,aAAa;AAClC,UAAM,UAAU,SAAS;AACzB,QAAI,SAAS;AACX,eAAS,KAAK,OAAO;AAAA,IACvB;AAAA,EACF;AAEA,SAAO;AACT;AAxBA,IAOM;AAPN;AAAA;AAAA;AAAA;AACA;AACA;AAKA,IAAM,cAAoC;AAAA,MACxC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA;;;ACXA,IAaa;AAbb;AAAA;AAAA;AAaO,IAAM,gBAAN,MAAoB;AAAA,MACjB,aAA0B,CAAC;AAAA,MAC3B,cAAc,oBAAI,IAAyB;AAAA;AAAA;AAAA;AAAA,MAKnD,iBAAiB,UAAiC;AAChD,cAAM,QAAQ,SAAS,gBAAgB,KAAK,CAAC;AAE7C,YAAI,MAAM,SAAS,GAAG;AACpB,eAAK,WAAW,KAAK,GAAG,KAAK;AAC7B,eAAK,YAAY,IAAI,SAAS,YAAY,KAAK;AAAA,QACjD;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA2BA,cAAc,MAAuB;AAEnC,YAAI,CAAC,KAAK,WAAW,CAAC,KAAK,UAAU;AACnC,gBAAM,IAAI,MAAM,0CAA0C;AAAA,QAC5D;AAGA,cAAM,WAAW,KAAK,aAAa,KAAK,OAAO;AAC/C,YAAI,UAAU;AACZ,kBAAQ;AAAA,YACN,iDAAiD,KAAK,OAAO,gBAC9C,SAAS,WAAW,UAAU,KAAK,WAAW;AAAA,UAC/D;AAEA,gBAAM,QAAQ,KAAK,WAAW,UAAU,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO;AACzE,cAAI,UAAU,IAAI;AAChB,iBAAK,WAAW,OAAO,OAAO,CAAC;AAAA,UACjC;AAEA,gBAAMC,iBAAgB,KAAK,YAAY,IAAI,KAAK,QAAQ;AACxD,cAAIA,gBAAe;AACjB,kBAAM,gBAAgBA,eAAc,UAAU,CAAC,MAAM,EAAE,YAAY,KAAK,OAAO;AAC/E,gBAAI,kBAAkB,IAAI;AACxB,cAAAA,eAAc,OAAO,eAAe,CAAC;AAAA,YACvC;AAAA,UACF;AAAA,QACF;AAGA,aAAK,WAAW,KAAK,IAAI;AAGzB,cAAM,gBAAgB,KAAK,YAAY,IAAI,KAAK,QAAQ,KAAK,CAAC;AAC9D,sBAAc,KAAK,IAAI;AACvB,aAAK,YAAY,IAAI,KAAK,UAAU,aAAa;AAAA,MACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAeA,eAAe,OAA0B;AACvC,mBAAW,QAAQ,OAAO;AACxB,eAAK,cAAc,IAAI;AAAA,QACzB;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,aAAa,SAAwC;AAGnD,cAAM,eAAe,QAAQ,SAAS,GAAG,IAAI,QAAQ,MAAM,GAAG,EAAE,CAAC,IAAI;AACrE,eAAO,KAAK,WAAW,KAAK,CAAC,UAAU,MAAM,YAAY,YAAY;AAAA,MACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,WAAW,YAAkC;AAC3C,YAAI,CAAC,YAAY;AACf,iBAAO,CAAC,GAAG,KAAK,UAAU;AAAA,QAC5B;AAEA,eAAO,KAAK,YAAY,IAAI,UAAU,KAAK,CAAC;AAAA,MAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,eAAe,SAA0C;AACvD,cAAM,OAAO,KAAK,aAAa,OAAO;AACtC,YAAI,CAAC,KAAM,QAAO;AAElB,eAAO;AAAA,UACL,eAAe,KAAK;AAAA,UACpB,iBAAiB,KAAK;AAAA,QACxB;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWA,aACE,SACA,aACA,cACA,oBAAoB,GACpB,2BAA2B,GACD;AAC1B,cAAM,OAAO,KAAK,aAAa,OAAO;AACtC,YAAI,CAAC,KAAM,QAAO;AAKlB,cAAM,aAAa,KAAK,QAAQ,eAAe,KAAK,QAAQ;AAC5D,cAAM,iBAAiB,KAAK,QAAQ,mBAAmB,KAAK,QAAQ;AACpE,cAAM,sBAAsB,cAAc,oBAAoB;AAE9D,cAAM,oBAAqB,sBAAsB,MAAa,KAAK,QAAQ;AAC3E,cAAM,kBAAmB,oBAAoB,MAAa;AAC1D,cAAM,oBAAqB,2BAA2B,MAAa;AACnE,cAAM,YAAY,oBAAoB,kBAAkB;AACxD,cAAM,aAAc,eAAe,MAAa,KAAK,QAAQ;AAC7D,cAAM,YAAY,YAAY;AAE9B,eAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,UAAU;AAAA,QACZ;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,oBAAoB,SAAiB,iBAAkC;AACrE,cAAM,SAAS,KAAK,eAAe,OAAO;AAC1C,YAAI,CAAC,OAAQ,QAAO;AAEpB,eAAO,mBAAmB,OAAO;AAAA,MACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,gBAAgB,SAAiB,SAA+C;AAC9E,cAAM,OAAO,KAAK,aAAa,OAAO;AACtC,YAAI,CAAC,KAAM,QAAO;AAElB,eAAO,KAAK,SAAS,OAAO,MAAM;AAAA,MACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,mBAAmB,SAAsC,YAAkC;AACzF,cAAM,SAAS,KAAK,WAAW,UAAU;AACzC,eAAO,OAAO,OAAO,CAAC,UAAU,MAAM,SAAS,OAAO,MAAM,IAAI;AAAA,MAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,iBACE,aACA,cACA,YACuB;AACvB,cAAM,SAAS,KAAK,WAAW,UAAU;AACzC,YAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,YAAI;AAEJ,mBAAW,SAAS,QAAQ;AAC1B,gBAAM,WAAW,KAAK,aAAa,MAAM,SAAS,aAAa,YAAY;AAC3E,cAAI,CAAC,SAAU;AAEf,cAAI,CAAC,YAAY,SAAS,YAAY,SAAS,MAAM;AACnD,uBAAW,EAAE,OAAO,MAAM,SAAS,UAAU;AAAA,UAC/C;AAAA,QACF;AAEA,eAAO,UAAU;AAAA,MACnB;AAAA,IACF;AAAA;AAAA;;;ACnQA,IA4Ba;AA5Bb;AAAA;AAAA;AA4BO,IAAM,iBAAN,MAAqB;AAAA,MAC1B,YACmB,UACA,iBACjB;AAFiB;AACA;AAAA,MAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASH,MAAM,SAAS,SAAiE;AAC9E,cAAM,UAAU,QAAQ;AAGxB,cAAM,UAAU,KAAK,iBAAiB,OAAO;AAC7C,YAAI,CAAC,WAAW,CAAC,QAAQ,eAAe;AACtC,gBAAM,IAAI;AAAA,YACR,oDAAoD,OAAO,8BAC9B,KAAK,WAAW,EACxC,IAAI,CAAC,MAAM,EAAE,OAAO,EACpB,KAAK,IAAI,CAAC;AAAA,UACjB;AAAA,QACF;AAEA,eAAO,QAAQ,cAAc,OAAO;AAAA,MACtC;AAAA;AAAA;AAAA;AAAA,MAKA,aAA+B;AAC7B,cAAM,SAA2B,CAAC;AAClC,mBAAW,WAAW,KAAK,UAAU;AACnC,cAAI,QAAQ,oBAAoB;AAC9B,mBAAO,KAAK,GAAG,QAAQ,mBAAmB,CAAC;AAAA,UAC7C;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,cAAc,SAA0B;AACtC,eAAO,KAAK,iBAAiB,OAAO,MAAM;AAAA,MAC5C;AAAA,MAEQ,iBAAiB,SAA8C;AACrE,eAAO,KAAK,SAAS,KAAK,CAAC,YAAY,QAAQ,0BAA0B,OAAO,KAAK,KAAK;AAAA,MAC5F;AAAA,IACF;AAAA;AAAA;;;ACjFA,IA4Ba;AA5Bb;AAAA;AAAA;AA4BO,IAAM,kBAAN,MAAsB;AAAA,MAC3B,YACmB,UACA,iBACjB;AAFiB;AACA;AAAA,MAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASH,MAAM,SAAS,SAAmE;AAChF,cAAM,UAAU,QAAQ;AAGxB,cAAM,UAAU,KAAK,kBAAkB,OAAO;AAC9C,YAAI,CAAC,WAAW,CAAC,QAAQ,gBAAgB;AACvC,gBAAM,IAAI;AAAA,YACR,qDAAqD,OAAO,+BAC9B,KAAK,WAAW,EACzC,IAAI,CAAC,MAAM,EAAE,OAAO,EACpB,KAAK,IAAI,CAAC;AAAA,UACjB;AAAA,QACF;AAEA,eAAO,QAAQ,eAAe,OAAO;AAAA,MACvC;AAAA;AAAA;AAAA;AAAA,MAKA,aAAgC;AAC9B,cAAM,SAA4B,CAAC;AACnC,mBAAW,WAAW,KAAK,UAAU;AACnC,cAAI,QAAQ,qBAAqB;AAC/B,mBAAO,KAAK,GAAG,QAAQ,oBAAoB,CAAC;AAAA,UAC9C;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,cAAc,SAA0B;AACtC,eAAO,KAAK,kBAAkB,OAAO,MAAM;AAAA,MAC7C;AAAA,MAEQ,kBAAkB,SAA8C;AACtE,eAAO,KAAK,SAAS,KAAK,CAAC,YAAY,QAAQ,2BAA2B,OAAO,KAAK,KAAK;AAAA,MAC7F;AAAA,IACF;AAAA;AAAA;;;AC3BA,eAAsB,SACpB,QACA,QACA,UAAiC,CAAC,GACjB;AACjB,QAAM,QAAQ,aAAa,QAAQ,SAAS,YAAY;AAExD,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,QAAQ,cAAc;AACxB,YAAQ,UAAU,QAAQ,YAAY;AAAA,EACxC;AACA,UAAQ,QAAQ,MAAM;AAEtB,MAAI,eAAe;AACnB,mBAAiB,SAAS,OAAO,OAAO;AAAA,IACtC;AAAA,IACA,UAAU,QAAQ,MAAM;AAAA,IACxB,aAAa,QAAQ;AAAA,IACrB,WAAW,QAAQ;AAAA,EACrB,CAAC,GAAG;AACF,oBAAgB,MAAM;AAAA,EACxB;AAEA,SAAO,aAAa,KAAK;AAC3B;AAmBA,gBAAuB,OACrB,QACA,QACA,UAAiC,CAAC,GACV;AACxB,QAAM,QAAQ,aAAa,QAAQ,SAAS,YAAY;AAExD,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,QAAQ,cAAc;AACxB,YAAQ,UAAU,QAAQ,YAAY;AAAA,EACxC;AACA,UAAQ,QAAQ,MAAM;AAEtB,mBAAiB,SAAS,OAAO,OAAO;AAAA,IACtC;AAAA,IACA,UAAU,QAAQ,MAAM;AAAA,IACxB,aAAa,QAAQ;AAAA,IACrB,WAAW,QAAQ;AAAA,EACrB,CAAC,GAAG;AACF,UAAM,MAAM;AAAA,EACd;AACF;AAtHA;AAAA;AAAA;AAmBA;AACA;AAAA;AAAA;;;ACpBA,IAuBa;AAvBb;AAAA;AAAA;AAqBA;AAEO,IAAM,gBAAN,MAAoB;AAAA,MACzB,YAA6B,QAAgB;AAAhB;AAAA,MAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAS9C,MAAM,SAAS,QAAgB,SAAkD;AAC/E,eAAO,SAAS,KAAK,QAAQ,QAAQ,OAAO;AAAA,MAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,OAAO,QAAgB,SAAyD;AAC9E,eAAO,OAAO,KAAK,QAAQ,QAAQ,OAAO;AAAA,MAC5C;AAAA,IACF;AAAA;AAAA;;;AC/CA,IA4Ea;AA5Eb;AAAA;AAAA;AAsBA;AAQA;AA8CO,IAAM,kBAAN,MAAsB;AAAA,MAC3B,YAA6B,QAAgB;AAAhB;AAAA,MAAiB;AAAA;AAAA;AAAA;AAAA;AAAA,MAMtC,kBAAkB,SAAkD;AAC1E,cAAM,UAAU,IAAI,kBAAkB;AAEtC,YAAI,QAAQ,cAAc;AACxB,kBAAQ,UAAU,QAAQ,YAAY;AAAA,QACxC;AAGA,YAAI,OAAO,QAAQ,UAAU,UAAU;AACrC,cAAI,QAAQ,MAAM,WAAW,SAAS,KAAK,QAAQ,MAAM,WAAW,UAAU,GAAG;AAE/E,oBAAQ,oBAAoB,QAAQ,QAAQ,QAAQ,KAAK;AAAA,UAC3D,WAAW,UAAU,QAAQ,KAAK,GAAG;AAEnC,kBAAM,SAAS,aAAa,QAAQ,KAAK;AACzC,gBAAI,CAAC,QAAQ;AACX,oBAAM,IAAI,MAAM,yBAAyB;AAAA,YAC3C;AACA,oBAAQ,iBAAiB,QAAQ,QAAQ,OAAO,MAAM,OAAO,QAAyB;AAAA,UACxF,OAAO;AAEL,kBAAM,SAAS,OAAO,KAAK,QAAQ,OAAO,QAAQ;AAClD,oBAAQ,iBAAiB,QAAQ,QAAQ,QAAQ,QAAQ,QAAQ;AAAA,UACnE;AAAA,QACF,OAAO;AAEL,kBAAQ,iBAAiB,QAAQ,QAAQ,QAAQ,OAAO,QAAQ,QAAQ;AAAA,QAC1E;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,iBACZ,SACA,SACiE;AACjE,YAAI,WAAW;AACf,YAAI;AAEJ,yBAAiB,SAAS,KAAK,OAAO,OAAO;AAAA,UAC3C,OAAO,QAAQ;AAAA,UACf,UAAU,QAAQ,MAAM;AAAA,UACxB,WAAW,QAAQ;AAAA,UACnB,aAAa,QAAQ;AAAA,QACvB,CAAC,GAAG;AACF,sBAAY,MAAM;AAClB,cAAI,MAAM,OAAO;AACf,yBAAa;AAAA,cACX,aAAa,MAAM,MAAM;AAAA,cACzB,cAAc,MAAM,MAAM;AAAA,cAC1B,aAAa,MAAM,MAAM;AAAA,YAC3B;AAAA,UACF;AAAA,QACF;AAEA,eAAO,EAAE,MAAM,SAAS,KAAK,GAAG,OAAO,WAAW;AAAA,MACpD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA2BA,MAAM,QAAQ,SAAgD;AAC5D,cAAM,UAAU,KAAK,kBAAkB,OAAO;AAC9C,cAAM,EAAE,MAAAC,MAAK,IAAI,MAAM,KAAK,iBAAiB,SAAS,OAAO;AAC7D,eAAOA;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,MAAM,iBAAiB,SAA6D;AAClF,cAAM,UAAU,KAAK,kBAAkB,OAAO;AAC9C,cAAM,EAAE,MAAAA,OAAM,MAAM,IAAI,MAAM,KAAK,iBAAiB,SAAS,OAAO;AAEpE,eAAO;AAAA,UACL,MAAAA;AAAA,UACA,OAAO,QAAQ;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,cAAc,SAA0B;AACtC,cAAM,OAAO,KAAK,OAAO,cAAc,aAAa,OAAO;AAC3D,eAAO,MAAM,UAAU,WAAW;AAAA,MACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,aAAuB;AACrB,eAAO,KAAK,OAAO,cAChB,WAAW,EACX,OAAO,CAAC,SAAS,KAAK,UAAU,WAAW,IAAI,EAC/C,IAAI,CAAC,SAAS,KAAK,OAAO;AAAA,MAC/B;AAAA,IACF;AAAA;AAAA;;;ACtNA,IAoFa;AApFb;AAAA;AAAA;AAoFO,IAAM,wBAAN,MAA4B;AAAA,MACjC,YAA6B,kBAA0B,UAAU;AAApC;AAAA,MAAqC;AAAA,MAElE,MAAM,YAAqC;AACzC,cAAM,UAAU,WAAW,KAAK;AAChC,YAAI,CAAC,SAAS;AACZ,gBAAM,IAAI,MAAM,kCAAkC;AAAA,QACpD;AAEA,cAAM,CAAC,eAAe,GAAG,IAAI,IAAI,QAAQ,MAAM,GAAG;AAClD,YAAI,KAAK,WAAW,GAAG;AACrB,iBAAO,EAAE,UAAU,KAAK,iBAAiB,MAAM,cAAc;AAAA,QAC/D;AAEA,cAAM,WAAW;AACjB,cAAM,OAAO,KAAK,KAAK,GAAG;AAC1B,YAAI,CAAC,MAAM;AACT,gBAAM,IAAI,MAAM,4BAA4B;AAAA,QAC9C;AAEA,eAAO,EAAE,UAAU,KAAK;AAAA,MAC1B;AAAA,IACF;AAAA;AAAA;;;AC1GA;AAAA;AAAA;AAAA;AAAA,IA0Da;AA1Db;AAAA;AAAA;AAAA;AACA;AAIA;AACA;AACA;AACA;AACA;AAEA;AACA;AA8CO,IAAM,SAAN,MAAM,QAAO;AAAA,MACD;AAAA,MACA;AAAA,MACR;AAAA,MACQ;AAAA;AAAA,MAGR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAMT,eAAe,MAAgF;AAC7F,YAAI,WAA8B,CAAC;AACnC,YAAI;AACJ,YAAI,wBAAwB;AAC5B,YAAI,eAA4B,CAAC;AAEjC,YAAI,KAAK,WAAW,GAAG;AAAA,QAEvB,WAAW,MAAM,QAAQ,KAAK,CAAC,CAAC,GAAG;AACjC,qBAAW,KAAK,CAAC;AACjB,cAAI,KAAK,SAAS,GAAG;AACnB,8BAAkB,KAAK,CAAC;AAAA,UAC1B;AAAA,QACF,WAAW,OAAO,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,MAAM;AAC1D,gBAAM,UAAU,KAAK,CAAC;AACtB,qBAAW,QAAQ,YAAY,CAAC;AAChC,4BAAkB,QAAQ;AAC1B,yBAAe,QAAQ,gBAAgB,CAAC;AACxC,cAAI,OAAO,QAAQ,0BAA0B,WAAW;AACtD,oCAAwB,QAAQ;AAAA,UAClC;AAAA,QACF;AAEA,cAAM,qBAAqB,wBAAwB,yBAAyB,IAAI,CAAC;AACjF,cAAM,mBAAsC,CAAC,GAAG,QAAQ;AACxD,mBAAW,WAAW,oBAAoB;AACxC,cAAI,CAAC,iBAAiB,KAAK,CAAC,aAAa,SAAS,eAAe,QAAQ,UAAU,GAAG;AACpF,6BAAiB,KAAK,OAAO;AAAA,UAC/B;AAAA,QACF;AAEA,YAAI,iBAAiB,WAAW,GAAG;AACjC,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,cAAM,0BAA0B,mBAAmB,iBAAiB,CAAC,GAAG,cAAc;AAItF,aAAK,WAAW,CAAC,GAAG,gBAAgB,EAAE,KAAK,CAAC,GAAG,MAAM;AACnD,gBAAM,YAAY,EAAE,YAAY;AAChC,gBAAM,YAAY,EAAE,YAAY;AAChC,iBAAO,YAAY;AAAA,QACrB,CAAC;AACD,aAAK,kBAAkB;AACvB,aAAK,SAAS,IAAI,sBAAsB,uBAAuB;AAC/D,aAAK,gBAAgB,IAAI,cAAc;AAGvC,mBAAW,WAAW,KAAK,UAAU;AACnC,eAAK,cAAc,iBAAiB,OAAO;AAAA,QAC7C;AAGA,YAAI,aAAa,SAAS,GAAG;AAC3B,eAAK,cAAc,eAAe,YAAY;AAAA,QAChD;AAGA,aAAK,OAAO,IAAI,cAAc,IAAI;AAClC,aAAK,QAAQ,IAAI,eAAe,KAAK,UAAU,KAAK,eAAe;AACnE,aAAK,SAAS,IAAI,gBAAgB,KAAK,UAAU,KAAK,eAAe;AACrE,aAAK,SAAS,IAAI,gBAAgB,IAAI;AAAA,MACxC;AAAA,MAEA,OAAO,SAA0C;AAC/C,cAAM,aAAa,KAAK,OAAO,MAAM,QAAQ,KAAK;AAClD,cAAM,OAAO,KAAK,cAAc,aAAa,WAAW,IAAI;AAC5D,cAAM,UAAU,KAAK,eAAe,UAAU;AAC9C,eAAO,QAAQ,OAAO,SAAS,YAAY,IAAI;AAAA,MACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAkCA,MAAM,YAAY,OAAe,UAAyC;AACxE,cAAM,aAAa,KAAK,OAAO,MAAM,KAAK;AAC1C,cAAM,OAAO,KAAK,cAAc,aAAa,WAAW,IAAI;AAC5D,cAAM,UAAU,KAAK,eAAe,UAAU;AAG9C,YAAI,QAAQ,aAAa;AACvB,iBAAO,QAAQ,YAAY,UAAU,YAAY,IAAI;AAAA,QACvD;AAGA,cAAM,aAAa,SAAS,OAAO,CAAC,KAAK,QAAQ,OAAO,IAAI,SAAS,UAAU,IAAI,CAAC;AACpF,eAAO,KAAK,KAAK,aAAa,CAAC;AAAA,MACjC;AAAA,MAEQ,eAAe,YAA8C;AACnE,cAAM,UAAU,KAAK,SAAS,KAAK,CAAC,SAAS,KAAK,SAAS,UAAU,CAAC;AACtE,YAAI,CAAC,SAAS;AACZ,gBAAM,IAAI,MAAM,sCAAsC,WAAW,QAAQ,EAAE;AAAA,QAC7E;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAqBA,aAAa,SAAS,QAAgB,SAAkD;AACtF,cAAM,SAAS,IAAI,QAAO;AAC1B,eAAO,SAAe,QAAQ,QAAQ,OAAO;AAAA,MAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAyBA,OAAO,OAAO,QAAgB,SAAyD;AACrF,cAAM,SAAS,IAAI,QAAO;AAC1B,eAAO,OAAa,QAAQ,QAAQ,OAAO;AAAA,MAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,MAAM,SAAS,QAAgB,SAAkD;AAC/E,eAAO,SAAe,MAAM,QAAQ,OAAO;AAAA,MAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,WAAW,QAAgB,SAAyD;AAClF,eAAO,OAAa,MAAM,QAAQ,OAAO;AAAA,MAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA6BA,OAAO,cAA4B;AACjC,eAAO,IAAI,aAAa;AAAA,MAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAiBA,cAA4B;AAC1B,eAAO,IAAI,aAAa,IAAI;AAAA,MAC9B;AAAA,IACF;AAAA;AAAA;;;ACjUA,SAAS,OAAO,QAA6C;AAC3D,SAAO,OAAO;AAChB;AAgBA,SAAS,YAAY,QAAwC;AAC3D,QAAM,MAAM,OAAO,MAAM;AAEzB,SAAQ,KAAK,QAAQ,KAAK;AAC5B;AAOA,SAAS,SAAS,QAA4D;AAC5E,QAAM,MAAM,OAAO,MAAM;AAEzB,MAAI,OAAO,KAAK,UAAU,YAAY;AACpC,WAAQ,IAAI,MAA2C;AAAA,EACzD;AACA,SAAO,KAAK;AACd;AA1CA,IAuEa;AAvEb;AAAA;AAAA;AAuEO,IAAM,qBAAN,MAAyB;AAAA,MACb;AAAA,MACA,QAAQ,oBAAI,IAAsB;AAAA,MAEnD,YAAY,QAAoB;AAC9B,aAAK,SAAS;AAAA,MAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,cAAc,SAA2B;AAEvC,cAAM,SAAS,KAAK,MAAM,IAAI,OAAO;AACrC,YAAI,WAAW,QAAW;AACxB,iBAAO;AAAA,QACT;AAEA,cAAM,SAAS,KAAK,kBAAkB,OAAO;AAC7C,aAAK,MAAM,IAAI,SAAS,MAAM;AAC9B,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,kBAAkB,SAA2B;AAEnD,YAAI,CAAC,SAAS;AACZ,iBAAO,KAAK,YAAY,KAAK,MAAM;AAAA,QACrC;AAEA,cAAM,WAAW,QAAQ,MAAM,GAAG;AAClC,YAAI,UAAsB,KAAK;AAE/B,mBAAW,WAAW,UAAU;AAE9B,oBAAU,KAAK,aAAa,OAAO;AAGnC,gBAAM,WAAW,YAAY,OAAO;AAEpC,cAAI,aAAa,YAAY,aAAa,aAAa;AAErD,kBAAM,QAAQ,SAAS,OAAO;AAC9B,gBAAI,CAAC,SAAS,EAAE,WAAW,QAAQ;AACjC,qBAAO;AAAA,YACT;AACA,sBAAU,MAAM,OAAO;AAAA,UACzB,WAAW,aAAa,WAAW,aAAa,YAAY;AAE1D,gBAAI,CAAC,QAAQ,KAAK,OAAO,GAAG;AAC1B,qBAAO;AAAA,YACT;AAEA,kBAAM,MAAM,OAAO,OAAO;AAC1B,kBAAM,cAAe,KAAK,WAAW,KAAK;AAC1C,gBAAI,CAAC,aAAa;AAChB,qBAAO;AAAA,YACT;AACA,sBAAU;AAAA,UACZ,WAAW,aAAa,WAAW,aAAa,YAAY;AAE1D,gBAAI,CAAC,QAAQ,KAAK,OAAO,GAAG;AAC1B,qBAAO;AAAA,YACT;AACA,kBAAM,QAAQ,SAAS,SAAS,EAAE;AAClC,kBAAM,MAAM,OAAO,OAAO;AAC1B,kBAAM,QAAQ,KAAK;AACnB,gBAAI,CAAC,SAAS,SAAS,MAAM,QAAQ;AACnC,qBAAO;AAAA,YACT;AACA,sBAAU,MAAM,KAAK;AAAA,UACvB,WAAW,aAAa,YAAY,aAAa,aAAa;AAG5D,kBAAM,MAAM,OAAO,OAAO;AAC1B,kBAAM,YAAY,KAAK;AACvB,gBAAI,CAAC,WAAW;AACd,qBAAO;AAAA,YACT;AACA,sBAAU;AAAA,UACZ,OAAO;AAEL,mBAAO;AAAA,UACT;AAAA,QACF;AAGA,eAAO,KAAK,YAAY,OAAO;AAAA,MACjC;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,aAAa,QAAgC;AACnD,YAAI,UAAU;AACd,YAAI,aAAa;AACjB,cAAM,gBAAgB;AAEtB,eAAO,aAAa,eAAe;AACjC,gBAAM,WAAW,YAAY,OAAO;AAGpC,gBAAM,eAAe;AAAA,YACnB;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAEA,cAAI,YAAY,aAAa,SAAS,QAAQ,GAAG;AAC/C,kBAAM,MAAM,OAAO,OAAO;AAC1B,kBAAM,QAAS,KAAK,aAAa,KAAK,MAAM,KAAK;AACjD,gBAAI,CAAC,SAAS,UAAU,QAAS;AACjC,sBAAU;AACV;AACA;AAAA,UACF;AAEA;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKQ,YAAY,QAA8B;AAChD,cAAM,YAAY,KAAK,aAAa,MAAM;AAC1C,cAAM,WAAW,YAAY,SAAS;AAGtC,gBAAQ,UAAU;AAAA;AAAA,UAEhB,KAAK;AAAA,UACL,KAAK;AACH,mBAAO;AAAA,UACT,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AACH,mBAAO;AAAA,UACT,KAAK;AAAA,UACL,KAAK;AACH,mBAAO;AAAA;AAAA,UAGT,KAAK;AAAA,UACL,KAAK,cAAc;AAEjB,kBAAM,MAAM,OAAO,SAAS;AAC5B,kBAAM,SAAS,KAAK;AACpB,kBAAM,QAAQ,SAAS,CAAC,KAAK,KAAK;AAClC,gBAAI,OAAO,UAAU,SAAU,QAAO;AACtC,gBAAI,OAAO,UAAU,YAAY,OAAO,UAAU,SAAU,QAAO;AACnE,gBAAI,OAAO,UAAU,UAAW,QAAO;AACvC,mBAAO;AAAA,UACT;AAAA;AAAA,UAGA,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AACH,mBAAO;AAAA;AAAA;AAAA;AAAA,UAKT,KAAK;AAAA,UACL,KAAK;AACH,mBAAO;AAAA;AAAA,UAGT,KAAK;AAAA,UACL,KAAK;AACH,mBAAO;AAAA;AAAA,UAGT,KAAK;AAAA,UACL,KAAK,mBAAmB;AACtB,kBAAM,MAAM,OAAO,SAAS;AAC5B,kBAAM,OAAO,KAAK;AAClB,kBAAM,QAAQ,KAAK;AACnB,gBAAI,CAAC,QAAQ,CAAC,MAAO,QAAO;AAE5B,kBAAM,WAAW,KAAK,YAAY,IAAI;AACtC,kBAAM,YAAY,KAAK,YAAY,KAAK;AAGxC,gBAAI,aAAa,UAAW,QAAO;AAEnC,gBAAI,aAAa,YAAY,cAAc,SAAU,QAAO;AAE5D,mBAAO;AAAA,UACT;AAAA;AAAA,UAGA,KAAK;AAAA,UACL,KAAK;AAGH,mBAAO;AAAA;AAAA,UAGT,KAAK;AAAA,UACL,KAAK;AACH,mBAAO;AAAA;AAAA,UAGT,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AACH,mBAAO;AAAA;AAAA,UAGT,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AACH,mBAAO;AAAA,UAET;AACE,mBAAO;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AClSO,SAAS,iBACd,SACA,SACyB;AACzB,QAAM,YAAY,SAAS,aAAa;AACxC,QAAM,SAAkC,CAAC;AACzC,QAAM,eAAe,oBAAI,IAAY;AAGrC,QAAM,eAAe,SAAS,SAAS,IAAI,mBAAmB,QAAQ,MAAM,IAAI;AAIhF,QAAM,QAAQ,QAAQ,MAAM,SAAS;AAErC,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC;AAGpB,UAAM,eAAe,KAAK,QAAQ,IAAI;AACtC,QAAI,iBAAiB,IAAI;AAEvB,YAAMC,WAAU,KAAK,KAAK;AAC1B,UAAIA,UAAS;AACX,YAAI,aAAa,IAAIA,QAAO,GAAG;AAC7B,gBAAM,IAAI,MAAM,sBAAsBA,QAAO,EAAE;AAAA,QACjD;AACA,qBAAa,IAAIA,QAAO;AACxB,qBAAa,QAAQA,UAAS,IAAI,YAAY;AAAA,MAChD;AACA;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,UAAU,GAAG,YAAY,EAAE,KAAK;AACrD,QAAI,QAAQ,KAAK,UAAU,eAAe,CAAC;AAG3C,QAAI,MAAM,SAAS,IAAI,GAAG;AACxB,cAAQ,MAAM,MAAM,GAAG,EAAE;AAAA,IAC3B;AAEA,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AAEA,QAAI,aAAa,IAAI,OAAO,GAAG;AAC7B,YAAM,IAAI,MAAM,sBAAsB,OAAO,EAAE;AAAA,IACjD;AACA,iBAAa,IAAI,OAAO;AAExB,iBAAa,QAAQ,SAAS,OAAO,YAAY;AAAA,EACnD;AAEA,SAAO;AACT;AAuBA,SAAS,YAAY,OAAe,cAAoD;AAEtF,MAAI,MAAM,SAAS,IAAI,GAAG;AACxB,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,MAAM,KAAK;AAG3B,MAAI,iBAAiB,UAAU;AAE7B,WAAO;AAAA,EACT;AAEA,MAAI,iBAAiB,WAAW;AAE9B,QAAI,YAAY,OAAQ,QAAO;AAC/B,QAAI,YAAY,QAAS,QAAO;AAEhC,WAAO;AAAA,EACT;AAEA,MAAI,iBAAiB,UAAU;AAE7B,UAAM,MAAM,OAAO,OAAO;AAC1B,QAAI,CAAC,MAAM,GAAG,KAAK,SAAS,GAAG,KAAK,YAAY,IAAI;AAClD,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAOA,MAAI,YAAY,OAAQ,QAAO;AAC/B,MAAI,YAAY,QAAS,QAAO;AAIhC,MAAI,YAAY,MAAM,kBAAkB,KAAK,OAAO,GAAG;AACrD,UAAM,MAAM,OAAO,OAAO;AAC1B,QAAI,CAAC,MAAM,GAAG,KAAK,SAAS,GAAG,GAAG;AAChC,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAmBA,SAAS,aACP,KACA,SACA,OACA,cACM;AACN,QAAM,WAAW,QAAQ,MAAM,GAAG;AAClC,MAAI,UAA+C;AAEnD,WAAS,IAAI,GAAG,IAAI,SAAS,SAAS,GAAG,KAAK;AAC5C,UAAM,UAAU,SAAS,CAAC;AAC1B,UAAM,cAAc,SAAS,IAAI,CAAC;AAClC,UAAM,mBAAmB,QAAQ,KAAK,WAAW;AAEjD,QAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,YAAM,QAAQ,SAAS,SAAS,EAAE;AAClC,UAAI,MAAM,KAAK,KAAK,QAAQ,GAAG;AAC7B,cAAM,IAAI,MAAM,wBAAwB,OAAO,EAAE;AAAA,MACnD;AAEA,UAAI,QAAQ,QAAQ,QAAQ;AAC1B,cAAM,IAAI,MAAM,6BAA6B,QAAQ,MAAM,SAAS,KAAK,EAAE;AAAA,MAC7E;AACA,UAAI,QAAQ,KAAK,MAAM,QAAW;AAChC,gBAAQ,KAAK,IAAI,mBAAmB,CAAC,IAAI,CAAC;AAAA,MAC5C;AACA,gBAAU,QAAQ,KAAK;AAAA,IACzB,OAAO;AAEL,YAAM,MAAM;AACZ,UAAI,IAAI,OAAO,MAAM,QAAW;AAC9B,YAAI,OAAO,IAAI,mBAAmB,CAAC,IAAI,CAAC;AAAA,MAC1C;AACA,gBAAU,IAAI,OAAO;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,cAAc,SAAS,SAAS,SAAS,CAAC;AAGhD,QAAM,eAAe,cAAc,cAAc,OAAO;AACxD,QAAM,eAAe,YAAY,OAAO,YAAY;AAEpD,MAAI,MAAM,QAAQ,OAAO,GAAG;AAC1B,UAAM,QAAQ,SAAS,aAAa,EAAE;AACtC,QAAI,MAAM,KAAK,KAAK,QAAQ,GAAG;AAC7B,YAAM,IAAI,MAAM,wBAAwB,WAAW,EAAE;AAAA,IACvD;AAEA,QAAI,QAAQ,QAAQ,QAAQ;AAC1B,YAAM,IAAI,MAAM,6BAA6B,QAAQ,MAAM,SAAS,KAAK,EAAE;AAAA,IAC7E;AACA,YAAQ,KAAK,IAAI;AAAA,EACnB,OAAO;AACL,IAAC,QAAoC,WAAW,IAAI;AAAA,EACtD;AACF;AAzPA;AAAA;AAAA;AACA;AACA;AAAA;AAAA;;;ACFA,IAkDa;AAlDb;AAAA;AAAA;AAkBA;AAgCO,IAAM,6BAAN,MAAgE;AAAA,MAIrE,YACmB,QACA,YACjB;AAFiB;AACA;AAGjB,aAAK,QAAQ;AAAA,UACX,UAAU,OAAO,YAAoE;AACnF,kBAAM,SAAS,MAAM,KAAK,OAAO,MAAM,SAAS,OAAO;AAEvD,gBAAI,OAAO,SAAS,UAAa,OAAO,OAAO,GAAG;AAChD,mBAAK,WAAW,OAAO,IAAI;AAAA,YAC7B;AACA,mBAAO;AAAA,UACT;AAAA,QACF;AAGA,aAAK,SAAS;AAAA,UACZ,UAAU,OAAO,YAAsE;AACrF,kBAAM,SAAS,MAAM,KAAK,OAAO,OAAO,SAAS,OAAO;AAExD,gBAAI,OAAO,SAAS,UAAa,OAAO,OAAO,GAAG;AAChD,mBAAK,WAAW,OAAO,IAAI;AAAA,YAC7B;AACA,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AAAA,MA9BS;AAAA,MACA;AAAA;AAAA;AAAA;AAAA,MAkCT,IAAI,gBAA+B;AACjC,eAAO,KAAK,OAAO;AAAA,MACrB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWA,MAAM,SAAS,QAAgB,SAAkD;AAC/E,cAAM,QAAQ,aAAa,SAAS,SAAS,OAAO;AACpD,YAAI,SAAS;AACb,YAAI,cAAc;AAClB,YAAI,eAAe;AACnB,YAAI,oBAAoB;AACxB,YAAI,2BAA2B;AAE/B,cAAM,WAAW;AAAA,UACf,GAAI,SAAS,eACT,CAAC,EAAE,MAAM,UAAmB,SAAS,QAAQ,aAAa,CAAC,IAC3D,CAAC;AAAA,UACL,EAAE,MAAM,QAAiB,SAAS,OAAO;AAAA,QAC3C;AAEA,yBAAiB,SAAS,KAAK,OAAO,OAAO;AAAA,UAC3C;AAAA,UACA;AAAA,UACA,aAAa,SAAS;AAAA,UACtB,WAAW,SAAS;AAAA,QACtB,CAAC,GAAG;AACF,oBAAU,MAAM,QAAQ;AACxB,cAAI,MAAM,OAAO;AACf,0BAAc,MAAM,MAAM;AAC1B,2BAAe,MAAM,MAAM;AAC3B,gCAAoB,MAAM,MAAM,qBAAqB;AACrD,uCAA2B,MAAM,MAAM,4BAA4B;AAAA,UACrE;AAAA,QACF;AAEA,aAAK;AAAA,UACH;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWA,OAAO,WAAW,QAAgB,SAAyD;AACzF,cAAM,QAAQ,aAAa,SAAS,SAAS,OAAO;AACpD,YAAI,cAAc;AAClB,YAAI,eAAe;AACnB,YAAI,oBAAoB;AACxB,YAAI,2BAA2B;AAE/B,cAAM,WAAW;AAAA,UACf,GAAI,SAAS,eACT,CAAC,EAAE,MAAM,UAAmB,SAAS,QAAQ,aAAa,CAAC,IAC3D,CAAC;AAAA,UACL,EAAE,MAAM,QAAiB,SAAS,OAAO;AAAA,QAC3C;AAEA,YAAI;AACF,2BAAiB,SAAS,KAAK,OAAO,OAAO;AAAA,YAC3C;AAAA,YACA;AAAA,YACA,aAAa,SAAS;AAAA,YACtB,WAAW,SAAS;AAAA,UACtB,CAAC,GAAG;AACF,gBAAI,MAAM,MAAM;AACd,oBAAM,MAAM;AAAA,YACd;AACA,gBAAI,MAAM,OAAO;AACf,4BAAc,MAAM,MAAM;AAC1B,6BAAe,MAAM,MAAM;AAC3B,kCAAoB,MAAM,MAAM,qBAAqB;AACrD,yCAA2B,MAAM,MAAM,4BAA4B;AAAA,YACrE;AAAA,UACF;AAAA,QACF,UAAE;AAEA,eAAK;AAAA,YACH;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA,OAAO,SAA0C;AAC/C,eAAO,KAAK,0BAA0B,OAAO;AAAA,MAC/C;AAAA;AAAA;AAAA;AAAA,MAKQ,0BAA0B,SAA0C;AAC1E,cAAM,cAAc,KAAK,OAAO,OAAO,OAAO;AAC9C,cAAM,sBAAsB,KAAK,oBAAoB,KAAK,IAAI;AAC9D,cAAM,QAAQ,QAAQ;AAEtB,wBAAgB,uBAAuD;AACrE,cAAI,cAAc;AAClB,cAAI,eAAe;AACnB,cAAI,oBAAoB;AACxB,cAAI,2BAA2B;AAE/B,cAAI;AACF,6BAAiB,SAAS,aAAa;AACrC,kBAAI,MAAM,OAAO;AACf,8BAAc,MAAM,MAAM;AAC1B,+BAAe,MAAM,MAAM;AAC3B,oCAAoB,MAAM,MAAM,qBAAqB;AACrD,2CAA2B,MAAM,MAAM,4BAA4B;AAAA,cACrE;AACA,oBAAM;AAAA,YACR;AAAA,UACF,UAAE;AAEA,gBAAI,cAAc,KAAK,eAAe,GAAG;AACvC;AAAA,gBACE;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,eAAO,qBAAqB;AAAA,MAC9B;AAAA;AAAA;AAAA;AAAA,MAKQ,oBACN,OACA,aACA,cACA,oBAAoB,GACpB,2BAA2B,GACrB;AACN,YAAI,gBAAgB,KAAK,iBAAiB,EAAG;AAG7C,cAAM,WAAW,KAAK,OAAO,cAAc;AAAA,UACzC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAEA,YAAI,YAAY,SAAS,YAAY,GAAG;AACtC,eAAK,WAAW,SAAS,SAAS;AAAA,QACpC;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;AC7QA,IAuBa;AAvBb;AAAA;AAAA;AACA;AAsBO,IAAM,gCAAN,MAAoC;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MAEjB,YAAY,UAAiC,CAAC,GAAG;AAC/C,aAAK,YAAY,QAAQ,aAAa;AACtC,aAAK,cAAc,QAAQ,eAAe;AAC1C,aAAK,YAAY,QAAQ,aAAa;AAAA,MACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA,sBAAsB,YAAoB,UAAoB,QAAgC;AAC5F,cAAM,QAAkB,CAAC;AAGzB,cAAM,KAAK,kCAAkC,UAAU,IAAI;AAG3D,mBAAW,SAAS,SAAS,QAAQ;AACnC,gBAAM,OAAO,MAAM,KAAK,KAAK,GAAG,KAAK;AACrC,gBAAM,KAAK,OAAO,IAAI,KAAK,MAAM,OAAO,EAAE;AAAA,QAC5C;AAGA,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,eAAe;AAC1B,cAAM,KAAK,OAAO,eAAe,KAAK,SAAS,CAAC;AAEhD,eAAO,MAAM,KAAK,IAAI;AAAA,MACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA,iBAAiB,YAAoB,YAAoB,QAA4C;AACnG,cAAM,QAAkB,CAAC;AAGzB,cAAM,KAAK,0CAA0C,UAAU,IAAI;AACnE,cAAM,KAAK,KAAK,UAAU,EAAE;AAG5B,YAAI,QAAQ;AACV,gBAAM,KAAK,EAAE;AACb,gBAAM,KAAK,eAAe;AAC1B,gBAAM,KAAK,OAAO,eAAe,KAAK,SAAS,CAAC;AAAA,QAClD;AAGA,cAAM,KAAK,EAAE;AACb,cAAM,KAAK,yBAAyB;AACpC,cAAM,KAAK,KAAK,KAAK,WAAW,GAAG,UAAU,EAAE;AAC/C,cAAM,KAAK,KAAK,KAAK,SAAS,eAAe;AAC7C,cAAM,KAAK,wBAAwB;AACnC,cAAM,KAAK,KAAK,KAAK,SAAS,EAAE;AAEhC,eAAO,MAAM,KAAK,IAAI;AAAA,MACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,oBAAoB,YAAoB,kBAAoC;AAC1E,cAAM,QAAkB,CAAC;AAGzB,cAAM,KAAK,kBAAkB,UAAU,cAAc;AAGrD,YAAI,iBAAiB,SAAS,GAAG;AAC/B,gBAAM,KAAK,EAAE;AACb,gBAAM,KAAK,sBAAsB,iBAAiB,KAAK,IAAI,CAAC,EAAE;AAAA,QAChE,OAAO;AACL,gBAAM,KAAK,EAAE;AACb,gBAAM,KAAK,sCAAsC;AAAA,QACnD;AAEA,eAAO,MAAM,KAAK,IAAI;AAAA,MACxB;AAAA,IACF;AAAA;AAAA;;;AC1GO,SAAS,oBAAoB,SAAyB;AAC3D,MAAI,UAAU,QAAQ,KAAK;AAG3B,QAAM,eAAe;AAErB,QAAM,eAAe;AAGrB,YAAU,QAAQ,QAAQ,cAAc,EAAE;AAE1C,YAAU,QAAQ,QAAQ,cAAc,EAAE;AAE1C,SAAO,QAAQ,KAAK;AACtB;AA3BA,IAqCI,yBAcS;AAnDb;AAAA;AAAA;AAAA;AACA;AAoCA,IAAI,0BAA0B;AAcvB,IAAM,mBAAN,MAAuB;AAAA,MACpB,SAAS;AAAA,MACT,wBAAwB;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,MAEjB,YAAY,UAA+B,CAAC,GAAG;AAC7C,aAAK,cAAc,QAAQ,eAAe;AAC1C,aAAK,YAAY,QAAQ,aAAa;AACtC,aAAK,YAAY,QAAQ,aAAa;AAAA,MACxC;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,mBAAmB,OAAmC;AAC5D,YAAI,SAAS,KAAK,uBAAuB;AACvC,iBAAO;AAAA,QACT;AAEA,cAAM,UAAU,KAAK,OAAO,MAAM,KAAK,uBAAuB,KAAK;AACnE,aAAK,wBAAwB;AAE7B,eAAO,QAAQ,KAAK,EAAE,SAAS,IAAI,UAAU;AAAA,MAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYQ,wBAAwB,YAI9B;AACA,cAAM,QAAQ,WAAW,MAAM,GAAG;AAElC,YAAI,MAAM,WAAW,GAAG;AAEtB,iBAAO;AAAA,YACL,YAAY,MAAM,CAAC;AAAA,YACnB,cAAc,UAAU,EAAE,uBAAuB;AAAA,YACjD,cAAc,CAAC;AAAA,UACjB;AAAA,QACF,WAAW,MAAM,WAAW,GAAG;AAE7B,iBAAO;AAAA,YACL,YAAY,MAAM,CAAC;AAAA,YACnB,cAAc,MAAM,CAAC,EAAE,KAAK;AAAA,YAC5B,cAAc,CAAC;AAAA,UACjB;AAAA,QACF,OAAO;AAEL,gBAAM,OAAO,MAAM,CAAC,EACjB,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC;AAC7B,iBAAO;AAAA,YACL,YAAY,MAAM,CAAC;AAAA,YACnB,cAAc,MAAM,CAAC,EAAE,KAAK;AAAA,YAC5B,cAAc;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOQ,kBAAkB,OAAwB;AAChD,eAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MAC9D;AAAA;AAAA;AAAA;AAAA,MAKQ,gBAAgB,KAGtB;AAEA,cAAM,UAAU,oBAAoB,GAAG;AAEvC,YAAI;AACF,iBAAO,EAAE,YAAY,iBAAiB,SAAS,EAAE,WAAW,KAAK,UAAU,CAAC,EAAE;AAAA,QAChF,SAAS,OAAO;AACd,iBAAO,EAAE,YAAY,KAAK,kBAAkB,KAAK,EAAE;AAAA,QACrD;AAAA,MACF;AAAA;AAAA,MAGA,CAAC,KAAK,OAAuC;AAC3C,aAAK,UAAU;AAEf,YAAI,aAAa;AACjB,eAAO,MAAM;AAEX,gBAAM,iBAAiB,KAAK,OAAO,QAAQ,KAAK,aAAa,UAAU;AACvE,cAAI,mBAAmB,GAAI;AAG3B,gBAAM,aAAa,KAAK,mBAAmB,cAAc;AACzD,cAAI,eAAe,QAAW;AAC5B,kBAAM,EAAE,MAAM,QAAQ,SAAS,WAAW;AAAA,UAC5C;AAGA,gBAAM,qBAAqB,iBAAiB,KAAK,YAAY;AAC7D,gBAAM,mBAAmB,KAAK,OAAO,QAAQ,MAAM,kBAAkB;AACrE,cAAI,qBAAqB,GAAI;AAE7B,gBAAM,aAAa,KAAK,OAAO,UAAU,oBAAoB,gBAAgB,EAAE,KAAK;AACpF,gBAAM,EAAE,YAAY,cAAc,aAAa,IAAI,KAAK,wBAAwB,UAAU;AAE1F,gBAAM,oBAAoB,mBAAmB;AAE7C,cAAI;AACJ,cAAI,kBAAkB;AAMtB,gBAAM,eAAe,KAAK,OAAO,QAAQ,KAAK,aAAa,iBAAiB;AAG5E,gBAAM,SAAS,KAAK,OAAO,QAAQ,KAAK,WAAW,iBAAiB;AAKpE,cAAI,iBAAiB,OAAO,WAAW,MAAM,eAAe,SAAS;AAEnE,2BAAe;AACf,8BAAkB;AAAA,UACpB,WAAW,WAAW,IAAI;AAExB,2BAAe;AACf,8BAAkB,KAAK,UAAU;AAAA,UACnC,OAAO;AAEL;AAAA,UACF;AAGA,gBAAM,gBAAgB,KAAK,OAAO,UAAU,mBAAmB,YAAY,EAAE,KAAK;AAGlF,gBAAM,EAAE,YAAY,WAAW,IAAI,KAAK,gBAAgB,aAAa;AAErE,gBAAM;AAAA,YACJ,MAAM;AAAA,YACN,MAAM;AAAA,cACJ;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAGA,uBAAa,eAAe;AAE5B,eAAK,wBAAwB;AAAA,QAC/B;AAGA,YAAI,aAAa,GAAG;AAClB,eAAK,SAAS,KAAK,OAAO,UAAU,UAAU;AAC9C,eAAK,wBAAwB;AAAA,QAC/B;AAAA,MACF;AAAA;AAAA,MAGA,CAAC,WAAmC;AAElC,cAAM,aAAa,KAAK,OAAO,QAAQ,KAAK,aAAa,KAAK,qBAAqB;AAEnF,YAAI,eAAe,IAAI;AAErB,gBAAM,aAAa,KAAK,mBAAmB,UAAU;AACrD,cAAI,eAAe,QAAW;AAC5B,kBAAM,EAAE,MAAM,QAAQ,SAAS,WAAW;AAAA,UAC5C;AAGA,gBAAM,qBAAqB,aAAa,KAAK,YAAY;AACzD,gBAAM,mBAAmB,KAAK,OAAO,QAAQ,MAAM,kBAAkB;AAErE,cAAI,qBAAqB,IAAI;AAC3B,kBAAM,aAAa,KAAK,OAAO,UAAU,oBAAoB,gBAAgB,EAAE,KAAK;AACpF,kBAAM,EAAE,YAAY,cAAc,aAAa,IAAI,KAAK,wBAAwB,UAAU;AAC1F,kBAAM,oBAAoB,mBAAmB;AAG7C,kBAAM,gBAAgB,KAAK,OAAO,UAAU,iBAAiB,EAAE,KAAK;AAEpE,kBAAM,EAAE,YAAY,WAAW,IAAI,KAAK,gBAAgB,aAAa;AAErE,kBAAM;AAAA,cACJ,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cACF;AAAA,YACF;AAEA;AAAA,UACF;AAAA,QACF;AAGA,cAAM,gBAAgB,KAAK,mBAAmB,KAAK,OAAO,MAAM;AAChE,YAAI,kBAAkB,QAAW;AAC/B,gBAAM,EAAE,MAAM,QAAQ,SAAS,cAAc;AAAA,QAC/C;AAAA,MACF;AAAA;AAAA,MAGA,QAAc;AACZ,aAAK,SAAS;AACd,aAAK,wBAAwB;AAAA,MAC/B;AAAA,IACF;AAAA;AAAA;;;ACpLO,SAAS,OAAgC,QAA+B;AAAA,EAC7E,MAAe,mBAAmB,eAAe;AAAA,IAC/C,cAAc,OAAO;AAAA,IACrB,kBAAkB,OAAO;AAAA,IACzB,OAAO,OAAO;AAAA,IACd,YAAY,OAAO;AAAA,IACnB,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAST;AAAA,EAgCX;AAEA,SAAO;AAGT;AAjKA;AAAA;AAAA;AA0BA;AAAA;AAAA;;;ACcA,SAAS,yBAAsC;AAC7C,MAAI,CAAC,mBAAmB;AACtB,wBAAoB;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AApDA,4BAEAC,aAqCI,mBAeS;AAtDb;AAAA;AAAA;AAAA,6BAAkB;AAElB,IAAAA,cAAkB;AAClB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAOA;AAEA;AAiCO,IAAM,iBAAN,MAAqB;AAAA,MAK1B,YACmB,UACA,mBACjB,QACiB,wBACjB,uBACiB,QACA,YACA,aACA,gBACA,iBAEA,MACA,cACA,WACjB;AAdiB;AACA;AAEA;AAEA;AACA;AACA;AACA;AACA;AAEA;AACA;AACA;AAEjB,aAAK,SAAS,UAAU,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAChE,aAAK,iBAAiB,IAAI,8BAA8B,qBAAqB;AAC7E,aAAK,YAAY,uBAAuB,aAAa;AAAA,MACvD;AAAA,MAvBiB;AAAA,MACA;AAAA,MACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA4BT,qBACN,YACA,WACA,iBACiD;AACjD,YAAI;AAEJ,cAAM,UAAU,IAAI,QAAe,CAAC,GAAG,WAAW;AAChD,sBAAY,WAAW,MAAM;AAC3B,kBAAM,eAAe,IAAI,iBAAiB,YAAY,SAAS;AAG/D,4BAAgB,MAAM,aAAa,OAAO;AAC1C,mBAAO,YAAY;AAAA,UACrB,GAAG,SAAS;AAAA,QACd,CAAC;AAED,eAAO;AAAA,UACL;AAAA,UACA,QAAQ,MAAM,aAAa,SAAS;AAAA,QACtC;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOQ,mBACN,KAC+D;AAC/D,YAAI,OAAO,QAAQ,UAAU;AAC3B,iBAAO,EAAE,QAAQ,KAAK,MAAM,EAAE;AAAA,QAChC;AAEA,YAAI,WAAW,OAAO,IAAI,OAAO;AAC/B,iBAAO,EAAE,QAAQ,IAAI,QAAQ,OAAO,IAAI,OAAO,MAAM,IAAI,QAAQ,EAAE;AAAA,QACrE;AACA,eAAO,EAAE,QAAQ,IAAI,QAAQ,MAAM,IAAI,QAAQ,EAAE;AAAA,MACnD;AAAA;AAAA,MAGA,MAAM,QAAQ,MAAwD;AACpE,cAAM,YAAY,KAAK,IAAI;AAE3B,aAAK,OAAO,MAAM,oBAAoB;AAAA,UACpC,YAAY,KAAK;AAAA,UACjB,cAAc,KAAK;AAAA,UACnB,YAAY,KAAK;AAAA,QACnB,CAAC;AAED,cAAM,gBAAyC,KAAK,cAAc,CAAC;AACnE,YAAI,sBAA+C;AAEnD,YAAI;AAEF,gBAAM,SAAS,KAAK,SAAS,IAAI,KAAK,UAAU;AAChD,cAAI,CAAC,QAAQ;AACX,iBAAK,OAAO,MAAM,oBAAoB,EAAE,YAAY,KAAK,WAAW,CAAC;AACrE,kBAAM,mBAAmB,KAAK,SAAS,SAAS;AAChD,mBAAO;AAAA,cACL,YAAY,KAAK;AAAA,cACjB,cAAc,KAAK;AAAA,cACnB,YAAY,KAAK,cAAc,CAAC;AAAA,cAChC,OAAO,KAAK,eAAe,oBAAoB,KAAK,YAAY,gBAAgB;AAAA,cAChF,iBAAiB,KAAK,IAAI,IAAI;AAAA,YAChC;AAAA,UACF;AAGA,cAAI,KAAK,cAAc,CAAC,KAAK,YAAY;AACvC,iBAAK,OAAO,MAAM,gCAAgC;AAAA,cAChD,YAAY,KAAK;AAAA,cACjB,YAAY,KAAK;AAAA,cACjB,eAAe,KAAK;AAAA,YACtB,CAAC;AACD,kBAAM,oBAAoB,KAAK,cAAc;AAC7C,mBAAO;AAAA,cACL,YAAY,KAAK;AAAA,cACjB,cAAc,KAAK;AAAA,cACnB,YAAY,CAAC;AAAA,cACb,OAAO,KAAK,eAAe,iBAAiB,KAAK,YAAY,mBAAmB,MAAM;AAAA,cACtF,iBAAiB,KAAK,IAAI,IAAI;AAAA,YAChC;AAAA,UACF;AAQA,cAAI,wBAAiD;AACrD,gBAAM,iBAAiB,KAAK,eAAe,SAAS,KAAK,SAAS;AAClE,cAAI,OAAO,mBAAmB,gBAAgB;AAC5C,gBAAI;AACF,oBAAM,aAAa,oBAAoB,KAAK,aAAa;AAGzD,oBAAM,eAAe,iBAAiB,YAAY,EAAE,WAAW,KAAK,UAAU,CAAC;AAI/E,oBAAM,yBAAyB,KAAC,uBAAAC,SAAM,eAAe,YAAY;AAEjE,kBAAI,wBAAwB;AAE1B,qBAAK,OAAO,MAAM,yDAAyD;AAAA,kBACzE,YAAY,KAAK;AAAA,gBACnB,CAAC;AACD,wCAAwB;AAAA,cAC1B,OAAO;AAEL,wCAAwB,iBAAiB,YAAY;AAAA,kBACnD,WAAW,KAAK;AAAA,kBAChB,QAAQ,OAAO;AAAA,gBACjB,CAAC;AACD,qBAAK,OAAO,MAAM,oCAAoC;AAAA,kBACpD,YAAY,KAAK;AAAA,kBACjB,UAAU;AAAA,kBACV,aAAa;AAAA,gBACf,CAAC;AAAA,cACH;AAAA,YACF,SAAS,OAAO;AAGd,mBAAK,OAAO,KAAK,6DAA6D;AAAA,gBAC5E,YAAY,KAAK;AAAA,gBACjB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,cAC9D,CAAC;AACD,sCAAwB;AAAA,YAC1B;AAAA,UACF;AAEA,cAAI,OAAO,iBAAiB;AAC1B,kBAAM,mBAAmB,OAAO,gBAAgB,UAAU,qBAAqB;AAC/E,gBAAI,CAAC,iBAAiB,SAAS;AAC7B,oBAAM,kBAAkB,KAAK,eAAe;AAAA,gBAC1C,KAAK;AAAA,gBACL,iBAAiB;AAAA,gBACjB;AAAA,cACF;AACA,mBAAK,OAAO,MAAM,sCAAsC;AAAA,gBACtD,YAAY,KAAK;AAAA,gBACjB,YAAY,iBAAiB,MAAM,OAAO;AAAA,cAC5C,CAAC;AAED,qBAAO;AAAA,gBACL,YAAY,KAAK;AAAA,gBACjB,cAAc,KAAK;AAAA,gBACnB,YAAY;AAAA,gBACZ,OAAO;AAAA,gBACP,iBAAiB,KAAK,IAAI,IAAI;AAAA,cAChC;AAAA,YACF;AAEA,kCAAsB,iBAAiB;AAAA,UACzC,OAAO;AAEL,kCAAsB;AAAA,UACxB;AAIA,gBAAM,kBAAkB,KAAK,iBAAiB,KAAK,UAAU,GAAG;AAChE,gBAAM,YAAY,mBAAmB,OAAO,aAAa,KAAK;AAI9D,gBAAM,kBAAkB,IAAI,gBAAgB;AAG5C,cAAI,eAAe;AACnB,gBAAM,aAAa,CAAC,WAAmB;AACrC,gBAAI,SAAS,GAAG;AACd,8BAAgB;AAChB,mBAAK,OAAO,MAAM,qCAAqC;AAAA,gBACrD,YAAY,KAAK;AAAA,gBACjB;AAAA,gBACA,mBAAmB;AAAA,cACrB,CAAC;AAAA,YACH;AAAA,UACF;AAIA,gBAAM,eAAe,KAAK,MAAM,sBAAsB,KAAK,YAAY,GAAG;AAC1E,gBAAM,cAAc,eAChB,KAAK,MAAM,QAAQ,YAAY,GAAG,SAAS,KAAK,YAChD,KAAK;AAET,gBAAM,MAAwB;AAAA,YAC5B;AAAA,YACA,QAAQ,KAAK,SAAS,IAAI,2BAA2B,KAAK,QAAQ,UAAU,IAAI;AAAA,YAChF,QAAQ,gBAAgB;AAAA,YACxB,aAAa,KAAK;AAAA,YAClB,gBAAgB,KAAK;AAAA,YACrB,cAAc,KAAK;AAAA,YACnB,iBAAiB,KAAK;AAAA;AAAA,YAEtB,MAAM,KAAK;AAAA,YACX,QAAQ;AAAA,YACR,OAAO;AAAA;AAAA,YAEP,aAAa,uBAAuB;AAAA;AAAA,YAEpC,QAAQ,KAAK;AAAA;AAAA,YAEb,mBAAmB,KAAK;AAAA,UAC1B;AAGA,cAAI;AACJ,cAAI,aAAa,YAAY,GAAG;AAE9B,iBAAK,OAAO,MAAM,iCAAiC;AAAA,cACjD,YAAY,KAAK;AAAA,cACjB;AAAA,YACF,CAAC;AACD,kBAAM,UAAU,KAAK,qBAAqB,KAAK,YAAY,WAAW,eAAe;AACrF,gBAAI;AACF,0BAAY,MAAM,QAAQ,KAAK;AAAA,gBAC7B,QAAQ,QAAQ,OAAO,QAAQ,qBAAqB,GAAG,CAAC;AAAA,gBACxD,QAAQ;AAAA,cACV,CAAC;AAAA,YACH,UAAE;AAEA,sBAAQ,OAAO;AAAA,YACjB;AAAA,UACF,OAAO;AAEL,wBAAY,MAAM,QAAQ,QAAQ,OAAO,QAAQ,qBAAqB,GAAG,CAAC;AAAA,UAC5E;AAGA,gBAAM,EAAE,QAAQ,OAAO,MAAM,WAAW,IAAI,KAAK,mBAAmB,SAAS;AAG7E,gBAAM,YAAY,eAAe;AAGjC,cAAI;AACJ,cAAI;AACJ,cAAI,SAAS,MAAM,SAAS,KAAK,KAAK,YAAY;AAChD,0BAAc,MAAM,QAAQ;AAAA,cAC1B,MAAM,IAAI,CAAC,SAAS,KAAK,WAAY,MAAM,MAAM,KAAK,UAAU,CAAC;AAAA,YACnE;AACA,uBAAW,YAAY,IAAI,CAAC,MAAM,EAAE,EAAE;AACtC,iBAAK,OAAO,MAAM,wBAAwB;AAAA,cACxC,YAAY,KAAK;AAAA,cACjB;AAAA,cACA,OAAO,MAAM;AAAA,YACf,CAAC;AAAA,UACH;AAEA,gBAAM,kBAAkB,KAAK,IAAI,IAAI;AACrC,eAAK,OAAO,KAAK,gCAAgC;AAAA,YAC/C,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB;AAAA,YACA,MAAM,YAAY,IAAI,YAAY;AAAA,YAClC,cAAc,eAAe,IAAI,eAAe;AAAA,YAChD,YAAY,aAAa,IAAI,aAAa;AAAA,YAC1C,YAAY,OAAO;AAAA,UACrB,CAAC;AAED,eAAK,OAAO,MAAM,iBAAiB;AAAA,YACjC,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB,YAAY;AAAA,YACZ;AAAA,YACA,MAAM;AAAA,YACN;AAAA,YACA;AAAA,UACF,CAAC;AAED,iBAAO;AAAA,YACL,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB,YAAY;AAAA,YACZ;AAAA,YACA;AAAA,YACA,MAAM;AAAA,YACN;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AAEd,cAAI,iBAAiB,sBAAsB;AACzC,iBAAK,OAAO,KAAK,qCAAqC;AAAA,cACpD,YAAY,KAAK;AAAA,cACjB,SAAS,MAAM;AAAA,YACjB,CAAC;AACD,mBAAO;AAAA,cACL,YAAY,KAAK;AAAA,cACjB,cAAc,KAAK;AAAA,cACnB,YAAY;AAAA,cACZ,QAAQ,MAAM;AAAA,cACd,YAAY;AAAA,cACZ,iBAAiB,KAAK,IAAI,IAAI;AAAA,YAChC;AAAA,UACF;AAGA,cAAI,iBAAiB,kBAAkB;AACrC,iBAAK,OAAO,MAAM,8BAA8B;AAAA,cAC9C,YAAY,KAAK;AAAA,cACjB,WAAW,MAAM;AAAA,cACjB,iBAAiB,KAAK,IAAI,IAAI;AAAA,YAChC,CAAC;AACD,mBAAO;AAAA,cACL,YAAY,KAAK;AAAA,cACjB,cAAc,KAAK;AAAA,cACnB,YAAY;AAAA,cACZ,OAAO,MAAM;AAAA,cACb,iBAAiB,KAAK,IAAI,IAAI;AAAA,YAChC;AAAA,UACF;AAGA,cAAI,iBAAiB,gBAAgB;AACnC,iBAAK,OAAO,KAAK,gCAAgC;AAAA,cAC/C,YAAY,KAAK;AAAA,cACjB,iBAAiB,KAAK,IAAI,IAAI;AAAA,YAChC,CAAC;AACD,mBAAO;AAAA,cACL,YAAY,KAAK;AAAA,cACjB,cAAc,KAAK;AAAA,cACnB,YAAY;AAAA,cACZ,OAAO,MAAM;AAAA,cACb,iBAAiB,KAAK,IAAI,IAAI;AAAA,YAChC;AAAA,UACF;AAIA,gBAAM,oBACJ,iBAAiB,SACjB,MAAM,SAAS,iCACf,cAAc;AAChB,cAAI,mBAAmB;AACrB,kBAAM,WAAY,MAAsC;AACxD,iBAAK,OAAO,KAAK,gCAAgC;AAAA,cAC/C,YAAY,KAAK;AAAA,cACjB;AAAA,YACF,CAAC;AAGD,gBAAI,KAAK,mBAAmB;AAC1B,kBAAI;AACF,sBAAM,SAAS,MAAM,KAAK,kBAAkB,QAAQ;AACpD,qBAAK,OAAO,MAAM,wBAAwB;AAAA,kBACxC,YAAY,KAAK;AAAA,kBACjB,cAAc,OAAO;AAAA,gBACvB,CAAC;AACD,uBAAO;AAAA,kBACL,YAAY,KAAK;AAAA,kBACjB,cAAc,KAAK;AAAA,kBACnB,YAAY;AAAA,kBACZ,QAAQ;AAAA,kBACR,iBAAiB,KAAK,IAAI,IAAI;AAAA,gBAChC;AAAA,cACF,SAAS,YAAY;AACnB,qBAAK,OAAO,MAAM,8BAA8B;AAAA,kBAC9C,YAAY,KAAK;AAAA,kBACjB,OAAO,sBAAsB,QAAQ,WAAW,UAAU,OAAO,UAAU;AAAA,gBAC7E,CAAC;AACD,uBAAO;AAAA,kBACL,YAAY,KAAK;AAAA,kBACjB,cAAc,KAAK;AAAA,kBACnB,YAAY;AAAA,kBACZ,OAAO,sBAAsB,QAAQ,WAAW,UAAU,OAAO,UAAU;AAAA,kBAC3E,iBAAiB,KAAK,IAAI,IAAI;AAAA,gBAChC;AAAA,cACF;AAAA,YACF;AAGA,iBAAK,OAAO,KAAK,iDAAiD;AAAA,cAChE,YAAY,KAAK;AAAA,YACnB,CAAC;AACD,mBAAO;AAAA,cACL,YAAY,KAAK;AAAA,cACjB,cAAc,KAAK;AAAA,cACnB,YAAY;AAAA,cACZ,OAAO;AAAA,cACP,iBAAiB,KAAK,IAAI,IAAI;AAAA,YAChC;AAAA,UACF;AAEA,gBAAM,kBAAkB,KAAK,IAAI,IAAI;AACrC,eAAK,OAAO,MAAM,2BAA2B;AAAA,YAC3C,YAAY,KAAK;AAAA,YACjB,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAC5D;AAAA,UACF,CAAC;AAED,iBAAO;AAAA,YACL,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB,YAAY;AAAA,YACZ,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAC5D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA;AAAA,MAGA,MAAM,WAAW,OAA6D;AAC5E,eAAO,QAAQ,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC;AAAA,MAC5D;AAAA,IAEF;AAAA;AAAA;;;AClfA,IA4Ka;AA5Kb;AAAA;AAAA;AAWA;AAEA;AAYA;AACA;AAkJO,IAAM,kBAAN,MAAsB;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA;AAAA,MACA;AAAA,MACA;AAAA,MAET,eAAe;AAAA,MACf,uBAAuB;AAAA;AAAA;AAAA,MAIvB,8BAA6D,oBAAI,IAAI;AAAA;AAAA,MAErE,mBAAuD,oBAAI,IAAI;AAAA;AAAA,MAE/D,oBAAiC,oBAAI,IAAI;AAAA;AAAA,MAEzC,qBAAiD,oBAAI,IAAI;AAAA;AAAA,MAEzD,wBAAuC,CAAC;AAAA;AAAA;AAAA,MAI/B;AAAA;AAAA,MAEA;AAAA,MAEjB,YAAY,SAAiC;AAC3C,aAAK,YAAY,QAAQ;AACzB,aAAK,WAAW,QAAQ;AACxB,aAAK,QAAQ,QAAQ,SAAS,CAAC;AAC/B,aAAK,SAAS,QAAQ,UAAU,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGhF,aAAK,OAAO,QAAQ;AACpB,aAAK,eAAe,QAAQ,gBAAgB;AAC5C,aAAK,YAAY,QAAQ,aAAa;AAGtC,aAAK,4BAA4B,QAAQ,6BAA6B,oBAAI,IAAI;AAC9E,aAAK,yBAAyB,QAAQ,0BAA0B,oBAAI,IAAI;AAExE,aAAK,SAAS,IAAI,iBAAiB;AAAA,UACjC,aAAa,QAAQ;AAAA,UACrB,WAAW,QAAQ;AAAA,UACnB,WAAW,QAAQ;AAAA,QACrB,CAAC;AAKD,cAAM,yBAAyB,QAAQ,kBACnC,CAAC,UAAyB;AAExB,eAAK,sBAAsB,KAAK;AAAA,YAC9B,MAAM;AAAA,YACN,eAAe;AAAA,UACjB,CAAC;AAED,kBAAQ,kBAAkB,KAAK;AAAA,QACjC,IACA;AAEJ,aAAK,WAAW,IAAI;AAAA,UAClB,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,KAAK,OAAO,aAAa,EAAE,MAAM,WAAW,CAAC;AAAA,UAC7C,QAAQ;AAAA,UACR,EAAE,WAAW,QAAQ,gBAAgB;AAAA,UACrC,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR;AAAA;AAAA,UAEA,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,QAAQ;AAAA,QACV;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYA,OAAO,QAAQC,SAAoE;AACjF,YAAI,eAA8B;AAClC,YAAI;AACJ,YAAI,oBAAoB;AACxB,YAAI,kBAAkB;AAGtB,yBAAiB,SAASA,SAAQ;AAEhC,cAAI,MAAM,aAAc,gBAAe,MAAM;AAC7C,cAAI,MAAM,MAAO,SAAQ,MAAM;AAG/B,cAAI,iBAAiB;AACrB,cAAI,MAAM,MAAM;AAEd,6BAAiB,MAAM;AACvB,gBAAI,KAAK,MAAM,cAAc,mBAAmB;AAC9C,oBAAM,UAAmC;AAAA,gBACvC,WAAW,KAAK;AAAA,gBAChB,iBAAiB,KAAK;AAAA,gBACtB,QAAQ,KAAK;AAAA,cACf;AACA,oBAAM,cAAc,KAAK,MAAM,aAAa,kBAAkB,gBAAgB,OAAO;AACrF,kBAAI,gBAAgB,MAAM;AAExB,iCAAiB;AAAA,cACnB,OAAO;AACL,iCAAiB;AAAA,cACnB;AAAA,YACF;AAGA,gBAAI,gBAAgB;AAClB,mBAAK,gBAAgB;AAAA,YACvB;AAAA,UACF;AAGA,cAAI,KAAK,MAAM,WAAW,kBAAkB,kBAAkB,MAAM,QAAQ;AAC1E,kBAAM,iBAAoD,CAAC;AAC3D,2BAAe,KAAK,YAAY;AAC9B,oBAAM,UAA+B;AAAA,gBACnC,WAAW,KAAK;AAAA,gBAChB,UAAU;AAAA,gBACV,iBAAiB,KAAK;AAAA,gBACtB;AAAA,gBACA,QAAQ,KAAK;AAAA,cACf;AACA,oBAAM,KAAK,MAAM,WAAW,gBAAgB,OAAO;AAAA,YACrD,CAAC;AACD,kBAAM,KAAK,uBAAuB,cAAc;AAAA,UAClD;AAGA,cAAI,CAAC,gBAAgB;AACnB;AAAA,UACF;AAGA,qBAAW,SAAS,KAAK,OAAO,KAAK,cAAc,GAAG;AACpD,6BAAiB,kBAAkB,KAAK,sBAAsB,KAAK,GAAG;AACpE,oBAAM;AAGN,kBAAI,eAAe,SAAS,iBAAiB;AAC3C,oCAAoB;AACpB,oBAAI,eAAe,OAAO,YAAY;AACpC,oCAAkB;AAAA,gBACpB;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAIA,qBAAW,OAAO,KAAK,sBAAsB,GAAG;AAC9C,kBAAM;AAEN,gBAAI,IAAI,SAAS,iBAAiB;AAChC,kCAAoB;AACpB,kBAAI,IAAI,OAAO,YAAY;AACzB,kCAAkB;AAAA,cACpB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAGA,mBAAW,SAAS,KAAK,OAAO,SAAS,GAAG;AAC1C,2BAAiB,kBAAkB,KAAK,sBAAsB,KAAK,GAAG;AACpE,kBAAM;AAEN,gBAAI,eAAe,SAAS,iBAAiB;AAC3C,kCAAoB;AACpB,kBAAI,eAAe,OAAO,YAAY;AACpC,kCAAkB;AAAA,cACpB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAIA,yBAAiB,OAAO,KAAK,0BAA0B,GAAG;AACxD,gBAAM;AAEN,cAAI,IAAI,SAAS,iBAAiB;AAChC,gCAAoB;AACpB,gBAAI,IAAI,OAAO,YAAY;AACzB,gCAAkB;AAAA,YACpB;AAAA,UACF;AAAA,QACF;AAGA,mBAAW,OAAO,KAAK,sBAAsB,GAAG;AAC9C,gBAAM;AAEN,cAAI,IAAI,SAAS,iBAAiB;AAChC,gCAAoB;AACpB,gBAAI,IAAI,OAAO,YAAY;AACzB,gCAAkB;AAAA,YACpB;AAAA,UACF;AAAA,QACF;AAKA,yBAAiB,OAAO,KAAK,+BAA+B,GAAG;AAC7D,gBAAM;AAEN,cAAI,IAAI,SAAS,iBAAiB;AAChC,gCAAoB;AACpB,gBAAI,IAAI,OAAO,YAAY;AACzB,gCAAkB;AAAA,YACpB;AAAA,UACF;AAAA,QACF;AAGA,YAAI,eAAe,KAAK;AACxB,YAAI,KAAK,MAAM,cAAc,2BAA2B;AACtD,gBAAM,UAAqC;AAAA,YACzC,WAAW,KAAK;AAAA,YAChB,aAAa,KAAK;AAAA,YAClB,QAAQ,KAAK;AAAA,UACf;AACA,yBAAe,KAAK,MAAM,aAAa,0BAA0B,cAAc,OAAO;AAAA,QACxF;AAGA,cAAM,kBAAyC;AAAA,UAC7C,MAAM;AAAA,UACN;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,aAAa,KAAK;AAAA,UAClB;AAAA,QACF;AACA,cAAM;AAAA,MACR;AAAA;AAAA;AAAA;AAAA,MAKA,OAAe,sBAAsB,OAAiD;AACpF,YAAI,MAAM,SAAS,QAAQ;AAEzB,qBAAW,KAAK,MAAM,KAAK,iBAAiB,KAAK,GAAG;AAClD,kBAAM;AAAA,UACR;AAAA,QACF,WAAW,MAAM,SAAS,eAAe;AACvC,2BAAiB,KAAK,KAAK,2BAA2B,MAAM,IAAI,GAAG;AACjE,kBAAM;AAAA,UACR;AAAA,QACF,OAAO;AACL,gBAAM;AAAA,QACR;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,iBAAiB,OAAkE;AAC/F,YAAI,UAAU,MAAM;AAGpB,YAAI,KAAK,MAAM,cAAc,oBAAoB;AAC/C,gBAAM,UAAmC;AAAA,YACvC,WAAW,KAAK;AAAA,YAChB,iBAAiB,KAAK;AAAA,YACtB,QAAQ,KAAK;AAAA,UACf;AACA,gBAAM,cAAc,KAAK,MAAM,aAAa,mBAAmB,SAAS,OAAO;AAC/E,cAAI,gBAAgB,MAAM;AAExB,mBAAO,CAAC;AAAA,UACV;AACA,oBAAU;AAAA,QACZ;AAEA,eAAO,CAAC,EAAE,MAAM,QAAQ,QAAQ,CAAC;AAAA,MACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,OAAe,2BAA2B,MAAqD;AAE7F,cAAM,EAAE,MAAM,eAAe,KAAK;AAGlC,YAAI,KAAK,MAAM;AACb,eAAK,KAAK,UAAU;AAAA,YAClB,cAAc,KAAK;AAAA,YACnB,MAAM,KAAK;AAAA,YACX,YAAY,KAAK,cAAc,CAAC;AAAA,YAChC,cAAc,KAAK;AAAA,YACnB,UAAU,KAAK;AAAA,UACjB,CAAC;AAAA,QACH;AAGA,YAAI,KAAK,aAAa,SAAS,GAAG;AAEhC,cAAI,KAAK,aAAa,SAAS,KAAK,YAAY,GAAG;AACjD,iBAAK,OAAO,KAAK,8DAA8D;AAAA,cAC7E,YAAY,KAAK;AAAA,cACjB,cAAc,KAAK;AAAA,YACrB,CAAC;AACD,iBAAK,kBAAkB,IAAI,KAAK,YAAY;AAC5C,kBAAM,YAAgC;AAAA,cACpC,MAAM;AAAA,cACN,YAAY,KAAK;AAAA,cACjB,cAAc,KAAK;AAAA,cACnB,YAAY,KAAK,cAAc,CAAC;AAAA,cAChC,kBAAkB,KAAK;AAAA,cACvB,uBAAuB,WAAW,KAAK,YAAY;AAAA,YACrD;AACA,kBAAM;AACN;AAAA,UACF;AAGA,gBAAM,YAAY,KAAK,aAAa;AAAA,YAClC,CAAC,QAAQ,KAAK,kBAAkB,IAAI,GAAG,KAAK,KAAK,uBAAuB,IAAI,GAAG;AAAA,UACjF;AACA,cAAI,WAAW;AAEb,kBAAM,aAAa,MAAM,KAAK,uBAAuB,MAAM,SAAS;AACpE,uBAAW,OAAO,YAAY;AAC5B,oBAAM;AAAA,YACR;AACA;AAAA,UACF;AAGA,gBAAM,cAAc,KAAK,aAAa;AAAA,YACpC,CAAC,QAAQ,CAAC,KAAK,iBAAiB,IAAI,GAAG,KAAK,CAAC,KAAK,0BAA0B,IAAI,GAAG;AAAA,UACrF;AACA,cAAI,YAAY,SAAS,GAAG;AAE1B,iBAAK,OAAO,MAAM,uDAAuD;AAAA,cACvE,YAAY,KAAK;AAAA,cACjB,cAAc,KAAK;AAAA,cACnB,WAAW;AAAA,YACb,CAAC;AACD,iBAAK,4BAA4B,IAAI,KAAK,cAAc,IAAI;AAC5D;AAAA,UACF;AAGA,2BAAiB,OAAO,KAAK,uBAAuB,IAAI,GAAG;AACzD,kBAAM;AAAA,UACR;AAGA,2BAAiB,OAAO,KAAK,+BAA+B,GAAG;AAC7D,kBAAM;AAAA,UACR;AACA;AAAA,QACF;AAIA,cAAM,mBAAmB,KAAK,wBAAwB,IAAI;AAC1D,aAAK,mBAAmB,IAAI,KAAK,cAAc,gBAAgB;AAAA,MAEjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,OAAe,uBAAuB,MAAqD;AAEzF,YAAI,KAAK,YAAY;AACnB,eAAK,OAAO,KAAK,0BAA0B;AAAA,YACzC,YAAY,KAAK;AAAA,YACjB,OAAO,KAAK;AAAA,YACZ,eAAe,KAAK;AAAA,UACtB,CAAC;AAAA,QACH;AAGA,YAAI,aAAa,KAAK,cAAc,CAAC;AACrC,YAAI,KAAK,MAAM,cAAc,2BAA2B;AACtD,gBAAM,UAA6C;AAAA,YACjD,WAAW,KAAK;AAAA,YAChB,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB,QAAQ,KAAK;AAAA,UACf;AACA,uBAAa,KAAK,MAAM,aAAa,0BAA0B,YAAY,OAAO;AAAA,QACpF;AAGA,aAAK,aAAa;AAGlB,YAAI,aAAa;AACjB,YAAI;AAEJ,YAAI,KAAK,MAAM,aAAa,uBAAuB;AACjD,gBAAM,UAA4C;AAAA,YAChD,WAAW,KAAK;AAAA,YAChB,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB;AAAA,YACA,QAAQ,KAAK;AAAA,UACf;AACA,gBAAM,SACJ,MAAM,KAAK,MAAM,YAAY,sBAAsB,OAAO;AAG5D,8CAAoC,MAAM;AAE1C,cAAI,OAAO,WAAW,QAAQ;AAC5B,yBAAa;AACb,8BAAkB,OAAO;AACzB,iBAAK,OAAO,KAAK,uCAAuC;AAAA,cACtD,YAAY,KAAK;AAAA,YACnB,CAAC;AAAA,UACH;AAAA,QACF;AAGA,cAAM,iBAAoD,CAAC;AAC3D,YAAI,KAAK,MAAM,WAAW,wBAAwB;AAChD,yBAAe,KAAK,YAAY;AAC9B,kBAAM,UAAqC;AAAA,cACzC,WAAW,KAAK;AAAA,cAChB,YAAY,KAAK;AAAA,cACjB,cAAc,KAAK;AAAA,cACnB;AAAA,cACA,QAAQ,KAAK;AAAA,YACf;AACA,kBAAM,KAAK,MAAM,WAAW,yBAAyB,OAAO;AAAA,UAC9D,CAAC;AAAA,QACH;AACA,cAAM,KAAK,uBAAuB,cAAc;AAGhD,YAAI,KAAK,MAAM;AACb,gBAAM,aAAa,KAAK,KAAK,sBAAsB,KAAK,YAAY;AACpE,cAAI,YAAY;AACd,iBAAK,KAAK,YAAY,WAAW,EAAE;AAAA,UACrC;AAAA,QACF;AAGA,YAAI;AACJ,YAAI,YAAY;AACd,mBAAS;AAAA,YACP,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB;AAAA,YACA,QAAQ,mBAAmB;AAAA,YAC3B,iBAAiB;AAAA,UACnB;AAAA,QACF,OAAO;AACL,mBAAS,MAAM,KAAK,SAAS,QAAQ,IAAI;AAAA,QAC3C;AAKA,cAAM,iBAAiB,OAAO;AAG9B,YAAI,OAAO,UAAU,KAAK,MAAM,cAAc,uBAAuB;AACnE,gBAAM,UAA0C;AAAA,YAC9C,WAAW,KAAK;AAAA,YAChB,YAAY,OAAO;AAAA,YACnB,cAAc,OAAO;AAAA,YACrB;AAAA,YACA,iBAAiB,OAAO;AAAA,YACxB,QAAQ,KAAK;AAAA,UACf;AACA,iBAAO,SAAS,KAAK,MAAM,aAAa,sBAAsB,OAAO,QAAQ,OAAO;AAAA,QACtF;AAGA,YAAI,KAAK,MAAM,aAAa,sBAAsB;AAChD,gBAAM,UAAiD;AAAA,YACrD,WAAW,KAAK;AAAA,YAChB,YAAY,OAAO;AAAA,YACnB,cAAc,OAAO;AAAA,YACrB;AAAA,YACA,QAAQ,OAAO;AAAA,YACf,OAAO,OAAO;AAAA,YACd,iBAAiB,OAAO;AAAA,YACxB,QAAQ,KAAK;AAAA,UACf;AACA,gBAAM,SACJ,MAAM,KAAK,MAAM,YAAY,qBAAqB,OAAO;AAG3D,6CAAmC,MAAM;AAEzC,cAAI,OAAO,WAAW,aAAa,OAAO,OAAO;AAC/C,iBAAK,OAAO,KAAK,0CAA0C;AAAA,cACzD,YAAY,OAAO;AAAA,cACnB,eAAe,OAAO;AAAA,YACxB,CAAC;AACD,qBAAS;AAAA,cACP,GAAG;AAAA,cACH,OAAO;AAAA,cACP,QAAQ,OAAO;AAAA,YACjB;AAAA,UACF;AAAA,QACF;AAGA,cAAM,oBAAuD,CAAC;AAC9D,YAAI,KAAK,MAAM,WAAW,2BAA2B;AACnD,4BAAkB,KAAK,YAAY;AACjC,kBAAM,UAAwC;AAAA,cAC5C,WAAW,KAAK;AAAA,cAChB,YAAY,OAAO;AAAA,cACnB,cAAc,OAAO;AAAA,cACrB;AAAA,cACA;AAAA,cACA,aAAa,OAAO;AAAA,cACpB,OAAO,OAAO;AAAA,cACd,iBAAiB,OAAO;AAAA,cACxB,YAAY,OAAO;AAAA,cACnB,MAAM,OAAO;AAAA,cACb,QAAQ,KAAK;AAAA,YACf;AACA,kBAAM,KAAK,MAAM,WAAW,4BAA4B,OAAO;AAAA,UACjE,CAAC;AAAA,QACH;AACA,cAAM,KAAK,uBAAuB,iBAAiB;AAGnD,YAAI,KAAK,MAAM;AACb,gBAAM,aAAa,KAAK,KAAK,sBAAsB,OAAO,YAAY;AACtE,cAAI,YAAY;AACd,gBAAI,OAAO,OAAO;AAChB,mBAAK,KAAK,eAAe,WAAW,IAAI;AAAA,gBACtC,OAAO,OAAO;AAAA,gBACd,iBAAiB,OAAO;AAAA,gBACxB,MAAM,OAAO;AAAA,cACf,CAAC;AAAA,YACH,OAAO;AACL,mBAAK,KAAK,eAAe,WAAW,IAAI;AAAA,gBACtC,QAAQ,OAAO;AAAA,gBACf,iBAAiB,OAAO;AAAA,gBACxB,MAAM,OAAO;AAAA,gBACb,OAAO,OAAO;AAAA,cAChB,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAGA,aAAK,iBAAiB,IAAI,OAAO,cAAc,MAAM;AACrD,YAAI,OAAO,OAAO;AAChB,eAAK,kBAAkB,IAAI,OAAO,YAAY;AAAA,QAChD;AAGA,cAAM,EAAE,MAAM,iBAAiB,OAAO;AAAA,MACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,MAAc,wBAAwB,MAAuC;AAC3E,yBAAiB,OAAO,KAAK,uBAAuB,IAAI,GAAG;AAEzD,eAAK,sBAAsB,KAAK,GAAG;AAAA,QACrC;AAAA,MAIF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,CAAS,wBAAgD;AACvD,eAAO,KAAK,sBAAsB,SAAS,GAAG;AAC5C,gBAAM,KAAK,sBAAsB,MAAM;AAAA,QACzC;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA,OAAe,4BAAyD;AACtE,YAAI,KAAK,mBAAmB,SAAS,GAAG;AACtC;AAAA,QACF;AAEA,aAAK,OAAO,MAAM,2CAA2C;AAAA,UAC3D,OAAO,KAAK,mBAAmB;AAAA,UAC/B,eAAe,MAAM,KAAK,KAAK,mBAAmB,KAAK,CAAC;AAAA,QAC1D,CAAC;AAGD,cAAM,UAAU,QAAQ,IAAI,KAAK,mBAAmB,OAAO,CAAC,EAAE,KAAK,MAAM,MAAe;AAGxF,cAAM,mBAAmB;AAGzB,eAAO,MAAM;AAEX,gBAAM,SAAS,MAAM,QAAQ,KAAK;AAAA,YAChC;AAAA,YACA,IAAI,QAAgB,CAAC,YAAY,WAAW,MAAM,QAAQ,MAAM,GAAG,gBAAgB,CAAC;AAAA,UACtF,CAAC;AAGD,iBAAO,KAAK,sBAAsB;AAElC,cAAI,WAAW,QAAQ;AAErB;AAAA,UACF;AAAA,QAEF;AAGA,aAAK,mBAAmB,MAAM;AAAA,MAChC;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAc,uBACZ,MACA,WACwB;AACxB,cAAM,SAAwB,CAAC;AAC/B,cAAM,YAAY,KAAK,iBAAiB,IAAI,SAAS;AACrD,cAAM,WAAW,WAAW,SAAS;AAGrC,YAAI,SAA+B,EAAE,QAAQ,OAAO;AACpD,YAAI,KAAK,MAAM,aAAa,qBAAqB;AAC/C,gBAAM,UAA2C;AAAA,YAC/C,WAAW,KAAK;AAAA,YAChB,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB,YAAY,KAAK,cAAc,CAAC;AAAA,YAChC,kBAAkB;AAAA,YAClB,uBAAuB;AAAA,YACvB,QAAQ,KAAK;AAAA,UACf;AACA,mBAAS,MAAM,KAAK,MAAM,YAAY,oBAAoB,OAAO;AAAA,QACnE;AAEA,YAAI,OAAO,WAAW,QAAQ;AAE5B,eAAK,kBAAkB,IAAI,KAAK,YAAY;AAG5C,cAAI,KAAK,MAAM;AACb,kBAAM,aAAa,KAAK,KAAK,sBAAsB,KAAK,YAAY;AACpE,gBAAI,YAAY;AACd,mBAAK,KAAK,WAAW,WAAW,IAAI,WAAW,UAAU,mBAAmB;AAAA,YAC9E;AAAA,UACF;AAGA,gBAAM,YAAgC;AAAA,YACpC,MAAM;AAAA,YACN,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB,YAAY,KAAK,cAAc,CAAC;AAAA,YAChC,kBAAkB;AAAA,YAClB,uBAAuB;AAAA,UACzB;AACA,iBAAO,KAAK,SAAS;AAGrB,cAAI,KAAK,MAAM,WAAW,iBAAiB;AACzC,kBAAM,iBAA8C;AAAA,cAClD,WAAW,KAAK;AAAA,cAChB,YAAY,KAAK;AAAA,cACjB,cAAc,KAAK;AAAA,cACnB,YAAY,KAAK,cAAc,CAAC;AAAA,cAChC,kBAAkB;AAAA,cAClB,uBAAuB;AAAA,cACvB,QAAQ,KAAK;AAAA,YACf;AACA,kBAAM,KAAK,YAAY,MAAM,KAAK,MAAM,WAAW,kBAAkB,cAAc,CAAC;AAAA,UACtF;AAEA,eAAK,OAAO,KAAK,2CAA2C;AAAA,YAC1D,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB,kBAAkB;AAAA,UACpB,CAAC;AAAA,QACH,WAAW,OAAO,WAAW,kBAAkB;AAE7C,eAAK,OAAO,KAAK,oEAAoE;AAAA,YACnF,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB,kBAAkB;AAAA,UACpB,CAAC;AACD,2BAAiB,OAAO,KAAK,uBAAuB,IAAI,GAAG;AACzD,mBAAO,KAAK,GAAG;AAAA,UACjB;AAAA,QACF,WAAW,OAAO,WAAW,gBAAgB;AAE3C,gBAAM,iBAAwC;AAAA,YAC5C,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB,YAAY,KAAK,cAAc,CAAC;AAAA,YAChC,QAAQ,OAAO;AAAA,YACf,iBAAiB;AAAA,UACnB;AACA,eAAK,iBAAiB,IAAI,KAAK,cAAc,cAAc;AAC3D,iBAAO,KAAK,EAAE,MAAM,iBAAiB,QAAQ,eAAe,CAAC;AAE7D,eAAK,OAAO,KAAK,2DAA2D;AAAA,YAC1E,YAAY,KAAK;AAAA,YACjB,cAAc,KAAK;AAAA,YACnB,kBAAkB;AAAA,UACpB,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASA,OAAe,iCAA8D;AAC3E,YAAI,WAAW;AAEf,eAAO,YAAY,KAAK,4BAA4B,OAAO,GAAG;AAC5D,qBAAW;AAGX,gBAAM,iBAAqC,CAAC;AAC5C,gBAAM,cAAoE,CAAC;AAE3E,qBAAW,CAAC,eAAe,IAAI,KAAK,KAAK,6BAA6B;AAEpE,kBAAM,YAAY,KAAK,aAAa;AAAA,cAClC,CAAC,QAAQ,KAAK,kBAAkB,IAAI,GAAG,KAAK,KAAK,uBAAuB,IAAI,GAAG;AAAA,YACjF;AACA,gBAAI,WAAW;AACb,0BAAY,KAAK,EAAE,MAAM,UAAU,CAAC;AACpC;AAAA,YACF;AAGA,kBAAM,eAAe,KAAK,aAAa;AAAA,cACrC,CAAC,QAAQ,KAAK,iBAAiB,IAAI,GAAG,KAAK,KAAK,0BAA0B,IAAI,GAAG;AAAA,YACnF;AACA,gBAAI,cAAc;AAChB,6BAAe,KAAK,IAAI;AAAA,YAC1B;AAAA,UACF;AAGA,qBAAW,EAAE,MAAM,UAAU,KAAK,aAAa;AAC7C,iBAAK,4BAA4B,OAAO,KAAK,YAAY;AACzD,kBAAM,aAAa,MAAM,KAAK,uBAAuB,MAAM,SAAS;AACpE,uBAAW,OAAO,YAAY;AAC5B,oBAAM;AAAA,YACR;AACA,uBAAW;AAAA,UACb;AAGA,cAAI,eAAe,SAAS,GAAG;AAC7B,iBAAK,OAAO,MAAM,uCAAuC;AAAA,cACvD,OAAO,eAAe;AAAA,cACtB,eAAe,eAAe,IAAI,CAAC,MAAM,EAAE,YAAY;AAAA,YACzD,CAAC;AAGD,uBAAW,QAAQ,gBAAgB;AACjC,mBAAK,4BAA4B,OAAO,KAAK,YAAY;AAAA,YAC3D;AAGA,kBAAM,YAAY,MAAM,QAAQ;AAAA,cAC9B,eAAe,IAAI,OAAO,SAAS;AACjC,sBAAM,SAAwB,CAAC;AAC/B,iCAAiB,OAAO,KAAK,uBAAuB,IAAI,GAAG;AACzD,yBAAO,KAAK,GAAG;AAAA,gBACjB;AACA,uBAAO;AAAA,cACT,CAAC;AAAA,YACH;AAGA,uBAAW,UAAU,WAAW;AAC9B,yBAAW,OAAO,QAAQ;AACxB,sBAAM;AAAA,cACR;AAAA,YACF;AAEA,uBAAW;AAAA,UACb;AAAA,QACF;AAGA,YAAI,KAAK,4BAA4B,OAAO,GAAG;AAE7C,gBAAM,aAAa,IAAI,IAAI,KAAK,4BAA4B,KAAK,CAAC;AAElE,qBAAW,CAAC,cAAc,IAAI,KAAK,KAAK,6BAA6B;AAEnE,kBAAM,cAAc,KAAK,aAAa;AAAA,cACpC,CAAC,QAAQ,CAAC,KAAK,iBAAiB,IAAI,GAAG,KAAK,CAAC,KAAK,0BAA0B,IAAI,GAAG;AAAA,YACrF;AAGA,kBAAM,eAAe,YAAY,OAAO,CAAC,QAAQ,WAAW,IAAI,GAAG,CAAC;AACpE,kBAAM,mBAAmB,YAAY,OAAO,CAAC,QAAQ,CAAC,WAAW,IAAI,GAAG,CAAC;AAEzE,gBAAI;AACJ,gBAAI,WAA6B;AAEjC,gBAAI,aAAa,SAAS,KAAK,iBAAiB,SAAS,GAAG;AAC1D,6BAAe,wCAAwC,aAAa,KAAK,IAAI,CAAC,eAAe,iBAAiB,KAAK,IAAI,CAAC;AACxH,yBAAW;AAAA,YACb,WAAW,aAAa,SAAS,GAAG;AAClC,6BAAe,kCAAkC,YAAY,iBAAiB,aAAa,CAAC,CAAC,4BAA4B,YAAY;AAAA,YACvI,OAAO;AACL,6BAAe,eAAe,YAAY,CAAC,CAAC;AAAA,YAC9C;AAEA,iBAAK,OAAO,QAAQ,EAAE,wCAAwC;AAAA,cAC5D,YAAY,KAAK;AAAA,cACjB;AAAA,cACA,sBAAsB;AAAA,cACtB,qBAAqB;AAAA,YACvB,CAAC;AAGD,iBAAK,kBAAkB,IAAI,YAAY;AACvC,kBAAM,YAAgC;AAAA,cACpC,MAAM;AAAA,cACN,YAAY,KAAK;AAAA,cACjB;AAAA,cACA,YAAY,KAAK,cAAc,CAAC;AAAA,cAChC,kBAAkB,YAAY,CAAC;AAAA,cAC/B,uBAAuB;AAAA,YACzB;AACA,kBAAM;AAAA,UACR;AACA,eAAK,4BAA4B,MAAM;AAAA,QACzC;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAc,YAAY,IAA+C;AACvE,YAAI;AACF,gBAAM,GAAG;AAAA,QACX,SAAS,OAAO;AACd,eAAK;AACL,eAAK,OAAO,MAAM,mCAAmC;AAAA,YACnD,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAC5D,cAAc,KAAK;AAAA,UACrB,CAAC;AAAA,QACH;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAc,uBACZ,WACe;AACf,YAAI,UAAU,WAAW,EAAG;AAI5B,cAAM,QAAQ;AAAA,UACZ,UAAU,IAAI,CAAC,aAAa,KAAK,YAAY,QAAQ,CAAC;AAAA,QACxD;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA,4BAAyC;AACvC,eAAO,IAAI,IAAI,KAAK,iBAAiB,KAAK,CAAC;AAAA,MAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,yBAAsC;AACpC,eAAO,IAAI,IAAI,KAAK,iBAAiB;AAAA,MACvC;AAAA,IACF;AAAA;AAAA;;;AC7lCA,IAuCA,gBA4Ja;AAnMb;AAAA;AAAA;AASA;AAMA;AAGA;AACA;AAGA;AACA;AAWA;AACA;AAGA;AACA,qBAAmB;AACnB;AACA;AAEA;AACA;AACA;AAoBA;AAkIO,IAAM,QAAN,MAAY;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAKA;AAAA,MACA;AAAA,MACT;AAAA;AAAA,MAGS;AAAA,MACA;AAAA,MACA;AAAA;AAAA,MAGA;AAAA;AAAA,MAGA;AAAA;AAAA,MAGA;AAAA;AAAA,MAGA;AAAA;AAAA,MAGA;AAAA,MACA;AAAA;AAAA,MAGA;AAAA;AAAA,MAEA,wBAAyC,CAAC;AAAA;AAAA,MAE1C;AAAA;AAAA,MAET,6BAA6B;AAAA;AAAA,MAGpB,yBAAsC,oBAAI,IAAI;AAAA,MAC9C,sBAAmC,oBAAI,IAAI;AAAA;AAAA,MAG3C,sBAAgC,CAAC;AAAA;AAAA,MAGjC;AAAA,MACA;AAAA,MACA;AAAA;AAAA;AAAA;AAAA;AAAA,MAMjB,YAAY,KAAgC,SAAuB;AACjE,YAAI,CAAC,gBAAgB,GAAG,GAAG;AACzB,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,aAAK,SAAS,QAAQ;AACtB,aAAK,QAAQ,aAAa,QAAQ,KAAK;AACvC,aAAK,gBAAgB,QAAQ,iBAAiB;AAC9C,aAAK,cAAc,QAAQ;AAC3B,aAAK,SAAS,QAAQ,UAAU,aAAa,EAAE,MAAM,eAAe,CAAC;AACrE,aAAK,WAAW,QAAQ;AACxB,aAAK,oBAAoB,QAAQ;AACjC,aAAK,kBAAkB,QAAQ;AAC/B,aAAK,kBAAkB,QAAQ;AAC/B,aAAK,oBAAoB,QAAQ;AACjC,aAAK,kBAAkB,QAAQ,mBAAmB;AAClD,aAAK,yBAAyB,QAAQ;AACtC,aAAK,yBAAyB,QAAQ;AACtC,aAAK,mBAAmB,KAAK,4BAA4B,QAAQ,KAAK;AAGtE,aAAK,qBAAqB,QAAQ,qBAAqB;AACvD,aAAK,cAAc,IAAI,kBAAkB;AAGzC,aAAK,aAAa,IAAI,WAAW;AAGjC,cAAM,eAAe,QAAQ,4BAA4B;AACzD,cAAM,SAAS,KAAK,OAAO,cAAc,eAAe,KAAK,KAAK;AAClE,cAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,aAAK,uBAAuB,KAAK,MAAM,iBAAiB,eAAe,OAAO,eAAe;AAI7F,YAAI,KAAK,oBAAoB;AAC3B,eAAK,SAAS;AAAA,YACZ;AAAA,YACA,yBAAyB,KAAK,aAAa,KAAK,oBAAoB;AAAA,UACtE;AAAA,QACF;AAGA,aAAK,QAAQ,KAAK,gCAAgC,QAAQ,KAAK;AAG/D,cAAM,cAAc,IAAI,kBAAkB,QAAQ,YAAY;AAC9D,YAAI,QAAQ,cAAc;AACxB,sBAAY,UAAU,QAAQ,YAAY;AAAA,QAC5C;AAEA,oBAAY,WAAW,KAAK,SAAS,OAAO,GAAG;AAAA,UAC7C,aAAa,QAAQ;AAAA,UACrB,WAAW,QAAQ;AAAA,UACnB,WAAW,QAAQ;AAAA,QACrB,CAAC;AACD,cAAM,eAAe,YAAY,MAAM;AAEvC,cAAM,mBAAmB,QAAQ,mBAAmB,CAAC,GAAG,IAAI,CAAC,aAAa;AAAA,UACxE,MAAM,QAAQ;AAAA,UACd,SAAS,QAAQ;AAAA,QACnB,EAAE;AAEF,aAAK,eAAe,IAAI,oBAAoB,cAAc,iBAAiB;AAAA,UACzE,aAAa,QAAQ;AAAA,UACrB,WAAW,QAAQ;AAAA,UACnB,WAAW,QAAQ;AAAA,QACrB,CAAC;AACD,aAAK,gBAAgB,CAAC,CAAC,QAAQ;AAC/B,YAAI,QAAQ,YAAY;AACtB,eAAK,aAAa,eAAe,QAAQ,UAAU;AAAA,QACrD;AAGA,cAAM,oBAAoB,QAAQ,kBAAkB,WAAW;AAC/D,YAAI,mBAAmB;AACrB,eAAK,oBAAoB,IAAI;AAAA,YAC3B,KAAK;AAAA,YACL,KAAK;AAAA,YACL,QAAQ;AAAA,UACV;AAAA,QACF;AAGA,aAAK,SAAS,QAAQ;AAGtB,aAAK,cAAc,mBAAmB,QAAQ,WAAW;AAGzD,aAAK,qBAAqB;AAAA,UACxB,OAAO,KAAK;AAAA,UACZ,aAAa,KAAK;AAAA,QACpB;AACA,aAAK,iBAAiB,QAAQ;AAI9B,aAAK,OAAO,QAAQ,cAAc,IAAI,cAAc;AACpD,aAAK,eAAe,QAAQ,gBAAgB;AAC5C,aAAK,YAAY,QAAQ,aAAa;AAMtC,aAAK,4BAA4B,QAAQ;AACzC,aAAK,kBAAkB,CAAC,UAAyB;AAC/C,eAAK,sBAAsB,KAAK,KAAK;AACrC,eAAK,4BAA4B,KAAK;AAGtC,gBAAM,kBAAkB;AAAA,YACtB,0BAA0B,MAAM;AAAA,YAChC,OAAO,MAAM;AAAA,UACf;AAGA,cAAI,MAAM,SAAS,kBAAkB;AACnC,kBAAM,OAAO,MAAM;AACnB,iBAAK,KAAK,OAAO,WAAW,iBAAiB;AAAA,cAC3C,WAAW,KAAK;AAAA,cAChB,SAAS,EAAE,OAAO,KAAK,OAAO,UAAU,CAAC,EAAE;AAAA,cAC3C,QAAQ,KAAK;AAAA,cACb;AAAA,YACF,CAAC;AAAA,UACH,WAAW,MAAM,SAAS,gBAAgB;AACxC,kBAAM,OAAO,MAAM;AAEnB,kBAAM,QAAQ,KAAK,UAAU,KAAK,eAC9B;AAAA,cACE,aAAa,KAAK,eAAe;AAAA,cACjC,cAAc,KAAK;AAAA,cACnB,cAAc,KAAK,eAAe,KAAK,KAAK;AAAA,YAC9C,IACA;AACJ,iBAAK,KAAK,OAAO,WAAW,oBAAoB;AAAA,cAC9C,WAAW,KAAK;AAAA,cAChB,SAAS,EAAE,OAAO,KAAK,OAAO,UAAU,CAAC,EAAE;AAAA,cAC3C,cAAc,KAAK,gBAAgB;AAAA,cACnC;AAAA,cACA,aAAa;AAAA,cACb,cAAc;AAAA,cACd,QAAQ,KAAK;AAAA,cACb;AAAA,YACF,CAAC;AAAA,UACH,WAAW,MAAM,SAAS,eAAe;AACvC,kBAAM,cAAc,MAAM;AAC1B,iBAAK,KAAK,OAAO,WAAW,yBAAyB;AAAA,cACnD,WAAW;AAAA,cACX,YAAY,YAAY,KAAK;AAAA,cAC7B,cAAc,YAAY,KAAK;AAAA,cAC/B,YAAY,YAAY,KAAK,cAAc,CAAC;AAAA,cAC5C,QAAQ,KAAK;AAAA,cACb;AAAA,YACF,CAAC;AAAA,UACH,WAAW,MAAM,SAAS,iBAAiB;AACzC,kBAAM,cAAc,MAAM;AAC1B,iBAAK,KAAK,OAAO,WAAW,4BAA4B;AAAA,cACtD,WAAW;AAAA,cACX,YAAY,YAAY,OAAO,cAAc;AAAA,cAC7C,cAAc,YAAY,OAAO;AAAA,cACjC,YAAY,CAAC;AAAA,cACb,iBAAiB,YAAY,OAAO,mBAAmB;AAAA,cACvD,QAAQ,KAAK;AAAA,cACb;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,CAAS,6BAAqD;AAC5D,eAAO,KAAK,sBAAsB,SAAS,GAAG;AAC5C,gBAAM,QAAQ,KAAK,sBAAsB,MAAM;AAC/C,cAAI,OAAO;AACT,kBAAM,EAAE,MAAM,kBAAkB,eAAe,MAAM;AAAA,UACvD;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAoBA,cAA8B;AAC5B,eAAO,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA6BA,gBAA4B;AAC1B,eAAO,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAyCA,UAAyB;AACvB,eAAO,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAyBA,MAAM,UAA2C;AAC/C,YAAI,CAAC,KAAK,mBAAmB;AAC3B,iBAAO;AAAA,QACT;AAEA,eAAO,KAAK,kBAAkB,QAAQ,KAAK,cAAc,EAAE;AAAA,MAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAiBA,qBAA6C;AAC3C,eAAO,KAAK,mBAAmB,SAAS,KAAK;AAAA,MAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAeA,kBAAwC;AACtC,eAAO,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAoBA,kBAAkB,SAAuB;AACvC,aAAK,oBAAoB,KAAK,OAAO;AACrC,aAAK,OAAO,MAAM,qCAAqC,EAAE,QAAQ,CAAC;AAAA,MACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,OAAO,MAAmC;AACxC,YAAI,CAAC,KAAK,eAAe;AACvB,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,YAAI,mBAAmB;AAEvB,aAAK,OAAO,KAAK,uBAAuB;AAAA,UACtC,OAAO,KAAK;AAAA,UACZ,eAAe,KAAK;AAAA,QACtB,CAAC;AAED,eAAO,mBAAmB,KAAK,eAAe;AAE5C,cAAI,MAAM,KAAK,oBAAoB,gBAAgB,GAAG;AACpD;AAAA,UACF;AAGA,iBAAO,KAAK,oBAAoB,SAAS,GAAG;AAC1C,kBAAM,MAAM,KAAK,oBAAoB,MAAM;AAC3C,iBAAK,aAAa,eAAe,GAAG;AACpC,iBAAK,OAAO,KAAK,2CAA2C;AAAA,cAC1D,WAAW;AAAA,cACX,eAAe,IAAI;AAAA,YACrB,CAAC;AAAA,UACH;AAEA,eAAK,OAAO,MAAM,sBAAsB,EAAE,WAAW,iBAAiB,CAAC;AAEvE,cAAI;AAEF,kBAAM,kBAAkB,MAAM,KAAK,0BAA0B,gBAAgB;AAC7E,gBAAI,iBAAiB;AACnB,oBAAM;AAAA,YACR;AAGA,kBAAM,WAAW,MAAM,KAAK,eAAe,gBAAgB;AAC3D,kBAAM,aAAa,SAAS;AAG5B,gBAAI,SAAS,sBAAsB,QAAW;AAC5C,mBAAK,aAAa,oBAAoB,SAAS,iBAAiB;AAChE,oBAAM,EAAE,MAAM,QAAQ,SAAS,SAAS,kBAAkB;AAC1D;AAAA,YACF;AAGA,iBAAK,OAAO,KAAK,eAAe,EAAE,OAAO,KAAK,MAAM,CAAC;AACrD,iBAAK,OAAO,MAAM,uBAAuB;AAAA,cACvC,OAAO,WAAW;AAAA,cAClB,aAAa,WAAW;AAAA,cACxB,WAAW,WAAW;AAAA,cACtB,cAAc,WAAW,SAAS;AAAA,cAClC,UAAU,WAAW;AAAA,YACvB,CAAC;AAGD,kBAAM,UAAU,KAAK,KAAK,WAAW;AAAA,cACnC,WAAW;AAAA,cACX,OAAO,WAAW;AAAA,cAClB,UAAU,KAAK;AAAA,cACf,SAAS,WAAW;AAAA,YACtB,CAAC;AACD,kBAAM,mBAAmB,QAAQ;AAGjC,kBAAMC,UAAS,MAAM,KAAK,sBAAsB,YAAY,gBAAgB;AAG5E,kBAAM,YAAY,IAAI,gBAAgB;AAAA,cACpC,WAAW;AAAA,cACX,UAAU,KAAK;AAAA,cACf,mBAAmB,KAAK;AAAA,cACxB,iBAAiB,KAAK;AAAA,cACtB,iBAAiB,KAAK;AAAA,cACtB,OAAO,KAAK;AAAA,cACZ,QAAQ,KAAK,OAAO,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAAA,cAC7D,mBAAmB,KAAK;AAAA,cACxB,wBAAwB,KAAK;AAAA,cAC7B,QAAQ,KAAK;AAAA,cACb,YAAY,KAAK;AAAA,cACjB,aAAa,KAAK;AAAA,cAClB,gBAAgB,KAAK;AAAA,cACrB,iBAAiB,KAAK;AAAA;AAAA,cAEtB,MAAM,KAAK;AAAA,cACX,cAAc;AAAA;AAAA,cACd,WAAW,KAAK;AAAA;AAAA,cAEhB,2BAA2B,KAAK;AAAA,cAChC,wBAAwB,KAAK;AAAA,YAC/B,CAAC;AAID,gBAAI,iBAA+C;AACnD,gBAAI,kBAAkB;AAGtB,kBAAM,cAAwB,CAAC;AAC/B,kBAAM,gBAA+B,CAAC;AAEtC,6BAAiB,SAAS,UAAU,QAAQA,OAAM,GAAG;AACnD,kBAAI,MAAM,SAAS,mBAAmB;AAEpC,iCAAiB;AACjB;AAAA,cACF;AAGA,kBAAI,MAAM,SAAS,QAAQ;AACzB,4BAAY,KAAK,MAAM,OAAO;AAAA,cAChC,WAAW,MAAM,SAAS,iBAAiB;AACzC;AACA,8BAAc,KAAK,KAAK;AAAA,cAC1B;AAGA,oBAAM;AAIN,qBAAO,KAAK,2BAA2B;AAAA,YACzC;AAGA,gBAAI,CAAC,gBAAgB;AACnB,oBAAM,IAAI,MAAM,oDAAoD;AAAA,YACtE;AAGA,uBAAW,MAAM,UAAU,0BAA0B,GAAG;AACtD,mBAAK,uBAAuB,IAAI,EAAE;AAAA,YACpC;AACA,uBAAW,MAAM,UAAU,uBAAuB,GAAG;AACnD,mBAAK,oBAAoB,IAAI,EAAE;AAAA,YACjC;AAGA,kBAAM,SAAS;AAEf,iBAAK,OAAO,KAAK,0BAA0B;AAAA,cACzC,cAAc,OAAO;AAAA,cACrB,OAAO,OAAO;AAAA,cACd,mBAAmB,OAAO;AAAA,YAC5B,CAAC;AACD,iBAAK,OAAO,MAAM,wBAAwB;AAAA,cACxC,aAAa,OAAO;AAAA,YACtB,CAAC;AAGD,kBAAM,KAAK,YAAY,YAAY;AACjC,kBAAI,KAAK,MAAM,WAAW,mBAAmB;AAC3C,sBAAM,UAAqC;AAAA,kBACzC,WAAW;AAAA,kBACX,SAAS;AAAA,kBACT,cAAc,OAAO;AAAA,kBACrB,OAAO,OAAO;AAAA,kBACd,aAAa,OAAO;AAAA,kBACpB,cAAc,OAAO;AAAA,kBACrB,QAAQ,KAAK;AAAA,gBACf;AACA,sBAAM,KAAK,MAAM,UAAU,kBAAkB,OAAO;AAAA,cACtD;AAAA,YACF,CAAC;AAGD,iBAAK,sBAAsB,kBAAkB,MAAM;AAGnD,kBAAM,eAAe,MAAM,KAAK;AAAA,cAC9B;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAGA,kBAAM,0BAA0B,MAAM,KAAK;AAAA,cACzC,OAAO;AAAA,cACP;AAAA,cACA;AAAA,cACA;AAAA,YACF;AACA,gBAAI,yBAAyB;AAC3B;AAAA,YACF;AAGA,gBAAI,OAAO,iBAAiB;AAC1B,mBAAK,OAAO,KAAK,wCAAwC;AACzD;AAAA,YACF;AAAA,UACF,SAAS,OAAO;AAEd,kBAAM,eAAe,MAAM,KAAK,eAAe,OAAgB,gBAAgB;AAG/E,kBAAM,KAAK,YAAY,YAAY;AACjC,kBAAI,KAAK,MAAM,WAAW,gBAAgB;AACxC,sBAAM,UAAkC;AAAA,kBACtC,WAAW;AAAA,kBACX,SAAS;AAAA,oBACP,OAAO,KAAK;AAAA,oBACZ,UAAU,KAAK,aAAa,YAAY;AAAA,oBACxC,aAAa,KAAK;AAAA,oBAClB,WAAW,KAAK;AAAA,kBAClB;AAAA,kBACA;AAAA,kBACA,WAAW;AAAA,kBACX,QAAQ,KAAK;AAAA,gBACf;AACA,sBAAM,KAAK,MAAM,UAAU,eAAe,OAAO;AAAA,cACnD;AAAA,YACF,CAAC;AAED,gBAAI,CAAC,cAAc;AACjB,oBAAM;AAAA,YACR;AAAA,UACF;AAEA;AAAA,QACF;AAEA,aAAK,OAAO,KAAK,wBAAwB;AAAA,UACvC,iBAAiB;AAAA,UACjB,QAAQ,oBAAoB,KAAK,gBAAgB,mBAAmB;AAAA,QACtE,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAc,sBACZ,YACA,WACuC;AAEvC,YAAI,CAAC,KAAK,YAAY,SAAS;AAC7B,iBAAO,KAAK,OAAO,OAAO,UAAU;AAAA,QACtC;AAEA,cAAM,EAAE,SAAS,YAAY,YAAY,QAAQ,WAAW,SAAS,oBAAoB,YAAY,IACnG,KAAK;AAEP,YAAI;AACF,iBAAO,UAAM,eAAAC;AAAA,YACX,OAAO,kBAAkB;AACvB,mBAAK,OAAO,MAAM,uBAAuB,EAAE,SAAS,eAAe,aAAa,UAAU,EAAE,CAAC;AAC7F,qBAAO,KAAK,OAAO,OAAO,UAAU;AAAA,YACtC;AAAA,YACA;AAAA,cACE;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA,QAAQ,KAAK;AAAA,cACb,iBAAiB,CAAC,YAAY;AAC5B,sBAAM,EAAE,OAAO,eAAe,YAAY,IAAI;AAC9C,qBAAK,OAAO;AAAA,kBACV,4BAA4B,aAAa,IAAI,gBAAgB,WAAW;AAAA,kBACxE,EAAE,OAAO,MAAM,SAAS,YAAY;AAAA,gBACtC;AACA,0BAAU,OAAO,aAAa;AAAA,cAChC;AAAA,cACA,aAAa,CAAC,YAAY;AAExB,oBAAI,aAAa;AACf,yBAAO,YAAY,QAAQ,KAAK;AAAA,gBAClC;AACA,uBAAO,iBAAiB,QAAQ,KAAK;AAAA,cACvC;AAAA,YACF;AAAA,UACF;AAAA,QACF,SAAS,OAAO;AAEd,eAAK,OAAO,MAAM,yBAAyB,UAAU,CAAC,aAAa;AAAA,YACjE,OAAQ,MAAgB;AAAA,YACxB;AAAA,UACF,CAAC;AACD,+BAAqB,OAAgB,UAAU,CAAC;AAChD,gBAAM;AAAA,QACR;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,eAAe,OAAc,WAAqC;AAC9E,aAAK,OAAO,MAAM,mBAAmB,EAAE,OAAO,MAAM,QAAQ,CAAC;AAE7D,YAAI,KAAK,MAAM,aAAa,eAAe;AACzC,gBAAM,UAAqC;AAAA,YACzC;AAAA,YACA,SAAS;AAAA,cACP,OAAO,KAAK;AAAA,cACZ,UAAU,KAAK,aAAa,YAAY;AAAA,cACxC,aAAa,KAAK;AAAA,cAClB,WAAW,KAAK;AAAA,YAClB;AAAA,YACA;AAAA,YACA,QAAQ,KAAK;AAAA,UACf;AACA,gBAAM,SAA8B,MAAM,KAAK,MAAM,YAAY,cAAc,OAAO;AAGtF,sCAA4B,MAAM;AAElC,cAAI,OAAO,WAAW,WAAW;AAC/B,iBAAK,OAAO,KAAK,qCAAqC;AACtD,iBAAK,aAAa,oBAAoB,OAAO,gBAAgB;AAC7D,mBAAO;AAAA,UACT;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,uBAAuB,OAAiC;AACpE,cAAM,UAAU,KAAK;AAErB,YAAI,OAAO,YAAY,UAAU;AAC/B,kBAAQ,SAAS;AAAA,YACf,KAAK;AACH,mBAAK,OAAO,KAAK,gCAAgC;AACjD,qBAAO;AAAA,YACT,KAAK;AACH,mBAAK,OAAO,KAAK,oCAAoC;AACrD,qBAAO;AAAA,YACT,KAAK;AACH,mBAAK,OAAO,KAAK,sCAAsC;AACvD,qBAAO;AAAA,YACT;AACE,mBAAK,OAAO,KAAK,+BAA+B,OAAO,2BAA2B;AAClF,qBAAO;AAAA,UACX;AAAA,QACF;AAIA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,YAAY,IAA+C;AACvE,YAAI;AACF,gBAAM,GAAG;AAAA,QACX,SAAS,OAAO;AACd,eAAK,OAAO,MAAM,mCAAmC;AAAA,YACnD,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,UAC9D,CAAC;AAAA,QACH;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKQ,4BAA4B,SAAqC;AACvE,cAAM,SAAS,KAAK,OAAO,cAAc,eAAe,OAAO;AAC/D,YAAI,QAAQ,oBAAoB,QAAW;AACzC,iBAAO,OAAO;AAAA,QAChB;AAEA,cAAM,iBAAiB,QAAQ,QAAQ,GAAG;AAC1C,YAAI,mBAAmB,IAAI;AACzB,iBAAO;AAAA,QACT;AAEA,cAAM,oBAAoB,QAAQ,MAAM,iBAAiB,CAAC,EAAE,KAAK;AACjE,YAAI,CAAC,mBAAmB;AACtB,iBAAO;AAAA,QACT;AAEA,eAAO,KAAK,OAAO,cAAc,eAAe,iBAAiB,GAAG;AAAA,MACtE;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,gCAAgC,WAAoC;AAC1E,YAAI,CAAC,KAAK,oBAAoB;AAC5B,iBAAO,aAAa,CAAC;AAAA,QACvB;AAEA,cAAM,qBAAqB,CAAC,QAAgB,QAAgD;AAE1F,cAAI,IAAI,eAAe,sBAAsB;AAC3C,mBAAO;AAAA,UACT;AAEA,cAAI,OAAO,SAAS,KAAK,sBAAsB;AAC7C,kBAAM,KAAK,KAAK,YAAY,MAAM,IAAI,YAAY,MAAM;AACxD,kBAAM,QAAQ,OAAO,MAAM,IAAI,EAAE;AACjC,kBAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,MAAM,EAAE;AAE/C,iBAAK,OAAO,KAAK,qDAAqD;AAAA,cACpE,YAAY,IAAI;AAAA,cAChB,UAAU;AAAA,cACV;AAAA,cACA;AAAA,cACA,WAAW,KAAK;AAAA,YAClB,CAAC;AAED,mBACE,YAAY,IAAI,UAAU,6BACvB,MAAM,eAAe,CAAC,WAAW,MAAM,eAAe,CAAC,2CACvB,EAAE;AAAA,UAEzC;AAEA,iBAAO;AAAA,QACT;AAGA,cAAM,kBAAkB,WAAW,cAAc;AACjD,cAAM,qBAAqB,kBACvB,CAAC,QAAgB,QACf,gBAAgB,mBAAmB,QAAQ,GAAG,GAAG,GAAG,IACtD;AAEJ,eAAO;AAAA,UACL,GAAG;AAAA,UACH,cAAc;AAAA,YACZ,GAAG,WAAW;AAAA,YACd,uBAAuB;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAUA,MAAc,oBAAoB,WAAqC;AACrE,YAAI,CAAC,KAAK,QAAQ,QAAS,QAAO;AAElC,aAAK,OAAO,KAAK,yCAAyC;AAAA,UACxD;AAAA,UACA,QAAQ,KAAK,OAAO;AAAA,QACtB,CAAC;AAED,cAAM,KAAK,YAAY,YAAY;AACjC,cAAI,KAAK,MAAM,WAAW,SAAS;AACjC,kBAAM,UAA+B;AAAA,cACnC;AAAA,cACA,QAAQ,KAAK,QAAQ;AAAA,cACrB,QAAQ,KAAK;AAAA,YACf;AACA,kBAAM,KAAK,MAAM,UAAU,QAAQ,OAAO;AAAA,UAC5C;AAAA,QACF,CAAC;AAED,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAc,0BAA0B,WAAgD;AACtF,YAAI,CAAC,KAAK,kBAAmB,QAAO;AAEpC,cAAM,kBAAkB,MAAM,KAAK,kBAAkB;AAAA,UACnD,KAAK;AAAA,UACL;AAAA,QACF;AAEA,YAAI,CAAC,gBAAiB,QAAO;AAE7B,aAAK,OAAO,KAAK,qBAAqB;AAAA,UACpC,UAAU,gBAAgB;AAAA,UAC1B,cAAc,gBAAgB;AAAA,UAC9B,aAAa,gBAAgB;AAAA,QAC/B,CAAC;AAGD,cAAM,KAAK,YAAY,YAAY;AACjC,cAAI,KAAK,MAAM,WAAW,cAAc;AACtC,kBAAM,KAAK,MAAM,UAAU,aAAa;AAAA,cACtC;AAAA,cACA,OAAO;AAAA;AAAA,cAEP,OAAO,KAAK,kBAAmB,SAAS;AAAA,cACxC,QAAQ,KAAK;AAAA,YACf,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AAED,eAAO,EAAE,MAAM,cAAc,OAAO,gBAAgB;AAAA,MACtD;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAc,eACZ,WACwE;AACxE,YAAI,aAAmC;AAAA,UACrC,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK,aAAa,YAAY;AAAA,UACxC,aAAa,KAAK;AAAA,UAClB,WAAW,KAAK;AAAA,UAChB,QAAQ,KAAK;AAAA,QACf;AAGA,cAAM,KAAK,YAAY,YAAY;AACjC,cAAI,KAAK,MAAM,WAAW,gBAAgB;AACxC,kBAAM,UAAiC;AAAA,cACrC;AAAA,cACA,SAAS;AAAA,cACT,QAAQ,KAAK;AAAA,YACf;AACA,kBAAM,KAAK,MAAM,UAAU,eAAe,OAAO;AAAA,UACnD;AAAA,QACF,CAAC;AAGD,YAAI,KAAK,MAAM,aAAa,eAAe;AACzC,gBAAM,UAAoC;AAAA,YACxC;AAAA,YACA,eAAe,KAAK;AAAA,YACpB,SAAS;AAAA,YACT,QAAQ,KAAK;AAAA,UACf;AACA,gBAAM,SAA8B,MAAM,KAAK,MAAM,YAAY,cAAc,OAAO;AAGtF,sCAA4B,MAAM;AAElC,cAAI,OAAO,WAAW,QAAQ;AAC5B,iBAAK,OAAO,KAAK,uDAAuD;AACxE,mBAAO,EAAE,SAAS,YAAY,mBAAmB,OAAO,kBAAkB;AAAA,UAC5E,WAAW,OAAO,WAAW,aAAa,OAAO,iBAAiB;AAChE,yBAAa,EAAE,GAAG,YAAY,GAAG,OAAO,gBAAgB;AAAA,UAC1D;AAAA,QACF;AAGA,cAAM,KAAK,YAAY,YAAY;AACjC,cAAI,KAAK,MAAM,WAAW,gBAAgB;AACxC,kBAAM,UAAsC;AAAA,cAC1C;AAAA,cACA,eAAe,KAAK;AAAA,cACpB,SAAS;AAAA,cACT,QAAQ,KAAK;AAAA,YACf;AACA,kBAAM,KAAK,MAAM,UAAU,eAAe,OAAO;AAAA,UACnD;AAAA,QACF,CAAC;AAED,eAAO,EAAE,SAAS,WAAW;AAAA,MAC/B;AAAA;AAAA;AAAA;AAAA,MAKQ,sBACN,QACA,QACM;AAEN,cAAM,UAAU,KAAK,OAAO,eAAe;AAAA,UACzC,KAAK;AAAA,UACL,OAAO,OAAO,eAAe;AAAA,UAC7B,OAAO,OAAO,gBAAgB;AAAA,UAC9B,OAAO,OAAO,qBAAqB;AAAA,UACnC,OAAO,OAAO,4BAA4B;AAAA,QAC5C,GAAG;AAGH,aAAK,KAAK,gBAAgB,QAAQ;AAAA,UAChC,UAAU,OAAO;AAAA,UACjB,OAAO,OAAO;AAAA,UACd,cAAc,OAAO;AAAA,UACrB,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA;AAAA;AAAA;AAAA,MAKA,MAAc,8BACZ,WACA,YACA,QACA,iBACiB;AACjB,YAAI,eAAe,OAAO;AAE1B,YAAI,CAAC,KAAK,MAAM,aAAa,cAAc;AACzC,iBAAO;AAAA,QACT;AAEA,cAAM,UAAyC;AAAA,UAC7C;AAAA,UACA,eAAe,KAAK;AAAA,UACpB,SAAS;AAAA,UACT,cAAc,OAAO;AAAA,UACrB,OAAO,OAAO;AAAA,UACd,cAAc,OAAO;AAAA,UACrB;AAAA,UACA,QAAQ,KAAK;AAAA,QACf;AACA,cAAM,SAA6B,MAAM,KAAK,MAAM,YAAY,aAAa,OAAO;AAGpF,mCAA2B,MAAM;AAEjC,YAAI,OAAO,WAAW,yBAAyB,OAAO,WAAW,qBAAqB;AACpF,yBAAe,OAAO;AAAA,QACxB;AAEA,YAAI,OAAO,WAAW,qBAAqB,OAAO,WAAW,qBAAqB;AAChF,qBAAW,OAAO,OAAO,UAAU;AACjC,gBAAI,IAAI,SAAS,QAAQ;AACvB,mBAAK,aAAa,eAAe,IAAI,OAAO;AAAA,YAC9C,WAAW,IAAI,SAAS,aAAa;AACnC,mBAAK,aAAa,oBAAoB,mBAAmB,IAAI,OAAO,CAAC;AAAA,YACvE,WAAW,IAAI,SAAS,UAAU;AAChC,mBAAK,aAAa,eAAe,YAAY,mBAAmB,IAAI,OAAO,CAAC,EAAE;AAAA,YAChF;AAAA,UACF;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,MAAc,8BACZ,mBACA,aACA,eACA,cACkB;AAClB,YAAI,mBAAmB;AAErB,cAAI,KAAK,wBAAwB;AAC/B,kBAAM,cAAc,YAAY,KAAK,EAAE;AAEvC,gBAAI,YAAY,KAAK,GAAG;AACtB,oBAAM,EAAE,YAAY,kBAAkB,cAAc,IAAI,KAAK;AAC7D,oBAAM,cAAc,WAAW,EAAE,KAAK,0BAA0B;AAChE,mBAAK,aAAa;AAAA,gBAChB;AAAA,gBACA,iBAAiB,WAAW;AAAA,gBAC5B,gBAAgB,cAAc,WAAW,IAAI;AAAA,gBAC7C;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAGA,qBAAW,UAAU,eAAe;AAClC,gBAAI,OAAO,SAAS,iBAAiB;AACnC,oBAAM,eAAe,OAAO;AAC5B,mBAAK,aAAa;AAAA,gBAChB,aAAa;AAAA,gBACb,aAAa;AAAA,gBACb,aAAa,SAAS,aAAa,UAAU;AAAA,gBAC7C,aAAa;AAAA,gBACb,aAAa;AAAA,gBACb,aAAa;AAAA,cACf;AAAA,YACF;AAAA,UACF;AAEA,iBAAO;AAAA,QACT;AAGA,YAAI,aAAa,KAAK,GAAG;AACvB,gBAAM,cAAc,WAAW,EAAE,KAAK,0BAA0B;AAChE,eAAK,aAAa;AAAA,YAChB;AAAA,YACA,EAAE,SAAS,cAAc,MAAM,OAAO,MAAM,OAAO;AAAA,YACnD,iBAAO,YAAY;AAAA,YACnB;AAAA,UACF;AAAA,QACF;AAGA,eAAO,MAAM,KAAK,uBAAuB,YAAY;AAAA,MACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAkBA,MAAM,QAAQ,UAAwC;AACpD,eAAO,gBAAgB,KAAK,IAAI,GAAG,QAAQ;AAAA,MAC7C;AAAA,IACF;AAAA;AAAA;;;ACt1CA,IAgEa;AAhEb;AAAA;AAAA;AAoBA;AAGA;AAEA;AAGA;AAEA;AACA;AAGA;AA8BO,IAAM,eAAN,MAAmB;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAA2B,CAAC;AAAA,MAC5B,kBAGH,CAAC;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAKA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA;AAAA,MAGA;AAAA,MAMR,YAAY,QAAiB;AAC3B,aAAK,SAAS;AAAA,MAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBA,UAAU,OAAqB;AAC7B,aAAK,QAAQ,aAAa,KAAK;AAC/B,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,WAAW,QAAsB;AAC/B,aAAK,eAAe;AACpB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,gBAAgB,aAA2B;AACzC,aAAK,cAAc;AACnB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,kBAAkB,KAAmB;AACnC,aAAK,gBAAgB;AACrB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,WAAW,QAA+B;AACxC,aAAK,SAAS;AACd,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAmBA,UAAU,OAAyB;AACjC,aAAK,QAAQ;AACb,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBA,yBAAyB,QAAoC;AAC3D,aAAK,eAAe;AACpB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBA,eAAe,SAAgC;AAC7C,aAAK,QAAQ,KAAK,GAAG,OAAO;AAC5B,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAmBA,YAAY,UAAkC;AAC5C,mBAAW,OAAO,UAAU;AAC1B,cAAI,UAAU,KAAK;AACjB,iBAAK,gBAAgB,KAAK,EAAE,MAAM,QAAQ,SAAS,IAAI,KAAK,CAAC;AAAA,UAC/D,WAAW,eAAe,KAAK;AAC7B,iBAAK,gBAAgB,KAAK,EAAE,MAAM,aAAa,SAAS,IAAI,UAAU,CAAC;AAAA,UACzE,WAAW,YAAY,KAAK;AAC1B,iBAAK,gBAAgB,KAAK,EAAE,MAAM,UAAU,SAAS,IAAI,OAAO,CAAC;AAAA,UACnE;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcA,WAAW,SAA+B;AACxC,eAAO,KAAK,YAAY,CAAC,OAAO,CAAC;AAAA,MACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcA,eAAqB;AACnB,aAAK,kBAAkB,CAAC;AACxB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA2BA,aAAa,OAAoB;AAC/B,cAAM,UAAU,MAAM,gBAAgB,EAAE,uBAAuB;AAC/D,aAAK,aAAa;AAGlB,mBAAW,OAAO,SAAS;AACzB,cAAI,IAAI,SAAS,QAAQ;AACvB,iBAAK,gBAAgB,KAAK,EAAE,MAAM,QAAQ,SAAS,IAAI,QAAQ,CAAC;AAAA,UAClE,WAAW,IAAI,SAAS,aAAa;AACnC,iBAAK,gBAAgB,KAAK,EAAE,MAAM,aAAa,SAAS,IAAI,QAAQ,CAAC;AAAA,UACvE;AAAA,QAEF;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAeA,aAAa,SAAsD;AACjE,aAAK,oBAAoB;AACzB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAaA,sBAAsB,QAAsB;AAC1C,aAAK,oBAAoB;AACzB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAaA,oBAAoB,QAAsB;AACxC,aAAK,kBAAkB;AACvB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAaA,oBAAoB,QAAsB;AACxC,aAAK,kBAAkB;AACvB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA+BA,oBAAoB,SAAgC;AAClD,aAAK,kBAAkB;AACvB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAsBA,2BAA2B,SAIlB;AACP,aAAK,yBAAyB;AAC9B,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcA,yBAAyB,WAAyB;AAChD,YAAI,YAAY,GAAG;AACjB,gBAAM,IAAI,MAAM,uCAAuC;AAAA,QACzD;AACA,aAAK,yBAAyB;AAC9B,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBA,sBAAsB,SAAwB;AAC5C,aAAK,oBAAoB;AACzB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAgBA,6BAA6B,SAAuB;AAClD,YAAI,UAAU,KAAK,UAAU,KAAK;AAChC,gBAAM,IAAI,MAAM,gDAAgD;AAAA,QAClE;AACA,aAAK,2BAA2B;AAChC,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAiCA,eAAe,QAAgC;AAC7C,aAAK,mBAAmB,EAAE,GAAG,QAAQ,SAAS,OAAO,WAAW,KAAK;AACrE,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcA,oBAA0B;AACxB,aAAK,mBAAmB,EAAE,SAAS,MAAM;AACzC,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAoCA,UAAU,QAA2B;AACnC,aAAK,cAAc,EAAE,GAAG,QAAQ,SAAS,OAAO,WAAW,KAAK;AAChE,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAcA,eAAqB;AACnB,aAAK,cAAc,EAAE,SAAS,MAAM;AACpC,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA2BA,WAAW,QAA2B;AACpC,aAAK,SAAS;AACd,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAmBA,mBAAmB,QAAiC;AAClD,aAAK,iBAAiB;AACtB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAuBA,0BAA0B,UAAgD;AACxE,aAAK,wBAAwB;AAC7B,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAoDA,kBAAkB,KAAuB,QAAQ,GAAS;AAIxD,YAAI,IAAI,MAAM;AACZ,eAAK,gBAAgB;AAAA,YACnB,MAAM,IAAI;AAAA,YACV,QAAQ,IAAI;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAGA,YAAI,IAAI,UAAU,CAAC,KAAK,QAAQ;AAC9B,eAAK,SAAS,IAAI;AAAA,QACpB;AAGA,YAAI,IAAI,UAAU,CAAC,KAAK,QAAQ;AAC9B,eAAK,SAAS,IAAI;AAAA,QACpB;AAEA,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAuBA,oBAAoB,SAAgC;AAClD,aAAK,kBAAkB;AACvB,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA8BA,wBACE,YACA,YACA,QACA,cACM;AACN,cAAM,cAAc,KAAK,qBAAqB;AAC9C,cAAM,YAAY,KAAK,mBAAmB;AAE1C,cAAM,WAAW,KAAK,sBAAsB,YAAY,EAAE;AAG1D,aAAK,gBAAgB,KAAK;AAAA,UACxB,MAAM;AAAA,UACN,SAAS,GAAG,WAAW,GAAG,UAAU,IAAI,YAAY;AAAA,EAAK,QAAQ;AAAA,EAAK,SAAS;AAAA,QACjF,CAAC;AAGD,aAAK,gBAAgB,KAAK;AAAA,UACxB,MAAM;AAAA,UACN,SAAS,WAAW,YAAY,MAAM,MAAM;AAAA,QAC9C,CAAC;AAED,eAAO;AAAA,MACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MASQ,eAAuC;AAC7C,cAAM,QAAQ,KAAK;AAGnB,YAAI,CAAC,KAAK,iBAAiB;AACzB,iBAAO;AAAA,QACT;AAEA,cAAM,cAAc,KAAK;AACzB,cAAM,wBAAwB,OAAO,aAAa;AAElD,cAAM,4BAA4B,OAChC,QACiC;AAEjC,gBAAM,SAA8B,wBAChC,MAAM,sBAAsB,GAAG,IAC/B,EAAE,QAAQ,UAAU;AAGxB,cAAI,OAAO,WAAW,QAAQ;AAC5B,mBAAO;AAAA,UACT;AAGA,gBAAM,WAAW,CAAC,GAAI,OAAO,iBAAiB,YAAY,IAAI,QAAQ,QAAS;AAG/E,gBAAM,UACJ,OAAO,gBAAgB,aACnB,YAAY,EAAE,WAAW,IAAI,WAAW,eAAe,IAAI,cAAc,CAAC,IAC1E;AAGN,mBAAS,KAAK,EAAE,MAAM,QAAQ,QAAQ,CAAC;AAEvC,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,iBAAiB,EAAE,GAAG,OAAO,iBAAiB,SAAS;AAAA,UACzD;AAAA,QACF;AAEA,eAAO;AAAA,UACL,GAAG;AAAA,UACH,aAAa;AAAA,YACX,GAAG,OAAO;AAAA,YACV,eAAe;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKQ,sBAAsB,QAAiC,QAAwB;AACrF,cAAM,QAAkB,CAAC;AACzB,cAAM,YAAY,KAAK,mBAAmB;AAE1C,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,gBAAM,WAAW,SAAS,GAAG,MAAM,IAAI,GAAG,KAAK;AAE/C,cAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,kBAAM,QAAQ,CAAC,MAAM,UAAU;AAC7B,oBAAM,WAAW,GAAG,QAAQ,IAAI,KAAK;AACrC,kBAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,sBAAM,KAAK,KAAK,sBAAsB,MAAiC,QAAQ,CAAC;AAAA,cAClF,OAAO;AACL,sBAAM,KAAK,GAAG,SAAS,GAAG,QAAQ,EAAE;AACpC,sBAAM,KAAK,OAAO,IAAI,CAAC;AAAA,cACzB;AAAA,YACF,CAAC;AAAA,UACH,WAAW,OAAO,UAAU,YAAY,UAAU,MAAM;AACtD,kBAAM,KAAK,KAAK,sBAAsB,OAAkC,QAAQ,CAAC;AAAA,UACnF,OAAO;AACL,kBAAM,KAAK,GAAG,SAAS,GAAG,QAAQ,EAAE;AACpC,kBAAM,KAAK,OAAO,KAAK,CAAC;AAAA,UAC1B;AAAA,QACF;AAEA,eAAO,MAAM,KAAK,IAAI;AAAA,MACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAyBQ,kBAAkB,YAAkD;AAE1E,YAAI,CAAC,KAAK,QAAQ;AAChB,gBAAM,EAAE,QAAQ,YAAY,IAC1B;AACF,eAAK,SAAS,IAAI,YAAY;AAAA,QAChC;AAEA,cAAM,WAAW,eAAe,KAAK,KAAK,OAAO;AAEjD,eAAO;AAAA,UACL,QAAQ,KAAK;AAAA,UACb,OAAO,KAAK,SAAS;AAAA,UACrB,cAAc,KAAK;AAAA,UACnB;AAAA,UACA;AAAA,UACA,eAAe,KAAK;AAAA,UACpB,aAAa,KAAK;AAAA,UAClB,QAAQ,KAAK;AAAA,UACb,OAAO,KAAK,aAAa;AAAA,UACzB,cAAc,KAAK;AAAA,UACnB,iBAAiB,KAAK;AAAA,UACtB,mBAAmB,KAAK;AAAA,UACxB,mBAAmB,KAAK;AAAA,UACxB,iBAAiB,KAAK;AAAA,UACtB,iBAAiB,KAAK;AAAA,UACtB,iBAAiB,KAAK;AAAA,UACtB,wBAAwB,KAAK;AAAA,UAC7B,wBAAwB,KAAK;AAAA,UAC7B,mBAAmB,KAAK;AAAA,UACxB,0BAA0B,KAAK;AAAA,UAC/B,kBAAkB,KAAK;AAAA,UACvB,aAAa,KAAK;AAAA,UAClB,QAAQ,KAAK;AAAA,UACb,gBAAgB,KAAK;AAAA,UACrB,iBAAiB,KAAK;AAAA;AAAA,UAEtB,YAAY,KAAK,eAAe;AAAA,UAChC,cAAc,KAAK,eAAe;AAAA,UAClC,WAAW,KAAK,iBAAiB,KAAK,cAAc,SAAS,KAAK,IAAI;AAAA,QACxE;AAAA,MACF;AAAA,MAEA,IAAI,YAA2B;AAC7B,cAAM,UAAU,KAAK,kBAAkB,UAAU;AACjD,eAAO,IAAI,MAAM,oBAAoB,OAAO;AAAA,MAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA0BA,aACE,YACA,WACA,UACO;AACP,cAAM,cACJ,OAAO,cAAc,WAAW,OAAO,KAAK,WAAW,QAAQ,IAAI;AACrE,cAAM,eAAe,YAAY,oBAAoB,WAAW;AAEhE,YAAI,CAAC,cAAc;AACjB,gBAAM,IAAI;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAGA,cAAM,cAA6B;AAAA,UACjC,KAAK,UAAU;AAAA,UACf;AAAA,YACE,MAAM;AAAA,YACN,QAAQ;AAAA,cACN,MAAM;AAAA,cACN,WAAW;AAAA,cACX,MAAM,SAAS,WAAW;AAAA,YAC5B;AAAA,UACF;AAAA,QACF;AAEA,cAAM,UAAU,KAAK,kBAAkB,WAAW;AAClD,eAAO,IAAI,MAAM,oBAAoB,OAAO;AAAA,MAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA0BA,eAAe,SAA+B;AAC5C,cAAM,UAAU,KAAK,kBAAkB,OAAO;AAC9C,eAAO,IAAI,MAAM,oBAAoB,OAAO;AAAA,MAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAmBA,MAAM,cAAc,YAAqC;AACvD,cAAM,QAAQ,KAAK,IAAI,UAAU;AACjC,eAAO,YAAY,MAAM,IAAI,CAAC;AAAA,MAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAoBA,MAAM,QAAQ,YAAoB,UAAwC;AACxE,cAAM,QAAQ,KAAK,IAAI,UAAU;AACjC,cAAM,MAAM,QAAQ,QAAQ;AAAA,MAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MA6BA,QAAe;AAEb,YAAI,CAAC,KAAK,QAAQ;AAChB,gBAAM,EAAE,QAAQ,YAAY,IAC1B;AACF,eAAK,SAAS,IAAI,YAAY;AAAA,QAChC;AACA,cAAM,WAAW,eAAe,KAAK,KAAK,OAAO;AAEjD,cAAM,UAAwB;AAAA,UAC5B,QAAQ,KAAK;AAAA,UACb,OAAO,KAAK,SAAS;AAAA,UACrB,cAAc,KAAK;AAAA;AAAA,UAEnB;AAAA,UACA,eAAe,KAAK;AAAA,UACpB,aAAa,KAAK;AAAA,UAClB,QAAQ,KAAK;AAAA,UACb,OAAO,KAAK,aAAa;AAAA,UACzB,cAAc,KAAK;AAAA,UACnB,iBAAiB,KAAK;AAAA,UACtB,mBAAmB,KAAK;AAAA,UACxB,mBAAmB,KAAK;AAAA,UACxB,iBAAiB,KAAK;AAAA,UACtB,iBAAiB,KAAK;AAAA,UACtB,iBAAiB,KAAK;AAAA,UACtB,wBAAwB,KAAK;AAAA,UAC7B,wBAAwB,KAAK;AAAA,UAC7B,mBAAmB,KAAK;AAAA,UACxB,0BAA0B,KAAK;AAAA,UAC/B,kBAAkB,KAAK;AAAA,UACvB,aAAa,KAAK;AAAA,UAClB,QAAQ,KAAK;AAAA,UACb,gBAAgB,KAAK;AAAA,UACrB,iBAAiB,KAAK;AAAA;AAAA,UAEtB,YAAY,KAAK,eAAe;AAAA,UAChC,cAAc,KAAK,eAAe;AAAA,UAClC,WAAW,KAAK,iBAAiB,KAAK,cAAc,SAAS,KAAK,IAAI;AAAA,QACxE;AAEA,eAAO,IAAI,MAAM,oBAAoB,OAAO;AAAA,MAC9C;AAAA,IACF;AAAA;AAAA;;;AC7sCA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAAC;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,IAAAC,cAAkB;AAElB;AAMAC;AAGA;AAEA;;;ACkJO,IAAM,cAAN,MAAM,aAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwDvB,OAAO,QAAQ,UAA0B,CAAC,GAAe;AACvD,WAAO;AAAA,MACL,WAAW;AAAA,QACT,gBAAgB,OAAO,QAAQ;AAC7B,kBAAQ,IAAI,kCAAkC,IAAI,SAAS,GAAG;AAAA,QAChE;AAAA,QACA,mBAAmB,OAAO,QAAQ;AAChC,gBAAM,SAAS,IAAI,OAAO,eAAe;AACzC,kBAAQ,IAAI,4BAA4B,MAAM,GAAG;AACjD,cAAI,QAAQ,WAAW,IAAI,cAAc;AACvC,oBAAQ,IAAI,mBAAmB,IAAI,YAAY,EAAE;AAAA,UACnD;AAAA,QACF;AAAA,QACA,wBAAwB,OAAO,QAAQ;AACrC,kBAAQ,IAAI,sBAAsB,IAAI,UAAU,EAAE;AAClD,cAAI,QAAQ,SAAS;AACnB,oBAAQ,IAAI,wBAAwB,KAAK,UAAU,IAAI,YAAY,MAAM,CAAC,CAAC;AAAA,UAC7E;AAAA,QACF;AAAA,QACA,2BAA2B,OAAO,QAAQ;AACxC,kBAAQ,IAAI,sBAAsB,IAAI,UAAU,EAAE;AAClD,cAAI,QAAQ,SAAS;AACnB,kBAAM,UAAU,IAAI,SAAS,IAAI,eAAe;AAChD,oBAAQ,IAAI,oBAAoB,OAAO,EAAE;AAAA,UAC3C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoDA,OAAO,SAAqB;AAC1B,UAAM,UAAU,oBAAI,IAAoB;AAExC,WAAO;AAAA,MACL,WAAW;AAAA,QACT,gBAAgB,OAAO,QAAQ;AAC7B,kBAAQ,IAAI,OAAO,IAAI,SAAS,IAAI,KAAK,IAAI,CAAC;AAAA,QAChD;AAAA,QACA,mBAAmB,OAAO,QAAQ;AAChC,gBAAM,QAAQ,QAAQ,IAAI,OAAO,IAAI,SAAS,EAAE;AAChD,cAAI,OAAO;AACT,kBAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,oBAAQ,IAAI,+BAAqB,QAAQ,IAAI;AAC7C,oBAAQ,OAAO,OAAO,IAAI,SAAS,EAAE;AAAA,UACvC;AAAA,QACF;AAAA,QACA,wBAAwB,OAAO,QAAQ;AACrC,gBAAM,MAAM,UAAU,IAAI,UAAU,IAAI,KAAK,IAAI,CAAC;AAClD,kBAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAE3B,UAAC,IAAY,aAAa;AAAA,QAC5B;AAAA,QACA,2BAA2B,OAAO,QAAQ;AACxC,gBAAM,MAAO,IAAY;AACzB,cAAI,KAAK;AACP,kBAAM,QAAQ,QAAQ,IAAI,GAAG;AAC7B,gBAAI,OAAO;AACT,oBAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,sBAAQ,IAAI,wBAAc,IAAI,UAAU,SAAS,QAAQ,IAAI;AAC7D,sBAAQ,OAAO,GAAG;AAAA,YACpB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuDA,OAAO,gBAA4B;AACjC,QAAI,cAAc;AAClB,QAAI,aAAa;AAEjB,WAAO;AAAA,MACL,WAAW;AAAA,QACT,mBAAmB,OAAO,QAAQ;AAChC;AACA,cAAI,IAAI,OAAO,aAAa;AAC1B,2BAAe,IAAI,MAAM;AACzB,oBAAQ,IAAI,+BAAwB,IAAI,MAAM,WAAW,EAAE;AAC3D,oBAAQ,IAAI,2BAAoB,WAAW,YAAY,UAAU,SAAS;AAAA,UAC5E;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4HA,OAAO,iBAAiB,SAA+C;AACrE,UAAM,EAAE,eAAe,YAAY,cAAc,MAAM,IAAI,WAAW,CAAC;AAGvE,QAAI,aAAa;AACjB,QAAI,mBAAmB;AACvB,QAAI,mBAAmB;AACvB,QAAI,oBAAoB;AACxB,QAAI,YAAY;AAChB,QAAI,kBAAkB;AACtB,UAAM,YAAY,KAAK,IAAI;AAE3B,WAAO;AAAA,MACL,WAAW;AAAA;AAAA,QAET,gBAAgB,OAAO,QAAQ;AAC7B;AAAA,QACF;AAAA;AAAA,QAGA,mBAAmB,OAAO,QAAQ;AAChC;AAGA,cAAI,IAAI,OAAO;AACb,gCAAoB,IAAI,MAAM;AAC9B,iCAAqB,IAAI,MAAM;AAI/B,gBAAI,eAAe;AACjB,kBAAI;AAGF,sBAAM,YAAY,IAAI,QAAQ,MAAM,SAAS,GAAG,IAC5C,IAAI,QAAQ,MAAM,MAAM,GAAG,EAAE,CAAC,IAC9B,IAAI,QAAQ;AAGhB,sBAAM,eAAe,cAAc;AAAA,kBACjC;AAAA,kBACA,IAAI,MAAM;AAAA,kBACV,IAAI,MAAM;AAAA,gBACZ;AAEA,oBAAI,cAAc;AAChB,+BAAa,aAAa;AAAA,gBAC5B;AAAA,cACF,SAAS,OAAO;AAGd,oBAAI,aAAa;AACf,0BAAQ,KAAK,yCAA+B,KAAK;AAAA,gBACnD;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAGA,gBAAM,QAAuB;AAAA,YAC3B;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,YACA,aAAa,mBAAmB;AAAA,YAChC,WAAW,YAAY;AAAA,YACvB,gBAAgB,SAAS,KAAK,IAAI,IAAI,aAAa,KAAM,QAAQ,CAAC,CAAC;AAAA,UACrE;AAGA,cAAI,YAAY;AACd,uBAAW,KAAK;AAAA,UAClB;AAGA,cAAI,aAAa;AACf,kBAAM,kBACJ,MAAM,eAAe,MACjB,IAAI,MAAM,cAAc,KAAM,QAAQ,CAAC,CAAC,MACxC,GAAG,MAAM,WAAW;AAE1B,kBAAM,gBAAgB,MAAM,YAAY,IAAI,IAAI,MAAM,UAAU,QAAQ,CAAC,CAAC,KAAK;AAE/E,oBAAQ;AAAA,cACN,kCAA2B,MAAM,gBAAgB,MAAM,eAAe,aAAa,aAAa,MAAM,MAAM,cAAc;AAAA,YAC5H;AAAA,UACF;AAAA,QACF;AAAA;AAAA,QAGA,2BAA2B,OAAO,QAAQ;AACxC,cAAI,IAAI,QAAQ,IAAI,OAAO,GAAG;AAC5B,+BAAmB,IAAI;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA8DA,OAAO,eAA2B;AAChC,WAAO;AAAA,MACL,WAAW;AAAA,QACT,gBAAgB,OAAO,QAAQ;AAC7B,kBAAQ,MAAM,+BAA0B,IAAI,SAAS,MAAM,IAAI,MAAM,OAAO;AAC5E,kBAAQ,MAAM,aAAa,IAAI,QAAQ,KAAK,EAAE;AAC9C,kBAAQ,MAAM,iBAAiB,IAAI,SAAS,EAAE;AAAA,QAChD;AAAA,QACA,2BAA2B,OAAO,QAAQ;AACxC,cAAI,IAAI,OAAO;AACb,oBAAQ,MAAM,wBAAmB,IAAI,UAAU,EAAE;AACjD,oBAAQ,MAAM,aAAa,IAAI,KAAK,EAAE;AACtC,oBAAQ,MAAM,kBAAkB,KAAK,UAAU,IAAI,YAAY,MAAM,CAAC,CAAC;AAAA,UACzE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BA,OAAO,qBAAiC;AACtC,WAAO;AAAA,MACL,WAAW;AAAA,QACT,cAAc,OAAO,QAAQ;AAC3B,gBAAM,QAAQ,IAAI,MAAM,eAAe,IAAI,MAAM;AACjD,gBAAM,WAAY,QAAQ,IAAI,MAAM,eAAgB,KAAK,QAAQ,CAAC;AAClE,kBAAQ;AAAA,YACN,gCAAoB,IAAI,MAAM,QAAQ,MAAM,IAAI,MAAM,YAAY,WAAM,IAAI,MAAM,WAAW,kBAAkB,KAAK,KAAK,OAAO;AAAA,UAClI;AACA,kBAAQ,IAAI,gBAAgB,IAAI,MAAM,cAAc,WAAM,IAAI,MAAM,aAAa,EAAE;AACnF,cAAI,IAAI,MAAM,mBAAmB,GAAG;AAClC,oBAAQ;AAAA,cACN,kBAAkB,IAAI,MAAM,gBAAgB,iBAAiB,IAAI,MAAM,gBAAgB;AAAA,YACzF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0CA,OAAO,SAAqB;AAC1B,WAAO,CAAC;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsFA,OAAO,SAAS,UAAoC;AAClD,UAAM,SAAqB;AAAA,MACzB,WAAW,CAAC;AAAA,MACZ,cAAc,CAAC;AAAA,MACf,aAAa,CAAC;AAAA,IAChB;AAGA,eAAW,SAAS,UAAU;AAC5B,UAAI,MAAM,WAAW;AACnB,mBAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,MAAM,SAAS,GAAG;AAC5D,gBAAM,WAAW;AACjB,cAAI,OAAO,UAAW,QAAQ,GAAG;AAE/B,kBAAM,WAAW,OAAO,UAAW,QAAQ;AAC3C,mBAAO,UAAW,QAAQ,IAAI,OAAO,QAAa;AAChD,oBAAM,SAAS,GAAG;AAClB,oBAAM,QAAQ,GAAG;AAAA,YACnB;AAAA,UACF,OAAO;AACL,mBAAO,UAAW,QAAQ,IAAI;AAAA,UAChC;AAAA,QACF;AAAA,MACF;AAKA,UAAI,MAAM,cAAc;AACtB,eAAO,OAAO,OAAO,cAAe,MAAM,YAAY;AAAA,MACxD;AAGA,UAAI,MAAM,aAAa;AACrB,eAAO,OAAO,OAAO,aAAc,MAAM,WAAW;AAAA,MACtD;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4DA,OAAO,WAAW,UAA0B,CAAC,GAAe;AAC1D,WAAO,aAAY;AAAA,MACjB,aAAY,QAAQ,OAAO;AAAA,MAC3B,aAAY,OAAO;AAAA,MACnB,aAAY,cAAc;AAAA,MAC1B,aAAY,aAAa;AAAA,IAC3B;AAAA,EACF;AACF;;;ACn7BA;AAUA;AAGA;;;AC3BA;AAGA;;;ACaA;AAkHO,SAAS,sBAAsB,SAA4C;AAChF,QAAM,EAAE,QAAAC,UAAS,UAAU,cAAc,MAAM,SAAS,IAAI,WAAW,CAAC;AAExE,SAAO;AAAA,IACL,aAAa;AAAA,MACX,eAAe,OAAO,QAAQ;AAC5B,cAAM,YAAY,IAAI,YAAY;AAClC,cAAM,gBAAgB,IAAI;AAC1B,cAAM,WAAW,YAAY;AAG7B,YAAIA,YAAW,UAAU,WAAW,KAAK;AACvC,iBAAO,EAAE,QAAQ,UAAU;AAAA,QAC7B;AACA,YAAIA,YAAW,YAAY,WAAW,KAAK;AACzC,iBAAO,EAAE,QAAQ,UAAU;AAAA,QAC7B;AAGA,cAAM,YAAY,gBAAgB;AAClC,cAAM,cAA2B;AAAA,UAC/B;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAGA,YAAI,OAAO,oBAAoB,UAAU,cAAc,uBAAuB,WAAW;AAGzF,YAAI,eAAe,YAAY,KAAK;AAClC,kBAAQ;AAAA,QACV;AAGA,cAAM,WAAW,CAAC,GAAG,IAAI,QAAQ,QAAQ;AAGzC,YAAI,gBAAgB;AACpB,iBAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,cAAI,SAAS,CAAC,EAAE,SAAS,QAAQ;AAC/B,4BAAgB;AAChB;AAAA,UACF;AAAA,QACF;AAEA,YAAI,iBAAiB,GAAG;AAEtB,mBAAS,OAAO,gBAAgB,GAAG,GAAG;AAAA,YACpC,MAAM;AAAA,YACN,SAAS,iBAAiB,IAAI;AAAA,UAChC,CAAC;AAAA,QACH,OAAO;AAEL,mBAAS,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,SAAS,iBAAiB,IAAI;AAAA,UAChC,CAAC;AAAA,QACH;AAEA,eAAO;AAAA,UACL,QAAQ;AAAA,UACR,iBAAiB,EAAE,SAAS;AAAA,QAC9B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAuBO,SAAS,mBAAmB,SAAiD;AAClF,QAAM;AAAA,IACJ,0BAA0B;AAAA,IAC1B,UAAU,cAAc;AAAA,IACxB,UAAU;AAAA,EACZ,IAAI,WAAW,CAAC;AAEhB,SAAO;AAAA,IACL,aAAa;AAAA,MACX,cAAc,OAAO,QAAQ;AAC3B,YAAI,CAAC,SAAS;AACZ,iBAAO,EAAE,QAAQ,WAAW;AAAA,QAC9B;AAGA,YAAI,IAAI,kBAAkB,KAAK,IAAI,kBAAkB,yBAAyB;AAC5E,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,UAAU;AAAA,cACR;AAAA,gBACE,MAAM;AAAA,gBACN,SAAS,iBAAiB,OAAO;AAAA,cACnC;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,eAAO,EAAE,QAAQ,WAAW;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AACF;AA2BO,SAAS,YAAY,QAAiC;AAC3D,QAAM,eAA6B,CAAC;AAGpC,MAAI,OAAO,mBAAmB;AAC5B,UAAM,UAAU,OAAO,OAAO,sBAAsB,YAAY,CAAC,IAAI,OAAO;AAC5E,iBAAa,KAAK,sBAAsB,OAAO,CAAC;AAAA,EAClD;AAGA,MAAI,OAAO,iBAAiB;AAC1B,UAAM,UAAU,OAAO,OAAO,oBAAoB,YAAY,CAAC,IAAI,OAAO;AAC1E,iBAAa,KAAK,mBAAmB,OAAO,CAAC;AAAA,EAC/C;AAGA,MAAI,OAAO,QAAQ;AACjB,iBAAa,KAAK,GAAG,OAAO,MAAM;AAAA,EACpC;AAEA,SAAO,YAAY,MAAM,GAAG,YAAY;AAC1C;;;ADtPA;;;AHcA;;;AKtDO,SAAS,aAAa,OAAyB;AACpD,MAAI,EAAE,iBAAiB,OAAQ,QAAO;AAGtC,MAAI,MAAM,SAAS,aAAc,QAAO;AAGxC,MAAI,MAAM,SAAS,4BAA6B,QAAO;AAGvD,MAAI,MAAM,SAAS,oBAAqB,QAAO;AAG/C,QAAM,UAAU,MAAM,QAAQ,YAAY;AAC1C,MAAI,QAAQ,SAAS,OAAO,EAAG,QAAO;AACtC,MAAI,QAAQ,SAAS,WAAW,EAAG,QAAO;AAC1C,MAAI,QAAQ,SAAS,UAAU,EAAG,QAAO;AAEzC,SAAO;AACT;;;ALuCA;AAIA;AAoBA;;;AMqKO,SAAS,WAAW,OAA0C;AACnE,SAAO,MAAM,KAAK,WAAW,WAAW;AAC1C;AAKO,SAAS,cAAc,OAA6C;AACzE,SAAO,MAAM,KAAK,WAAW,SAAS;AACxC;AAKO,SAAS,gBAAgB,OAAgC;AAC9D,SAAO,MAAM,QAAQ;AACvB;AAKO,SAAS,YAAY,OAAgC;AAC1D,SAAO,MAAM,UAAU;AACzB;AASO,SAAS,cAAc,QAA0B,OAAiC;AACvF,SAAO,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,KAAK;AAC/C;AAKO,SAAS,eAAe,QAA0B,UAAoC;AAC3F,SAAO,OAAO,OAAO,CAAC,MAAM,EAAE,aAAa,QAAQ;AACrD;AAKO,SAAS,iBAAiB,QAA4C;AAC3E,SAAO,cAAc,QAAQ,CAAC;AAChC;AAKO,SAAS,cAAc,QAAgE;AAC5F,QAAM,SAAS,oBAAI,IAAqC;AAExD,aAAW,SAAS,QAAQ;AAC1B,UAAM,WAAW,MAAM;AACvB,QAAI,CAAC,OAAO,IAAI,QAAQ,GAAG;AACzB,aAAO,IAAI,UAAU,CAAC,CAAC;AAAA,IACzB;AACA,WAAO,IAAI,QAAQ,GAAG,KAAK,KAAK;AAAA,EAClC;AAEA,SAAO;AACT;;;ANvLA;AAkBA;AASA;AAEA;AA0BA;AAQA;AAQA;AAEA;AAEA;AAMA;AACA;AAEA;AACA;AAEA;AAIA;;;AOvNA;AA4BO,SAAS,cAAc,OAAgC,CAAC,GAAW;AACxE,SAAO,KAAK,UAAU,EAAE,SAAS,MAAM,GAAG,KAAK,CAAC;AAClD;AAkBO,SAAS,YAAY,SAAiB,SAA2C;AACtF,SAAO,KAAK,UAAU,EAAE,OAAO,SAAS,GAAG,QAAQ,CAAC;AACtD;AAUO,SAAS,gBAAgB,OAAwB;AACtD,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAyBO,SAAS,kBACd,SAC8D;AAC9D,SAAO,OAAO,QAAiB,QAA4C;AACzE,QAAI;AACF,aAAO,MAAM,QAAQ,QAAQ,GAAG;AAAA,IAClC,SAAS,OAAO;AACd,aAAO,YAAY,gBAAgB,KAAK,CAAC;AAAA,IAC3C;AAAA,EACF;AACF;AAeO,SAAS,kBACd,MACA,MACA,UACA,SACmB;AACnB,QAAM,SAAS,gBAAgB,SAAS,OAAO,OAAO,KAAK,IAAI;AAC/D,SAAO;AAAA,IACL;AAAA,IACA,MAAM,OAAO,SAAS,QAAQ;AAAA,IAC9B;AAAA,IACA,aAAa,SAAS;AAAA,IACtB,UAAU,SAAS;AAAA,IACnB,UAAU,SAAS;AAAA,EACrB;AACF;AAuBO,SAAS,gBACd,QACA,OACA,MAC8B;AAC9B,MAAI,MAAM,WAAW,GAAG;AACtB,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAoCO,SAAS,gBACd,QACA,WACA,SAC8B;AAC9B,QAAM,SAAS,qBAAqB,SAAS,YAAY,OAAO,KAAK,SAAS;AAC9E,QAAM,WAAW,SAAS,YAAY,oBAAoB,MAAM;AAEhE,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,MAAM,OAAO,SAAS,QAAQ;AAAA,QAC9B;AAAA,QACA,aAAa,SAAS;AAAA,QACtB,UAAU,SAAS;AAAA,QACnB,UAAU,SAAS;AAAA,MACrB;AAAA,IACF;AAAA,IACA,MAAM,SAAS;AAAA,EACjB;AACF;AAuCO,SAAS,iBACd,QACA,QACA,MAC8B;AAC9B,MAAI,OAAO,WAAW,GAAG;AACvB,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,QAAM,QAA6B,OAAO,IAAI,CAAC,KAAK,UAAU;AAC5D,UAAM,SAAS,IAAI,gBAAgB,SAAS,IAAI,OAAO,OAAO,KAAK,IAAI,IAAI;AAC3E,UAAM,WAAW,IAAI,YAAY,oBAAoB,MAAM;AAE3D,QAAI,CAAC,UAAU;AACb,YAAM,IAAI;AAAA,QACR,iDAAiD,KAAK;AAAA,MACxD;AAAA,IACF;AAEA,WAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM,OAAO,SAAS,QAAQ;AAAA,MAC9B;AAAA,MACA,aAAa,IAAI;AAAA,MACjB,UAAU,IAAI;AAAA,MACd,UAAU,IAAI;AAAA,IAChB;AAAA,EACF,CAAC;AAED,SAAO,EAAE,QAAQ,OAAO,KAAK;AAC/B;AAoCO,SAAS,gBACd,QACA,WACA,SAC8B;AAC9B,QAAM,SAAS,qBAAqB,SAAS,YAAY,OAAO,KAAK,SAAS;AAC9E,QAAM,WAAW,SAAS,YAAY,oBAAoB,MAAM;AAEhE,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,WAAsC,SAAS,aACjD,EAAE,YAAY,QAAQ,WAAW,IACjC;AAEJ,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,MAAM,OAAO,SAAS,QAAQ;AAAA,QAC9B;AAAA,QACA,aAAa,SAAS;AAAA,QACtB;AAAA,QACA,UAAU,SAAS;AAAA,MACrB;AAAA,IACF;AAAA,IACA,MAAM,SAAS;AAAA,EACjB;AACF;AAoCO,SAAS,eACd,QACA,UACA,UACA,SAC8B;AAC9B,QAAM,SAAS,oBAAoB,SAAS,WAAW,OAAO,KAAK,QAAQ;AAE3E,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,MACL;AAAA,QACE,MAAM;AAAA,QACN,MAAM,OAAO,SAAS,QAAQ;AAAA,QAC9B;AAAA,QACA,aAAa,SAAS;AAAA,QACtB,UAAU,SAAS;AAAA,MACrB;AAAA,IACF;AAAA,IACA,MAAM,SAAS;AAAA,EACjB;AACF;;;AP3GA;;;AQjSO,SAAS,yBACd,QACA,QACqB;AACrB,QAAM,SAAS,OAAO,UAAU,MAAM;AAEtC,MAAI,OAAO,SAAS;AAClB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM,OAAO;AAAA,IACf;AAAA,EACF;AAEA,QAAM,SAA4B,OAAO,MAAM,OAAO,IAAI,CAAC,WAAW;AAAA,IACpE,MAAM,MAAM,KAAK,KAAK,GAAG,KAAK;AAAA,IAC9B,SAAS,MAAM;AAAA,EACjB,EAAE;AAEF,QAAM,iBAAiB,uBAAuB,OAAO,IAAI,CAAC,MAAM,GAAG,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC;AAErG,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO;AAAA,IACP;AAAA,EACF;AACF;AAiCO,SAAS,qBACd,QACA,QACkB;AAClB,MAAI,CAAC,OAAO,iBAAiB;AAC3B,WAAO;AAAA,MACL,SAAS;AAAA,MACT,MAAM;AAAA,IACR;AAAA,EACF;AAEA,SAAO,yBAAyB,OAAO,iBAAiB,MAAM;AAChE;;;AR+NA;AACA;AAEA;;;AShTO,SAAS,aACd,KACA,YACA,SACG;AACH,QAAM,EAAE,SAAS,aAAa,WAAW,cAAc,cAAc,IAAI;AAGzE,MAAI,YAAY,QAAW;AAEzB,QAAI,iBAAiB,YAAY,WAAW;AAAA,IAE5C,OAAO;AACL,aAAO;AAAA,IACT;AAAA,EACF;AAGA,MAAI,eAAe,IAAI,gBAAgB;AACrC,UAAM,cAAc,IAAI,eAAe,UAAU;AACjD,QAAI,eAAe,eAAe,aAAa;AAC7C,YAAM,QAAQ,YAAY,WAAW;AAErC,UAAI,iBAAiB,UAAU,WAAW;AAAA,MAE1C,WAAW,UAAU,QAAW;AAC9B,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,MAAI,aAAa,IAAI,eAAe,aAAa,IAAI,aAAa;AAChE,UAAM,cAAc,IAAI,YAAY,SAAS;AAC7C,QAAI,gBAAgB,QAAW;AAC7B,aAAO;AAAA,IACT;AAAA,EACF;AAGA,SAAO;AACT;AA8BO,SAAS,cACd,KACA,YACA,QACG;AACH,QAAM,SAAkC,CAAC;AAEzC,aAAW,CAAC,KAAK,OAAO,KAAK,OAAO,QAAQ,MAAM,GAAG;AACnD,WAAO,GAAG,IAAI,aAAa,KAAK,YAAY,OAAuC;AAAA,EACrF;AAEA,SAAO;AACT;AAsBO,SAAS,qBACd,KACA,YACA,cACA,cACQ;AACR,SAAO,aAAa,KAAK,YAAY;AAAA,IACnC,SAAS;AAAA,IACT,aAAa;AAAA,IACb,WAAW;AAAA,IACX,cAAc;AAAA,IACd,eAAe;AAAA,EACjB,CAAC;AACH;AAqBO,SAAS,uBACd,KACA,YACA,gBACA,gBACQ;AACR,SAAO,aAAa,KAAK,YAAY;AAAA,IACnC,SAAS;AAAA,IACT,aAAa;AAAA,IACb,cAAc;AAAA,EAChB,CAAC;AACH;;;ATsKA;AAIA;AACA;AACA;;;AUvVO,SAAS,SAASC,OAAc,WAAmB,SAAS,OAAe;AAChF,MAAIA,MAAK,UAAU,UAAW,QAAOA;AACrC,QAAM,aAAa,YAAY,OAAO;AACtC,MAAI,cAAc,EAAG,QAAO,OAAO,MAAM,GAAG,SAAS;AACrD,SAAOA,MAAK,MAAM,GAAG,UAAU,IAAI;AACrC;AAiBO,SAAS,YAAY,OAAe,WAAW,GAAW;AAC/D,MAAI,UAAU,EAAG,QAAO;AAExB,QAAM,IAAI;AACV,QAAM,QAAQ,CAAC,KAAK,MAAM,MAAM,MAAM,MAAM,IAAI;AAChD,QAAM,IAAI,KAAK,MAAM,KAAK,IAAI,KAAK,IAAI,KAAK,IAAI,CAAC,CAAC;AAClD,QAAM,OAAO,QAAQ,KAAK,IAAI,GAAG,CAAC;AAGlC,QAAM,YAAY,OAAO,MAAM,IAAI,KAAK,SAAS,IAAI,KAAK,QAAQ,QAAQ;AAE1E,SAAO,GAAG,SAAS,IAAI,MAAM,CAAC,CAAC;AACjC;AAkBO,SAAS,WACd,SACA,UAAsC;AAAA,EACpC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,KAAK;AAAA,EACL,MAAM;AAAA,EACN,QAAQ;AACV,GACQ;AACR,MAAI;AACF,UAAM,OAAO,IAAI,KAAK,OAAO;AAC7B,WAAO,KAAK,eAAe,QAAW,OAAO;AAAA,EAC/C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAiBO,SAAS,eACd,IACA,UAAiC,CAAC,GAC1B;AACR,MAAI,KAAK,KAAM;AACb,WAAO,GAAG,KAAK,MAAM,EAAE,CAAC;AAAA,EAC1B;AAEA,QAAM,UAAU,KAAK,MAAM,KAAK,GAAI;AACpC,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AAErC,MAAI,QAAQ,GAAG;AACb,UAAM,mBAAmB,UAAU;AACnC,UAAM,mBAAmB,UAAU;AACnC,QAAI,QAAQ,SAAS;AACnB,aAAO,GAAG,KAAK,KAAK,gBAAgB;AAAA,IACtC;AACA,WAAO,mBAAmB,IACtB,GAAG,KAAK,KAAK,gBAAgB,KAAK,gBAAgB,MAClD,GAAG,KAAK,KAAK,gBAAgB;AAAA,EACnC;AAEA,MAAI,UAAU,GAAG;AACf,UAAM,mBAAmB,UAAU;AACnC,WAAO,mBAAmB,IACtB,GAAG,OAAO,KAAK,gBAAgB,MAC/B,GAAG,OAAO;AAAA,EAChB;AAGA,QAAM,OAAO,KAAK;AAClB,SAAO,OAAO,MAAM,IAAI,GAAG,IAAI,MAAM,GAAG,KAAK,QAAQ,CAAC,CAAC;AACzD;AAeO,IAAM,SAAS;AAAA,EACpB;AAAA,EACA,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU;AACZ;;;ACnIO,SAAS,YAAY,KAAa,KAAqB;AAC5D,SAAO,KAAK,MAAM,KAAK,OAAO,KAAK,MAAM,MAAM,EAAE,IAAI;AACvD;AAoBA,eAAsB,WAAW,MAAM,IAAI,MAAM,KAAoB;AACnE,QAAM,QAAQ,YAAY,KAAK,GAAG;AAClC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,CAAC;AAC5D;AA2BA,eAAsB,YACpB,IACA,WACA,QACY;AACZ,SAAO,IAAI,QAAW,CAAC,SAAS,WAAW;AAEzC,QAAI,QAAQ,SAAS;AACnB,aAAO,IAAI,MAAM,mBAAmB,CAAC;AACrC;AAAA,IACF;AAEA,QAAI,UAAU;AACd,UAAM,YAAY,WAAW,MAAM;AACjC,UAAI,CAAC,SAAS;AACZ,kBAAU;AACV,eAAO,IAAI,MAAM,6BAA6B,SAAS,IAAI,CAAC;AAAA,MAC9D;AAAA,IACF,GAAG,SAAS;AAGZ,UAAM,eAAe,MAAM;AACzB,UAAI,CAAC,SAAS;AACZ,kBAAU;AACV,qBAAa,SAAS;AACtB,eAAO,IAAI,MAAM,mBAAmB,CAAC;AAAA,MACvC;AAAA,IACF;AAEA,YAAQ,iBAAiB,SAAS,YAAY;AAE9C,OAAG,EACA,KAAK,CAAC,WAAW;AAChB,UAAI,CAAC,SAAS;AACZ,kBAAU;AACV,qBAAa,SAAS;AACtB,gBAAQ,oBAAoB,SAAS,YAAY;AACjD,gBAAQ,MAAM;AAAA,MAChB;AAAA,IACF,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,UAAI,CAAC,SAAS;AACZ,kBAAU;AACV,qBAAa,SAAS;AACtB,gBAAQ,oBAAoB,SAAS,YAAY;AACjD,eAAO,KAAK;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACL,CAAC;AACH;AA+CA,eAAsB,UACpB,IACA,UAAwB,CAAC,GACb;AACZ,QAAM;AAAA,IACJ,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,WAAW;AAAA,IACX,cAAc,MAAM;AAAA,IACpB;AAAA,EACF,IAAI;AAEJ,MAAI;AACJ,MAAI,eAAe;AAEnB,WAAS,UAAU,GAAG,WAAW,YAAY,WAAW;AACtD,QAAI;AACF,aAAO,MAAM,GAAG;AAAA,IAClB,SAAS,OAAO;AACd,kBAAY;AAGZ,UAAI,WAAW,cAAc,CAAC,YAAY,OAAO,OAAO,GAAG;AACzD,cAAM;AAAA,MACR;AAGA,YAAM,WAAW,KAAK,IAAI,cAAc,QAAQ;AAGhD,gBAAU,OAAO,UAAU,GAAG,QAAQ;AAGtC,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,QAAQ,CAAC;AAG5D,UAAI,YAAY,eAAe;AAC7B,wBAAgB;AAAA,MAClB,OAAO;AACL,wBAAgB;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAGA,QAAM;AACR;AAcO,IAAM,SAAS;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AClIO,IAAe,qBAAf,MAEP;AAAA;AAAA,EAEY,WAAW,oBAAI,IAAsB;AAAA;AAAA,EAGrC,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQZ,WAAW,QAAwB;AAC3C,WAAO,GAAG,MAAM,GAAG,EAAE,KAAK,SAAS;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA,EAiBA,WAAW,IAAkC;AAC3C,WAAO,KAAK,SAAS,IAAI,EAAE;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,IAAsB;AACnC,UAAM,UAAU,KAAK,SAAS,IAAI,EAAE;AACpC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,sBAAsB,EAAE,EAAE;AAAA,IAC5C;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,eAAyB;AACvB,WAAO,MAAM,KAAK,KAAK,SAAS,KAAK,CAAC;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,IAAqB;AAC9B,WAAO,KAAK,SAAS,IAAI,EAAE;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAA0B;AAC9B,UAAM,MAAM,KAAK,aAAa,EAAE,QAAQ;AACxC,eAAW,MAAM,KAAK;AACpB,UAAI;AACF,cAAM,KAAK,aAAa,EAAE;AAAA,MAC5B,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;AAeO,IAAM,uBAAN,cAA6C,mBAAuC;AAAA;AAAA;AAAA;AAAA,EAIzF,MAAM,cAAc,MAAkC;AACpD,UAAM,KAAK,KAAK,WAAW,GAAG;AAC9B,QAAI,SAAS,QAAW;AACtB,WAAK,SAAS,IAAI,IAAI,IAAI;AAAA,IAC5B;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,IAA2B;AAC5C,SAAK,SAAS,OAAO,EAAE;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,IAAY,MAAsB;AAC3C,SAAK,SAAS,IAAI,IAAI,IAAI;AAAA,EAC5B;AACF;;;AClIA,SAAS,eAAe,KAAoC;AAC1D,MAAI,CAAC,KAAK,aAAa;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO,IAAI;AACb;AAiDO,SAAS,eACd,KACA,SACc;AACd,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,eAAe;AAAA,IACf,eAAe;AAAA,IACf,uBAAuB;AAAA,IACvB;AAAA,IACA;AAAA,EACF,IAAI;AAGJ,QAAM,EAAE,cAAAC,eAAc,QAAAC,QAAO,IAAI,eAAe,GAAG;AAGnD,QAAM,SAAS,IAAIA,QAAO;AAG1B,QAAM,QAAQ,qBAAqB,KAAK,MAAM,cAAc,YAAY;AAGxE,QAAM,gBAAgB,aAAa,KAAK,MAAM;AAAA,IAC5C,SAAS;AAAA,IACT,aAAa;AAAA,IACb,cAAc;AAAA,EAChB,CAAC;AAGD,MAAI,UAAU,IAAID,cAAa,MAAM,EAClC,UAAU,KAAK,EACf,YAAY,GAAG,OAAO,EACtB,kBAAkB,aAAa,EAC/B,kBAAkB,GAAG;AAIxB,MAAI,IAAI,mBAAmB;AACzB,cAAU,QAAQ,aAAa,IAAI,iBAAiB;AAAA,EACtD;AAGA,MAAI,cAAc;AAChB,cAAU,QAAQ,WAAW,YAAY;AAAA,EAC3C;AAEA,MAAI,OAAO;AACT,cAAU,QAAQ,UAAU,KAAK;AAAA,EACnC;AAEA,MAAI,gBAAgB,QAAW;AAC7B,cAAU,QAAQ,gBAAgB,WAAW;AAAA,EAC/C;AAGA,MAAI,IAAI,QAAQ;AACd,cAAU,QAAQ,WAAW,IAAI,MAAM;AAAA,EACzC;AAEA,SAAO;AACT;AAUO,SAAS,eAAe,KAAiC;AAC9D,SAAO,KAAK,gBAAgB;AAC9B;;;ACjEO,SAAS,cACd,aACmC;AACnC,QAAM,SAAS,YAAY;AAC3B,MAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAKO,SAAS,UACd,UACA,YACS;AACT,SAAO,UAAU,UAAU,UAAU,MAAM;AAC7C;AAMO,SAAS,iBACd,UACA,YAC4B;AAC5B,QAAM,SAAS,UAAU,UAAU,UAAU;AAC7C,MAAI,WAAW,OAAW,QAAO;AACjC,SAAO;AACT;AAKO,SAAS,aAAa,UAAsD;AACjF,SAAO,UAAU,cAAc,UAAa,OAAO,KAAK,SAAS,SAAS,EAAE,SAAS;AACvF;AAKO,SAAS,YACd,UACA,MACmC;AACnC,SAAO,UAAU,YAAY,IAAI;AACnC;AAKO,SAAS,cAAc,UAAuD;AACnF,MAAI,CAAC,UAAU,UAAW,QAAO,CAAC;AAClC,SAAO,OAAO,KAAK,SAAS,SAAS;AACvC;AAKO,SAAS,YAAY,UAAuD;AACjF,MAAI,CAAC,UAAU,QAAS,QAAO,CAAC;AAChC,SAAO,OAAO,KAAK,SAAS,OAAO;AACrC;;;AdkGO,SAASE,gBAAe,KAAoC;AACjE,MAAI,CAAC,KAAK,aAAa;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,IAEF;AAAA,EACF;AACA,SAAO,IAAI;AACb;","names":["init_constants","import_node_path","z","import_node_crypto","Anthropic","init_constants","stream","init_constants","response","images","cost","stream","text","OpenAI","init_constants","format","stream","text","providerSpecs","text","pointer","import_zod","equal","stream","stream","pRetry","getHostExports","import_zod","init_constants","timing","text","AgentBuilder","LLMist","getHostExports"]}
1
+ {"version":3,"sources":["../src/core/constants.ts","../src/providers/constants.ts","../src/core/input-content.ts","../src/core/model-shortcuts.ts","../src/gadgets/schema-validator.ts","../src/gadgets/registry.ts","../src/core/execution-tree.ts","../src/core/prompt-config.ts","../src/core/messages.ts","../src/gadgets/media-store.ts","../src/gadgets/exceptions.ts","../src/logging/logger.ts","../src/gadgets/schema-to-json.ts","../src/gadgets/gadget.ts","../src/gadgets/create-gadget.ts","../src/gadgets/output-viewer.ts","../src/agent/agent-internal-key.ts","../src/core/retry.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/conversation-manager.ts","../src/agent/event-handlers.ts","../src/agent/gadget-output-store.ts","../src/agent/hook-validators.ts","../src/providers/anthropic-models.ts","../src/providers/base-provider.ts","../src/providers/utils.ts","../src/providers/anthropic.ts","../src/providers/gemini-image-models.ts","../src/providers/gemini-models.ts","../src/providers/gemini-speech-models.ts","../src/providers/gemini.ts","../src/providers/openai-image-models.ts","../src/providers/openai-models.ts","../src/providers/openai-speech-models.ts","../src/providers/openai.ts","../src/providers/discovery.ts","../src/core/model-registry.ts","../src/core/namespaces/image.ts","../src/core/namespaces/speech.ts","../src/core/quick-methods.ts","../src/core/namespaces/text.ts","../src/core/namespaces/vision.ts","../src/core/options.ts","../src/core/client.ts","../src/gadgets/schema-introspector.ts","../src/gadgets/block-params.ts","../src/gadgets/cost-reporting-client.ts","../src/gadgets/error-formatter.ts","../src/gadgets/parser.ts","../src/gadgets/typed-gadget.ts","../src/gadgets/executor.ts","../src/agent/stream-processor.ts","../src/agent/agent.ts","../src/agent/builder.ts","../src/index.ts","../src/agent/hook-presets.ts","../src/agent/compaction/index.ts","../src/agent/index.ts","../src/agent/hints.ts","../src/core/errors.ts","../src/core/execution-events.ts","../src/gadgets/helpers.ts","../src/gadgets/validation.ts","../src/utils/config-resolver.ts","../src/utils/format.ts","../src/utils/timing.ts","../src/session/manager.ts","../src/agent/subagent.ts","../src/package/manifest.ts"],"sourcesContent":["// Gadget marker constants\nexport const GADGET_START_PREFIX = \"!!!GADGET_START:\";\nexport const GADGET_END_PREFIX = \"!!!GADGET_END\";\nexport const GADGET_ARG_PREFIX = \"!!!ARG:\";\n\n// Default configuration values\nexport const DEFAULT_MAX_TOKENS = 1024;\nexport const DEFAULT_MAX_ITERATIONS = 10;\n\n// Gadget output limiting defaults\n/** Default: gadget output limiting is enabled */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT = true;\n\n/** Default: limit gadget output to 15% of context window */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;\n\n/** Approximate characters per token for limit calculation */\nexport const CHARS_PER_TOKEN = 4;\n\n/** Fallback context window size if model is not in registry */\nexport const FALLBACK_CONTEXT_WINDOW = 128_000;\n","/**\n * 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 * Types and interfaces for multimodal input content.\n *\n * These types define the structure for sending images, audio, and other\n * media alongside text in LLM messages. They complement the output types\n * in media-types.ts.\n */\n\n// ============================================================================\n// MIME Types\n// ============================================================================\n\n/**\n * Supported image MIME types for input.\n * All major providers support these formats.\n */\nexport type ImageMimeType = \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\";\n\n/**\n * Supported audio MIME types for input.\n * Currently only Gemini supports audio input.\n */\nexport type AudioMimeType =\n | \"audio/mp3\"\n | \"audio/mpeg\"\n | \"audio/wav\"\n | \"audio/webm\"\n | \"audio/ogg\"\n | \"audio/flac\";\n\n// ============================================================================\n// Content Part Types\n// ============================================================================\n\n/**\n * Base interface for all content parts.\n */\nexport interface BaseContentPart {\n type: string;\n}\n\n/**\n * Text content part.\n */\nexport interface TextContentPart extends BaseContentPart {\n type: \"text\";\n text: string;\n}\n\n/**\n * Image content part.\n */\nexport interface ImageContentPart extends BaseContentPart {\n type: \"image\";\n source: ImageSource;\n}\n\n/**\n * Audio content part.\n * Currently only supported by Gemini.\n */\nexport interface AudioContentPart extends BaseContentPart {\n type: \"audio\";\n source: AudioSource;\n}\n\n/**\n * Union of all supported content part types.\n */\nexport type ContentPart = TextContentPart | ImageContentPart | AudioContentPart;\n\n// ============================================================================\n// Source Types\n// ============================================================================\n\n/**\n * Image can come from base64 data or a URL.\n */\nexport type ImageSource = ImageBase64Source | ImageUrlSource;\n\n/**\n * Base64-encoded image data.\n * Supported by all providers.\n */\nexport interface ImageBase64Source {\n type: \"base64\";\n mediaType: ImageMimeType;\n data: string;\n}\n\n/**\n * Image URL reference.\n * Only supported by OpenAI.\n */\nexport interface ImageUrlSource {\n type: \"url\";\n url: string;\n}\n\n/**\n * Audio source (base64 only).\n * URL sources are not currently supported for audio.\n */\nexport interface AudioSource {\n type: \"base64\";\n mediaType: AudioMimeType;\n data: string;\n}\n\n// ============================================================================\n// Type Guards\n// ============================================================================\n\n/**\n * Check if a content part is a text part.\n */\nexport function isTextPart(part: ContentPart): part is TextContentPart {\n return part.type === \"text\";\n}\n\n/**\n * Check if a content part is an image part.\n */\nexport function isImagePart(part: ContentPart): part is ImageContentPart {\n return part.type === \"image\";\n}\n\n/**\n * Check if a content part is an audio part.\n */\nexport function isAudioPart(part: ContentPart): part is AudioContentPart {\n return part.type === \"audio\";\n}\n\n/**\n * Check if an image source is base64.\n */\nexport function isBase64ImageSource(source: ImageSource): source is ImageBase64Source {\n return source.type === \"base64\";\n}\n\n/**\n * Check if an image source is a URL.\n */\nexport function isUrlImageSource(source: ImageSource): source is ImageUrlSource {\n return source.type === \"url\";\n}\n\n// ============================================================================\n// Helper Functions - Content Part Creation\n// ============================================================================\n\n/**\n * Create a text content part.\n *\n * @example\n * ```typescript\n * const part = text(\"What's in this image?\");\n * ```\n */\nexport function text(content: string): TextContentPart {\n return { type: \"text\", text: content };\n}\n\n/**\n * Create an image content part from base64-encoded data.\n *\n * @param data - Base64-encoded image data\n * @param mediaType - MIME type of the image\n *\n * @example\n * ```typescript\n * const part = imageFromBase64(base64Data, \"image/jpeg\");\n * ```\n */\nexport function imageFromBase64(data: string, mediaType: ImageMimeType): ImageContentPart {\n return {\n type: \"image\",\n source: { type: \"base64\", mediaType, data },\n };\n}\n\n/**\n * Create an image content part from a URL.\n * Note: Only supported by OpenAI.\n *\n * @param url - URL to the image (must be accessible)\n *\n * @example\n * ```typescript\n * const part = imageFromUrl(\"https://example.com/image.jpg\");\n * ```\n */\nexport function imageFromUrl(url: string): ImageContentPart {\n return {\n type: \"image\",\n source: { type: \"url\", url },\n };\n}\n\n/**\n * Magic bytes for detecting image MIME types.\n */\nconst IMAGE_MAGIC_BYTES: Array<{ bytes: number[]; mimeType: ImageMimeType }> = [\n { bytes: [0xff, 0xd8, 0xff], mimeType: \"image/jpeg\" },\n { bytes: [0x89, 0x50, 0x4e, 0x47], mimeType: \"image/png\" },\n { bytes: [0x47, 0x49, 0x46, 0x38], mimeType: \"image/gif\" },\n // WebP starts with RIFF....WEBP\n { bytes: [0x52, 0x49, 0x46, 0x46], mimeType: \"image/webp\" },\n];\n\n/**\n * Magic bytes for detecting audio MIME types.\n */\nconst AUDIO_MAGIC_BYTES: Array<{ bytes: number[]; mimeType: AudioMimeType }> = [\n // MP3 frame sync\n { bytes: [0xff, 0xfb], mimeType: \"audio/mp3\" },\n { bytes: [0xff, 0xfa], mimeType: \"audio/mp3\" },\n // ID3 tag (MP3)\n { bytes: [0x49, 0x44, 0x33], mimeType: \"audio/mp3\" },\n // OGG\n { bytes: [0x4f, 0x67, 0x67, 0x53], mimeType: \"audio/ogg\" },\n // WAV (RIFF)\n { bytes: [0x52, 0x49, 0x46, 0x46], mimeType: \"audio/wav\" },\n // WebM\n { bytes: [0x1a, 0x45, 0xdf, 0xa3], mimeType: \"audio/webm\" },\n // FLAC (fLaC)\n { bytes: [0x66, 0x4c, 0x61, 0x43], mimeType: \"audio/flac\" },\n];\n\n/**\n * Detect the MIME type of image data from magic bytes.\n *\n * @param data - Raw image data\n * @returns Detected MIME type or null if unknown\n */\nexport function detectImageMimeType(data: Buffer | Uint8Array): ImageMimeType | null {\n const bytes = data instanceof Buffer ? data : Buffer.from(data);\n\n for (const { bytes: magic, mimeType } of IMAGE_MAGIC_BYTES) {\n if (bytes.length >= magic.length) {\n let matches = true;\n for (let i = 0; i < magic.length; i++) {\n if (bytes[i] !== magic[i]) {\n matches = false;\n break;\n }\n }\n if (matches) {\n // Special case: RIFF could be WebP or WAV, check for WEBP marker\n if (mimeType === \"image/webp\") {\n // RIFF....WEBP - check bytes 8-11\n if (bytes.length >= 12) {\n const webpMarker =\n bytes[8] === 0x57 && bytes[9] === 0x45 && bytes[10] === 0x42 && bytes[11] === 0x50;\n if (!webpMarker) continue; // Not WebP, try next pattern\n }\n }\n return mimeType;\n }\n }\n }\n return null;\n}\n\n/**\n * Detect the MIME type of audio data from magic bytes.\n *\n * @param data - Raw audio data\n * @returns Detected MIME type or null if unknown\n */\nexport function detectAudioMimeType(data: Buffer | Uint8Array): AudioMimeType | null {\n const bytes = data instanceof Buffer ? data : Buffer.from(data);\n\n for (const { bytes: magic, mimeType } of AUDIO_MAGIC_BYTES) {\n if (bytes.length >= magic.length) {\n let matches = true;\n for (let i = 0; i < magic.length; i++) {\n if (bytes[i] !== magic[i]) {\n matches = false;\n break;\n }\n }\n if (matches) {\n // Special case: RIFF could be WAV or WebP, check for WAVE marker\n if (mimeType === \"audio/wav\") {\n // RIFF....WAVE - check bytes 8-11\n if (bytes.length >= 12) {\n const waveMarker =\n bytes[8] === 0x57 && bytes[9] === 0x41 && bytes[10] === 0x56 && bytes[11] === 0x45;\n if (!waveMarker) continue; // Not WAV, try next pattern\n }\n }\n return mimeType;\n }\n }\n }\n return null;\n}\n\n/**\n * Convert data to base64 string.\n *\n * @param data - Data to encode (Buffer, Uint8Array, or already base64 string)\n * @returns Base64-encoded string\n */\nexport function toBase64(data: Buffer | Uint8Array | string): string {\n if (typeof data === \"string\") {\n return data; // Assume already base64\n }\n return Buffer.from(data).toString(\"base64\");\n}\n\n/**\n * Create an image content part from a Buffer or Uint8Array.\n * Automatically detects the MIME type if not provided.\n *\n * @param buffer - Image data\n * @param mediaType - Optional MIME type (auto-detected if not provided)\n *\n * @example\n * ```typescript\n * const imageData = await fs.readFile(\"photo.jpg\");\n * const part = imageFromBuffer(imageData); // Auto-detects JPEG\n * ```\n */\nexport function imageFromBuffer(\n buffer: Buffer | Uint8Array,\n mediaType?: ImageMimeType,\n): ImageContentPart {\n const detectedType = mediaType ?? detectImageMimeType(buffer);\n if (!detectedType) {\n throw new Error(\n \"Could not detect image MIME type. Please provide the mediaType parameter explicitly.\",\n );\n }\n return {\n type: \"image\",\n source: {\n type: \"base64\",\n mediaType: detectedType,\n data: toBase64(buffer),\n },\n };\n}\n\n/**\n * Create an audio content part from base64-encoded data.\n *\n * @param data - Base64-encoded audio data\n * @param mediaType - MIME type of the audio\n *\n * @example\n * ```typescript\n * const part = audioFromBase64(base64Audio, \"audio/mp3\");\n * ```\n */\nexport function audioFromBase64(data: string, mediaType: AudioMimeType): AudioContentPart {\n return {\n type: \"audio\",\n source: { type: \"base64\", mediaType, data },\n };\n}\n\n/**\n * Create an audio content part from a Buffer or Uint8Array.\n * Automatically detects the MIME type if not provided.\n *\n * @param buffer - Audio data\n * @param mediaType - Optional MIME type (auto-detected if not provided)\n *\n * @example\n * ```typescript\n * const audioData = await fs.readFile(\"audio.mp3\");\n * const part = audioFromBuffer(audioData); // Auto-detects MP3\n * ```\n */\nexport function audioFromBuffer(\n buffer: Buffer | Uint8Array,\n mediaType?: AudioMimeType,\n): AudioContentPart {\n const detectedType = mediaType ?? detectAudioMimeType(buffer);\n if (!detectedType) {\n throw new Error(\n \"Could not detect audio MIME type. Please provide the mediaType parameter explicitly.\",\n );\n }\n return {\n type: \"audio\",\n source: {\n type: \"base64\",\n mediaType: detectedType,\n data: toBase64(buffer),\n },\n };\n}\n\n// ============================================================================\n// Data URL Utilities\n// ============================================================================\n\n/**\n * Check if a string is a data URL.\n *\n * @param input - String to check\n * @returns True if it's a data URL\n */\nexport function isDataUrl(input: string): boolean {\n return input.startsWith(\"data:\");\n}\n\n/**\n * Parse a data URL into its components.\n *\n * @param url - Data URL to parse\n * @returns Parsed components or null if invalid\n *\n * @example\n * ```typescript\n * const result = parseDataUrl(\"data:image/jpeg;base64,/9j/4AAQ...\");\n * // { mimeType: \"image/jpeg\", data: \"/9j/4AAQ...\" }\n * ```\n */\nexport function parseDataUrl(url: string): { mimeType: string; data: string } | null {\n const match = url.match(/^data:([^;]+);base64,(.+)$/);\n if (!match) return null;\n return { mimeType: match[1], data: match[2] };\n}\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 *\n * Updated: 2025-12-20\n */\nexport const MODEL_ALIASES: Record<string, string> = {\n // OpenAI aliases - GPT-5.2 is the latest flagship\n gpt4: \"openai:gpt-4o\",\n gpt4o: \"openai:gpt-4o\",\n \"gpt4o-mini\": \"openai:gpt-4o-mini\",\n gpt5: \"openai:gpt-5.2\", // Latest flagship\n \"gpt5.2\": \"openai:gpt-5.2\",\n \"gpt5.1\": \"openai:gpt-5.1\",\n \"gpt5-mini\": \"openai:gpt-5-mini\",\n \"gpt5-nano\": \"openai:gpt-5-nano\",\n \"gpt5-codex\": \"openai:gpt-5-codex\",\n o1: \"openai:o1\",\n o3: \"openai:o3\",\n \"o4-mini\": \"openai:o4-mini\",\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 - 2.5 Flash is the recommended fast model\n flash: \"gemini:gemini-2.5-flash\",\n \"gemini-flash\": \"gemini:gemini-2.5-flash\",\n \"flash-lite\": \"gemini:gemini-2.5-flash-lite\",\n \"gemini-pro\": \"gemini:gemini-3-pro-preview\",\n pro: \"gemini:gemini-3-pro-preview\",\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 { AbstractGadget } from \"./gadget.js\";\nimport { validateGadgetSchema } from \"./schema-validator.js\";\n\n// Type for gadget constructor\nexport type GadgetClass = new (...args: unknown[]) => AbstractGadget;\n\n// Type for gadget or gadget class\nexport type GadgetOrClass = AbstractGadget | GadgetClass;\n\nexport class GadgetRegistry {\n private readonly gadgets = new Map<string, AbstractGadget>();\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: AbstractGadget): 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: AbstractGadget): 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): AbstractGadget | 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(): AbstractGadget[] {\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 * First-class Execution Tree model for nested subagent support.\n *\n * The ExecutionTree is THE single source of truth for execution state.\n * All nodes (including nested subagent nodes) live in one tree.\n * Events are projections of tree changes.\n *\n * @module core/execution-tree\n */\n\nimport type { GadgetMediaOutput } from \"../gadgets/types.js\";\nimport type { LLMMessage } from \"./messages.js\";\nimport type { TokenUsage } from \"./options.js\";\n\n// =============================================================================\n// Node Identifiers\n// =============================================================================\n\n/**\n * Unique identifier for any execution node.\n * Format examples: \"llm_1\", \"gadget_abc123\", \"llm_1_2\" (nested)\n */\nexport type NodeId = string;\n\n/**\n * Node type discriminator.\n */\nexport type ExecutionNodeType = \"llm_call\" | \"gadget\";\n\n// =============================================================================\n// Execution Node Types\n// =============================================================================\n\n/**\n * Base properties shared by all execution nodes.\n */\ninterface BaseExecutionNode {\n /** Unique identifier for this node */\n id: NodeId;\n /** Node type discriminator */\n type: ExecutionNodeType;\n /** Parent node ID (null for root nodes) */\n parentId: NodeId | null;\n /** Nesting depth (0 = root, 1 = child of gadget, etc.) */\n depth: number;\n /** Path from root to this node: [\"llm_1\", \"gadget_abc\", \"llm_1_1\"] */\n path: NodeId[];\n /** Creation timestamp */\n createdAt: number;\n /** Completion timestamp (null if in progress) */\n completedAt: number | null;\n}\n\n/**\n * LLM call execution node.\n */\nexport interface LLMCallNode extends BaseExecutionNode {\n type: \"llm_call\";\n /** Iteration number within the agent loop (1-indexed for display) */\n iteration: number;\n /** Model identifier */\n model: string;\n /** Request messages (set when call starts) */\n request?: LLMMessage[];\n /** Accumulated response text */\n response: string;\n /** Token usage (set on completion) */\n usage?: TokenUsage;\n /** Finish reason from LLM */\n finishReason?: string | null;\n /** Cost in USD */\n cost?: number;\n /** Child node IDs (gadgets spawned by this LLM call) */\n children: NodeId[];\n}\n\n/**\n * Gadget execution state.\n */\nexport type GadgetState = \"pending\" | \"running\" | \"completed\" | \"failed\" | \"skipped\";\n\n/**\n * Gadget execution node.\n */\nexport interface GadgetNode extends BaseExecutionNode {\n type: \"gadget\";\n /** Invocation ID (LLM-generated or auto) */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Parameters passed to the gadget */\n parameters: Record<string, unknown>;\n /** Dependencies (other invocation IDs this gadget waits for) */\n dependencies: string[];\n /** Execution state */\n state: GadgetState;\n /** Result string (if completed successfully) */\n result?: string;\n /** Error message (if failed or skipped) */\n error?: string;\n /** Failed dependency invocation ID (if skipped due to dependency) */\n failedDependency?: string;\n /** Execution time in milliseconds */\n executionTimeMs?: number;\n /** Cost in USD */\n cost?: number;\n /** Media outputs from this gadget */\n media?: GadgetMediaOutput[];\n /** Child node IDs (nested LLM calls for subagent gadgets) */\n children: NodeId[];\n /** Whether this gadget is a subagent (has nested LLM calls) */\n isSubagent: boolean;\n}\n\n/**\n * Union of all execution node types.\n */\nexport type ExecutionNode = LLMCallNode | GadgetNode;\n\n// =============================================================================\n// Node Creation Parameters\n// =============================================================================\n\nexport interface AddLLMCallParams {\n /** Iteration number (1-indexed) */\n iteration: number;\n /** Model identifier */\n model: string;\n /** Request messages */\n request?: LLMMessage[];\n /** Parent node ID (for subagent LLM calls) */\n parentId?: NodeId | null;\n}\n\nexport interface AddGadgetParams {\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Parameters */\n parameters: Record<string, unknown>;\n /** Dependencies */\n dependencies?: string[];\n /** Parent LLM call node ID */\n parentId?: NodeId | null;\n}\n\nexport interface CompleteLLMCallParams {\n /** Accumulated response text */\n response?: string;\n /** Token usage */\n usage?: TokenUsage;\n /** Finish reason */\n finishReason?: string | null;\n /** Cost in USD */\n cost?: number;\n}\n\nexport interface CompleteGadgetParams {\n /** Result string */\n result?: string;\n /** Error message */\n error?: string;\n /** Failed dependency (for skipped gadgets) */\n failedDependency?: string;\n /** Execution time in ms */\n executionTimeMs?: number;\n /** Cost in USD */\n cost?: number;\n /** Media outputs */\n media?: GadgetMediaOutput[];\n}\n\n// =============================================================================\n// Event Types (imported from execution-events.ts)\n// =============================================================================\n\n// Forward declaration - actual types in execution-events.ts\nimport type { ExecutionEvent, ExecutionEventType } from \"./execution-events.js\";\n\nexport type { ExecutionEvent, ExecutionEventType };\n\n// =============================================================================\n// Event Listener Types\n// =============================================================================\n\n/** Event listener function type */\ntype EventListener = (event: ExecutionEvent) => void;\n\n// =============================================================================\n// ExecutionTree Class\n// =============================================================================\n\n/**\n * The Execution Tree - single source of truth for all execution state.\n *\n * Features:\n * - Stores all nodes (LLM calls, gadgets) in a hierarchical structure\n * - Emits events on mutations\n * - Provides query methods for aggregation (costs, media, descendants)\n * - Supports single shared tree model for nested subagents\n *\n * @example\n * ```typescript\n * const tree = new ExecutionTree();\n *\n * // Add root LLM call\n * const llmNode = tree.addLLMCall({ iteration: 1, model: \"sonnet\" });\n *\n * // Add gadget under the LLM call\n * const gadgetNode = tree.addGadget({\n * invocationId: \"gc_1\",\n * name: \"ReadFile\",\n * parameters: { path: \"/foo.txt\" },\n * parentId: llmNode.id,\n * });\n *\n * // Complete the gadget\n * tree.completeGadget(gadgetNode.id, { result: \"file contents\", executionTimeMs: 50 });\n *\n * // Query total cost\n * console.log(tree.getTotalCost());\n * ```\n */\nexport class ExecutionTree {\n private nodes = new Map<NodeId, ExecutionNode>();\n private rootIds: NodeId[] = [];\n private eventListeners = new Map<ExecutionEventType, Set<EventListener>>();\n private eventIdCounter = 0;\n private invocationIdToNodeId = new Map<string, NodeId>();\n\n // For async event streaming\n private eventQueue: ExecutionEvent[] = [];\n private eventWaiters: Array<(event: ExecutionEvent) => void> = [];\n private isCompleted = false;\n\n /**\n * Base depth for all nodes in this tree.\n * Used when this tree is a subagent's view into a parent tree.\n */\n public readonly baseDepth: number;\n\n /**\n * Parent node ID for subagent trees.\n * All root nodes in this tree will have this as their parentId.\n */\n public readonly parentNodeId: NodeId | null;\n\n constructor(options?: { baseDepth?: number; parentNodeId?: NodeId | null }) {\n this.baseDepth = options?.baseDepth ?? 0;\n this.parentNodeId = options?.parentNodeId ?? null;\n }\n\n // ===========================================================================\n // Node ID Generation\n // ===========================================================================\n\n private generateLLMCallId(iteration: number, parentId: NodeId | null): NodeId {\n if (parentId) {\n // Subagent LLM call: include parent info for uniqueness\n return `llm_${parentId}_${iteration}`;\n }\n return `llm_${iteration}`;\n }\n\n private gadgetIdCounter = 0;\n private generateGadgetId(invocationId: string): NodeId {\n return `gadget_${invocationId}_${++this.gadgetIdCounter}`;\n }\n\n // ===========================================================================\n // Event Emission\n // ===========================================================================\n\n private emit(event: ExecutionEvent): void {\n // Notify sync listeners\n const listeners = this.eventListeners.get(event.type);\n if (listeners) {\n for (const listener of listeners) {\n try {\n listener(event);\n } catch (error) {\n console.error(`Error in event listener for ${event.type}:`, error);\n }\n }\n }\n\n // Also emit to \"all\" listeners\n const allListeners = this.eventListeners.get(\"*\");\n if (allListeners) {\n for (const listener of allListeners) {\n try {\n listener(event);\n } catch (error) {\n console.error(\"Error in wildcard event listener:\", error);\n }\n }\n }\n\n // Push to async queue\n if (this.eventWaiters.length > 0) {\n const waiter = this.eventWaiters.shift();\n if (waiter) waiter(event);\n } else {\n this.eventQueue.push(event);\n }\n }\n\n private createBaseEventProps(node: ExecutionNode): {\n eventId: number;\n timestamp: number;\n nodeId: NodeId;\n parentId: NodeId | null;\n depth: number;\n path: NodeId[];\n } {\n return {\n eventId: ++this.eventIdCounter,\n timestamp: Date.now(),\n nodeId: node.id,\n parentId: node.parentId,\n depth: node.depth,\n path: node.path,\n };\n }\n\n // ===========================================================================\n // Node Creation\n // ===========================================================================\n\n /**\n * Add a new LLM call node to the tree.\n */\n addLLMCall(params: AddLLMCallParams): LLMCallNode {\n const parentId = params.parentId ?? this.parentNodeId;\n const parent = parentId ? this.nodes.get(parentId) : null;\n\n const depth = parent ? parent.depth + 1 : this.baseDepth;\n const path = parent ? [...parent.path] : [];\n\n const id = this.generateLLMCallId(params.iteration, parentId);\n path.push(id);\n\n const node: LLMCallNode = {\n id,\n type: \"llm_call\",\n parentId,\n depth,\n path,\n createdAt: Date.now(),\n completedAt: null,\n iteration: params.iteration,\n model: params.model,\n request: params.request,\n response: \"\",\n children: [],\n };\n\n this.nodes.set(id, node);\n\n if (!parentId) {\n this.rootIds.push(id);\n } else if (parent) {\n parent.children.push(id);\n }\n\n this.emit({\n type: \"llm_call_start\",\n ...this.createBaseEventProps(node),\n iteration: node.iteration,\n model: node.model,\n request: node.request,\n });\n\n return node;\n }\n\n /**\n * Add text to an LLM call's response (for streaming).\n */\n appendLLMResponse(nodeId: NodeId, chunk: string): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"llm_call\") {\n throw new Error(`LLM call node not found: ${nodeId}`);\n }\n\n (node as LLMCallNode).response += chunk;\n\n this.emit({\n type: \"llm_call_stream\",\n ...this.createBaseEventProps(node),\n chunk,\n });\n }\n\n /**\n * Complete an LLM call node.\n */\n completeLLMCall(nodeId: NodeId, params: CompleteLLMCallParams): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"llm_call\") {\n throw new Error(`LLM call node not found: ${nodeId}`);\n }\n\n const llmNode = node as LLMCallNode;\n llmNode.completedAt = Date.now();\n if (params.response !== undefined) llmNode.response = params.response;\n if (params.usage) llmNode.usage = params.usage;\n if (params.finishReason !== undefined) llmNode.finishReason = params.finishReason;\n if (params.cost !== undefined) llmNode.cost = params.cost;\n\n this.emit({\n type: \"llm_call_complete\",\n ...this.createBaseEventProps(node),\n response: llmNode.response,\n usage: llmNode.usage,\n finishReason: llmNode.finishReason,\n cost: llmNode.cost,\n });\n }\n\n /**\n * Mark an LLM call as failed.\n */\n failLLMCall(nodeId: NodeId, error: Error, recovered: boolean): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"llm_call\") {\n throw new Error(`LLM call node not found: ${nodeId}`);\n }\n\n const llmNode = node as LLMCallNode;\n llmNode.completedAt = Date.now();\n\n this.emit({\n type: \"llm_call_error\",\n ...this.createBaseEventProps(node),\n error,\n recovered,\n });\n }\n\n /**\n * Add a new gadget node to the tree.\n */\n addGadget(params: AddGadgetParams): GadgetNode {\n const parentId = params.parentId ?? this.getCurrentLLMCallId() ?? this.parentNodeId;\n const parent = parentId ? this.nodes.get(parentId) : null;\n\n const depth = parent ? parent.depth + 1 : this.baseDepth;\n const path = parent ? [...parent.path] : [];\n\n const id = this.generateGadgetId(params.invocationId);\n path.push(id);\n\n const node: GadgetNode = {\n id,\n type: \"gadget\",\n parentId,\n depth,\n path,\n createdAt: Date.now(),\n completedAt: null,\n invocationId: params.invocationId,\n name: params.name,\n parameters: params.parameters,\n dependencies: params.dependencies ?? [],\n state: \"pending\",\n children: [],\n isSubagent: false,\n };\n\n this.nodes.set(id, node);\n this.invocationIdToNodeId.set(params.invocationId, id);\n\n if (parent) {\n parent.children.push(id);\n }\n\n this.emit({\n type: \"gadget_call\",\n ...this.createBaseEventProps(node),\n invocationId: node.invocationId,\n name: node.name,\n parameters: node.parameters,\n dependencies: node.dependencies,\n });\n\n return node;\n }\n\n /**\n * Mark a gadget as started (running).\n */\n startGadget(nodeId: NodeId): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"gadget\") {\n throw new Error(`Gadget node not found: ${nodeId}`);\n }\n\n const gadgetNode = node as GadgetNode;\n gadgetNode.state = \"running\";\n\n this.emit({\n type: \"gadget_start\",\n ...this.createBaseEventProps(node),\n invocationId: gadgetNode.invocationId,\n name: gadgetNode.name,\n });\n }\n\n /**\n * Complete a gadget node successfully.\n */\n completeGadget(nodeId: NodeId, params: CompleteGadgetParams): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"gadget\") {\n throw new Error(`Gadget node not found: ${nodeId}`);\n }\n\n const gadgetNode = node as GadgetNode;\n gadgetNode.completedAt = Date.now();\n gadgetNode.state = params.error ? \"failed\" : \"completed\";\n if (params.result !== undefined) gadgetNode.result = params.result;\n if (params.error) gadgetNode.error = params.error;\n if (params.executionTimeMs !== undefined) gadgetNode.executionTimeMs = params.executionTimeMs;\n if (params.cost !== undefined) gadgetNode.cost = params.cost;\n if (params.media) gadgetNode.media = params.media;\n\n // Mark as subagent if it has child LLM calls\n gadgetNode.isSubagent = gadgetNode.children.some((childId) => {\n const child = this.nodes.get(childId);\n return child?.type === \"llm_call\";\n });\n\n if (params.error) {\n this.emit({\n type: \"gadget_error\",\n ...this.createBaseEventProps(node),\n invocationId: gadgetNode.invocationId,\n name: gadgetNode.name,\n error: params.error,\n executionTimeMs: params.executionTimeMs ?? 0,\n });\n } else {\n this.emit({\n type: \"gadget_complete\",\n ...this.createBaseEventProps(node),\n invocationId: gadgetNode.invocationId,\n name: gadgetNode.name,\n result: params.result ?? \"\",\n executionTimeMs: params.executionTimeMs ?? 0,\n cost: params.cost,\n media: params.media,\n });\n }\n }\n\n /**\n * Mark a gadget as skipped due to dependency failure.\n */\n skipGadget(\n nodeId: NodeId,\n failedDependency: string,\n failedDependencyError: string,\n reason: \"dependency_failed\" | \"controller_skip\",\n ): void {\n const node = this.nodes.get(nodeId);\n if (!node || node.type !== \"gadget\") {\n throw new Error(`Gadget node not found: ${nodeId}`);\n }\n\n const gadgetNode = node as GadgetNode;\n gadgetNode.completedAt = Date.now();\n gadgetNode.state = \"skipped\";\n gadgetNode.failedDependency = failedDependency;\n gadgetNode.error = failedDependencyError;\n\n // Build error message combining reason and dependency error\n const error =\n reason === \"controller_skip\"\n ? \"Skipped by controller\"\n : `Dependency ${failedDependency} failed: ${failedDependencyError}`;\n\n this.emit({\n type: \"gadget_skipped\",\n ...this.createBaseEventProps(node),\n invocationId: gadgetNode.invocationId,\n name: gadgetNode.name,\n reason,\n error,\n failedDependency,\n failedDependencyError,\n });\n }\n\n // ===========================================================================\n // Text Events (pure notifications, not tree nodes)\n // ===========================================================================\n\n /**\n * Emit a text event (notification only, not stored in tree).\n */\n emitText(content: string, llmCallNodeId: NodeId): void {\n const node = this.nodes.get(llmCallNodeId);\n if (!node) {\n throw new Error(`Node not found: ${llmCallNodeId}`);\n }\n\n this.emit({\n type: \"text\",\n ...this.createBaseEventProps(node),\n content,\n });\n }\n\n // ===========================================================================\n // Query Methods\n // ===========================================================================\n\n /**\n * Get a node by ID.\n */\n getNode(id: NodeId): ExecutionNode | undefined {\n return this.nodes.get(id);\n }\n\n /**\n * Get a gadget node by invocation ID.\n */\n getNodeByInvocationId(invocationId: string): GadgetNode | undefined {\n const nodeId = this.invocationIdToNodeId.get(invocationId);\n if (!nodeId) return undefined;\n const node = this.nodes.get(nodeId);\n return node?.type === \"gadget\" ? (node as GadgetNode) : undefined;\n }\n\n /**\n * Get all root nodes (depth 0 for this tree).\n */\n getRoots(): ExecutionNode[] {\n return this.rootIds\n .map((id) => this.nodes.get(id))\n .filter((node): node is ExecutionNode => node !== undefined);\n }\n\n /**\n * Get children of a node.\n */\n getChildren(id: NodeId): ExecutionNode[] {\n const node = this.nodes.get(id);\n if (!node) return [];\n return node.children\n .map((childId) => this.nodes.get(childId))\n .filter((child): child is ExecutionNode => child !== undefined);\n }\n\n /**\n * Get ancestors of a node (from root to parent).\n */\n getAncestors(id: NodeId): ExecutionNode[] {\n const node = this.nodes.get(id);\n if (!node) return [];\n\n const ancestors: ExecutionNode[] = [];\n let currentId = node.parentId;\n while (currentId) {\n const ancestor = this.nodes.get(currentId);\n if (ancestor) {\n ancestors.unshift(ancestor);\n currentId = ancestor.parentId;\n } else {\n break;\n }\n }\n return ancestors;\n }\n\n /**\n * Get all descendants of a node.\n */\n getDescendants(id: NodeId, type?: ExecutionNodeType): ExecutionNode[] {\n const node = this.nodes.get(id);\n if (!node) return [];\n\n const descendants: ExecutionNode[] = [];\n const stack = [...node.children];\n\n while (stack.length > 0) {\n const childId = stack.pop()!;\n const child = this.nodes.get(childId);\n if (child) {\n if (!type || child.type === type) {\n descendants.push(child);\n }\n stack.push(...child.children);\n }\n }\n\n return descendants;\n }\n\n /**\n * Get the current (most recent incomplete) LLM call node.\n */\n getCurrentLLMCallId(): NodeId | undefined {\n // Find the most recent root LLM call that's not complete\n for (let i = this.rootIds.length - 1; i >= 0; i--) {\n const node = this.nodes.get(this.rootIds[i]);\n if (node?.type === \"llm_call\" && !node.completedAt) {\n return node.id;\n }\n }\n return undefined;\n }\n\n // ===========================================================================\n // Aggregation Methods (for subagent support)\n // ===========================================================================\n\n /**\n * Get total cost for entire tree.\n */\n getTotalCost(): number {\n let total = 0;\n for (const node of this.nodes.values()) {\n if (node.type === \"llm_call\" && (node as LLMCallNode).cost) {\n total += (node as LLMCallNode).cost!;\n } else if (node.type === \"gadget\" && (node as GadgetNode).cost) {\n total += (node as GadgetNode).cost!;\n }\n }\n return total;\n }\n\n /**\n * Get total cost for a subtree (node and all descendants).\n */\n getSubtreeCost(nodeId: NodeId): number {\n const node = this.nodes.get(nodeId);\n if (!node) return 0;\n\n let total = 0;\n\n // Add node's own cost\n if (node.type === \"llm_call\" && (node as LLMCallNode).cost) {\n total += (node as LLMCallNode).cost!;\n } else if (node.type === \"gadget\" && (node as GadgetNode).cost) {\n total += (node as GadgetNode).cost!;\n }\n\n // Add descendants' costs\n for (const descendant of this.getDescendants(nodeId)) {\n if (descendant.type === \"llm_call\" && (descendant as LLMCallNode).cost) {\n total += (descendant as LLMCallNode).cost!;\n } else if (descendant.type === \"gadget\" && (descendant as GadgetNode).cost) {\n total += (descendant as GadgetNode).cost!;\n }\n }\n\n return total;\n }\n\n /**\n * Get token usage for entire tree.\n */\n getTotalTokens(): { input: number; output: number; cached: number } {\n let input = 0;\n let output = 0;\n let cached = 0;\n\n for (const node of this.nodes.values()) {\n if (node.type === \"llm_call\") {\n const llmNode = node as LLMCallNode;\n if (llmNode.usage) {\n input += llmNode.usage.inputTokens;\n output += llmNode.usage.outputTokens;\n cached += llmNode.usage.cachedInputTokens ?? 0;\n }\n }\n }\n\n return { input, output, cached };\n }\n\n /**\n * Get token usage for a subtree.\n */\n getSubtreeTokens(nodeId: NodeId): { input: number; output: number; cached: number } {\n const node = this.nodes.get(nodeId);\n if (!node) return { input: 0, output: 0, cached: 0 };\n\n let input = 0;\n let output = 0;\n let cached = 0;\n\n const nodesToProcess = [node, ...this.getDescendants(nodeId)];\n\n for (const n of nodesToProcess) {\n if (n.type === \"llm_call\") {\n const llmNode = n as LLMCallNode;\n if (llmNode.usage) {\n input += llmNode.usage.inputTokens;\n output += llmNode.usage.outputTokens;\n cached += llmNode.usage.cachedInputTokens ?? 0;\n }\n }\n }\n\n return { input, output, cached };\n }\n\n /**\n * Collect all media from a subtree.\n */\n getSubtreeMedia(nodeId: NodeId): GadgetMediaOutput[] {\n const node = this.nodes.get(nodeId);\n if (!node) return [];\n\n const media: GadgetMediaOutput[] = [];\n const nodesToProcess: ExecutionNode[] = node.type === \"gadget\" ? [node] : [];\n nodesToProcess.push(...this.getDescendants(nodeId, \"gadget\"));\n\n for (const n of nodesToProcess) {\n if (n.type === \"gadget\") {\n const gadgetNode = n as GadgetNode;\n if (gadgetNode.media) {\n media.push(...gadgetNode.media);\n }\n }\n }\n\n return media;\n }\n\n /**\n * Check if a subtree is complete (all nodes finished).\n */\n isSubtreeComplete(nodeId: NodeId): boolean {\n const node = this.nodes.get(nodeId);\n if (!node) return true;\n if (!node.completedAt) return false;\n\n for (const descendant of this.getDescendants(nodeId)) {\n if (!descendant.completedAt) return false;\n }\n\n return true;\n }\n\n /**\n * Get node counts.\n */\n getNodeCount(): { llmCalls: number; gadgets: number } {\n let llmCalls = 0;\n let gadgets = 0;\n\n for (const node of this.nodes.values()) {\n if (node.type === \"llm_call\") llmCalls++;\n else if (node.type === \"gadget\") gadgets++;\n }\n\n return { llmCalls, gadgets };\n }\n\n // ===========================================================================\n // Event Subscription\n // ===========================================================================\n\n /**\n * Subscribe to events of a specific type.\n * Returns unsubscribe function.\n *\n * @param type - Event type to subscribe to (use \"*\" for all events)\n * @param listener - Callback function that receives matching events\n * @returns Unsubscribe function\n *\n * @example\n * ```typescript\n * const unsubscribe = tree.on(\"gadget_complete\", (event) => {\n * if (event.type === \"gadget_complete\") {\n * console.log(`Gadget ${event.name} completed`);\n * }\n * });\n * ```\n */\n on(type: ExecutionEventType, listener: EventListener): () => void {\n if (!this.eventListeners.has(type)) {\n this.eventListeners.set(type, new Set());\n }\n const listeners = this.eventListeners.get(type)!;\n listeners.add(listener);\n\n return () => {\n listeners.delete(listener);\n };\n }\n\n /**\n * Subscribe to all events.\n */\n onAll(listener: EventListener): () => void {\n return this.on(\"*\", listener);\n }\n\n /**\n * Get async iterable of all events.\n * Events are yielded as they occur.\n */\n async *events(): AsyncGenerator<ExecutionEvent> {\n while (!this.isCompleted) {\n // Drain queue first\n while (this.eventQueue.length > 0) {\n yield this.eventQueue.shift()!;\n }\n\n if (this.isCompleted) break;\n\n // Wait for next event\n const event = await new Promise<ExecutionEvent>((resolve) => {\n // Check queue again in case events arrived while setting up\n if (this.eventQueue.length > 0) {\n resolve(this.eventQueue.shift()!);\n } else {\n this.eventWaiters.push(resolve);\n }\n });\n\n yield event;\n }\n\n // Drain remaining events\n while (this.eventQueue.length > 0) {\n yield this.eventQueue.shift()!;\n }\n }\n\n /**\n * Mark the tree as complete (no more events will be emitted).\n */\n complete(): void {\n this.isCompleted = true;\n // Wake up any waiters with a dummy event that signals completion\n for (const waiter of this.eventWaiters) {\n // Push a completion marker so waiters can exit\n }\n this.eventWaiters = [];\n }\n\n /**\n * Check if the tree is complete.\n */\n isComplete(): boolean {\n return this.isCompleted;\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: PromptTemplateConfig = {\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 PromptTemplateConfig {\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: \"Tip: You can call multiple gadgets in a single response for efficiency.\",\n\n iterationProgressHint: \"[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<\n PromptTemplateConfig,\n \"rules\" | \"customExamples\" | \"parallelGadgetsHint\" | \"iterationProgressHint\"\n > & {\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 \"Gadgets without dependencies execute immediately (in parallel if multiple)\",\n \"Use :invocation_id:dep1,dep2 syntax when a gadget needs results from prior gadgets\",\n \"If any dependency fails, dependent gadgets are automatically skipped\",\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: PromptTemplateConfig[\"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 { AbstractGadget } from \"../gadgets/gadget.js\";\nimport type { GadgetMediaOutput } from \"../gadgets/types.js\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"./constants.js\";\nimport type {\n AudioMimeType,\n ContentPart,\n ImageMimeType,\n TextContentPart,\n} from \"./input-content.js\";\nimport {\n audioFromBase64,\n audioFromBuffer,\n detectImageMimeType,\n imageFromBase64,\n imageFromBuffer,\n imageFromUrl,\n text,\n toBase64,\n} from \"./input-content.js\";\nimport type { PromptTemplateConfig } from \"./prompt-config.js\";\nimport { DEFAULT_PROMPTS, resolvePromptTemplate, resolveRulesTemplate } from \"./prompt-config.js\";\n\nexport type MessageRole = \"system\" | \"user\" | \"assistant\";\n\n/**\n * Message content can be a simple string (text only) or an array of content parts (multimodal).\n * Using a string is simpler for text-only messages, while arrays support images and audio.\n */\nexport type MessageContent = string | ContentPart[];\n\nexport interface LLMMessage {\n role: MessageRole;\n content: MessageContent;\n name?: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Normalize message content to an array of content parts.\n * Converts string content to a single text part.\n *\n * @param content - Message content (string or ContentPart[])\n * @returns Array of content parts\n */\nexport function normalizeMessageContent(content: MessageContent): ContentPart[] {\n if (typeof content === \"string\") {\n return [{ type: \"text\", text: content }];\n }\n return content;\n}\n\n/**\n * Extract text from message content.\n * Concatenates all text parts in the content.\n *\n * @param content - Message content (string or ContentPart[])\n * @returns Combined text from all text parts\n */\nexport function extractMessageText(content: MessageContent): string {\n if (typeof content === \"string\") {\n return content;\n }\n return content\n .filter((part): part is TextContentPart => part.type === \"text\")\n .map((part) => part.text)\n .join(\"\");\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: PromptTemplateConfig;\n\n constructor(promptConfig?: PromptTemplateConfig) {\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: AbstractGadget[],\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: AbstractGadget[]): 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({\n argPrefix: this.argPrefix,\n startPrefix: this.startPrefix,\n endPrefix: this.endPrefix,\n });\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 With ID: ${this.startPrefix}gadget_name:my_id`);\n parts.push(`\\n With dependencies: ${this.startPrefix}gadget_name:my_id:dep1,dep2`);\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 // Dependency example\n const dependencyExample = `${this.startPrefix}fetch_data:fetch_1\n${this.argPrefix}url\nhttps://api.example.com/users\n${this.endPrefix}\n${this.startPrefix}fetch_data:fetch_2\n${this.argPrefix}url\nhttps://api.example.com/orders\n${this.endPrefix}\n${this.startPrefix}merge_data:merge_1:fetch_1,fetch_2\n${this.argPrefix}format\njson\n${this.endPrefix}`;\n\n parts.push(`\\n\\nEXAMPLE (With Dependencies):\nmerge_1 waits for fetch_1 AND fetch_2 to complete.\nIf either fails, merge_1 is automatically skipped.\n\n${dependencyExample}`);\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 /**\n * Add a user message.\n * Content can be a string (text only) or an array of content parts (multimodal).\n *\n * @param content - Message content\n * @param metadata - Optional metadata\n *\n * @example\n * ```typescript\n * // Text only\n * builder.addUser(\"Hello!\");\n *\n * // Multimodal\n * builder.addUser([\n * text(\"What's in this image?\"),\n * imageFromBuffer(imageData),\n * ]);\n * ```\n */\n addUser(content: MessageContent, 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 /**\n * Add a user message with an image attachment.\n *\n * @param textContent - Text prompt\n * @param imageData - Image data (Buffer, Uint8Array, or base64 string)\n * @param mimeType - Optional MIME type (auto-detected if not provided)\n *\n * @example\n * ```typescript\n * builder.addUserWithImage(\n * \"What's in this image?\",\n * await fs.readFile(\"photo.jpg\"),\n * \"image/jpeg\" // Optional - auto-detected\n * );\n * ```\n */\n addUserWithImage(\n textContent: string,\n imageData: Buffer | Uint8Array | string,\n mimeType?: ImageMimeType,\n ): this {\n const imageBuffer =\n typeof imageData === \"string\" ? Buffer.from(imageData, \"base64\") : imageData;\n const detectedMime = mimeType ?? detectImageMimeType(imageBuffer);\n\n if (!detectedMime) {\n throw new Error(\n \"Could not detect image MIME type. Please provide the mimeType parameter explicitly.\",\n );\n }\n\n const content: ContentPart[] = [\n text(textContent),\n {\n type: \"image\",\n source: {\n type: \"base64\",\n mediaType: detectedMime,\n data: toBase64(imageBuffer),\n },\n },\n ];\n\n this.messages.push({ role: \"user\", content });\n return this;\n }\n\n /**\n * Add a user message with an image URL (OpenAI only).\n *\n * @param textContent - Text prompt\n * @param imageUrl - URL to the image\n *\n * @example\n * ```typescript\n * builder.addUserWithImageUrl(\n * \"What's in this image?\",\n * \"https://example.com/image.jpg\"\n * );\n * ```\n */\n addUserWithImageUrl(textContent: string, imageUrl: string): this {\n const content: ContentPart[] = [text(textContent), imageFromUrl(imageUrl)];\n this.messages.push({ role: \"user\", content });\n return this;\n }\n\n /**\n * Add a user message with an audio attachment (Gemini only).\n *\n * @param textContent - Text prompt\n * @param audioData - Audio data (Buffer, Uint8Array, or base64 string)\n * @param mimeType - Optional MIME type (auto-detected if not provided)\n *\n * @example\n * ```typescript\n * builder.addUserWithAudio(\n * \"Transcribe this audio\",\n * await fs.readFile(\"recording.mp3\"),\n * \"audio/mp3\" // Optional - auto-detected\n * );\n * ```\n */\n addUserWithAudio(\n textContent: string,\n audioData: Buffer | Uint8Array | string,\n mimeType?: AudioMimeType,\n ): this {\n const audioBuffer =\n typeof audioData === \"string\" ? Buffer.from(audioData, \"base64\") : audioData;\n\n const content: ContentPart[] = [text(textContent), audioFromBuffer(audioBuffer, mimeType)];\n this.messages.push({ role: \"user\", content });\n return this;\n }\n\n /**\n * Add a user message with multiple content parts.\n * Provides full flexibility for complex multimodal messages.\n *\n * @param parts - Array of content parts\n *\n * @example\n * ```typescript\n * builder.addUserMultimodal([\n * text(\"Compare these images:\"),\n * imageFromBuffer(image1),\n * imageFromBuffer(image2),\n * ]);\n * ```\n */\n addUserMultimodal(parts: ContentPart[]): this {\n this.messages.push({ role: \"user\", content: parts });\n return this;\n }\n\n /**\n * Record a gadget execution result in the message history.\n * Creates an assistant message with the gadget invocation and a user message with the result.\n *\n * The invocationId is shown to the LLM so it can reference previous calls when building dependencies.\n *\n * @param gadget - Name of the gadget that was executed\n * @param parameters - Parameters that were passed to the gadget\n * @param result - Text result from the gadget execution\n * @param invocationId - Invocation ID (shown to LLM so it can reference for dependencies)\n * @param media - Optional media outputs from the gadget\n * @param mediaIds - Optional IDs for the media outputs\n */\n addGadgetCallResult(\n gadget: string,\n parameters: Record<string, unknown>,\n result: string,\n invocationId: string,\n media?: GadgetMediaOutput[],\n mediaIds?: string[],\n ) {\n const paramStr = this.formatBlockParameters(parameters, \"\");\n\n // Assistant message with gadget markers and invocation ID\n this.messages.push({\n role: \"assistant\",\n content: `${this.startPrefix}${gadget}:${invocationId}\\n${paramStr}\\n${this.endPrefix}`,\n });\n\n // User message with result, including invocation ID so LLM can reference it\n if (media && media.length > 0 && mediaIds && mediaIds.length > 0) {\n // Build text with ID references (include kind for clarity)\n const idRefs = media.map((m, i) => `[Media: ${mediaIds[i]} (${m.kind})]`).join(\"\\n\");\n const textWithIds = `Result (${invocationId}): ${result}\\n${idRefs}`;\n\n // Build multimodal content: text + media content parts\n const parts: ContentPart[] = [text(textWithIds)];\n for (const item of media) {\n // Convert based on media kind\n if (item.kind === \"image\") {\n parts.push(imageFromBase64(item.data, item.mimeType as ImageMimeType));\n } else if (item.kind === \"audio\") {\n parts.push(audioFromBase64(item.data, item.mimeType as AudioMimeType));\n }\n // Note: video and file types are stored but not included in LLM context\n // as most providers don't support them yet\n }\n this.messages.push({ role: \"user\", content: parts });\n } else {\n // Simple text result\n this.messages.push({\n role: \"user\",\n content: `Result (${invocationId}): ${result}`,\n });\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(params: Record<string, unknown>, prefix: string): 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 const validRole =\n message.role === \"system\" || message.role === \"user\" || message.role === \"assistant\";\n const validContent = typeof message.content === \"string\" || Array.isArray(message.content);\n\n return validRole && validContent;\n};\n","/**\n * MediaStore: Session-scoped storage for gadget media outputs.\n *\n * This module provides an abstraction layer between gadgets and the filesystem.\n * Instead of exposing raw file paths, it assigns unique IDs to stored media\n * that can be shared with the LLM and user.\n *\n * @example\n * ```typescript\n * const store = new MediaStore();\n *\n * // Store an image, get back ID\n * const stored = await store.store({\n * kind: \"image\",\n * data: base64EncodedPng,\n * mimeType: \"image/png\",\n * description: \"Screenshot\"\n * }, \"Screenshot\");\n *\n * console.log(stored.id); // \"media_a1b2c3\"\n * console.log(stored.path); // \"/tmp/llmist-media-xxx/Screenshot_001.png\"\n *\n * // Later: retrieve by ID\n * const retrieved = store.get(\"media_a1b2c3\");\n * ```\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { GadgetMediaOutput, MediaKind, StoredMedia } from \"./types.js\";\n\n// Re-export StoredMedia for convenience\nexport type { StoredMedia };\n\n/**\n * Get the llmist temp directory path.\n * Uses ~/.llmist/tmp for user-scoped storage.\n */\nfunction getLlmistTmpDir(): string {\n return join(homedir(), \".llmist\", \"tmp\");\n}\n\n/**\n * Common MIME type to file extension mapping.\n */\nconst MIME_TO_EXTENSION: Record<string, string> = {\n // Images\n \"image/png\": \".png\",\n \"image/jpeg\": \".jpg\",\n \"image/gif\": \".gif\",\n \"image/webp\": \".webp\",\n \"image/svg+xml\": \".svg\",\n \"image/bmp\": \".bmp\",\n \"image/tiff\": \".tiff\",\n // Audio\n \"audio/mp3\": \".mp3\",\n \"audio/mpeg\": \".mp3\",\n \"audio/wav\": \".wav\",\n \"audio/webm\": \".webm\",\n \"audio/ogg\": \".ogg\",\n \"audio/flac\": \".flac\",\n \"audio/aac\": \".aac\",\n // Video\n \"video/mp4\": \".mp4\",\n \"video/webm\": \".webm\",\n \"video/ogg\": \".ogv\",\n \"video/quicktime\": \".mov\",\n \"video/x-msvideo\": \".avi\",\n // Documents\n \"application/pdf\": \".pdf\",\n \"application/json\": \".json\",\n \"text/plain\": \".txt\",\n \"text/html\": \".html\",\n \"text/css\": \".css\",\n \"text/javascript\": \".js\",\n};\n\n/**\n * Session-scoped media storage with ID abstraction.\n *\n * Each MediaStore instance manages media for a single agent session.\n * Media files are stored in a temporary directory and referenced by\n * short, unique IDs rather than file paths.\n */\nexport class MediaStore {\n private readonly items = new Map<string, StoredMedia>();\n private readonly outputDir: string;\n private counter = 0;\n private initialized = false;\n\n /**\n * Create a new MediaStore.\n *\n * @param sessionId - Optional session ID for the output directory.\n * If not provided, a random ID is generated.\n */\n constructor(sessionId?: string) {\n const id = sessionId ?? randomBytes(8).toString(\"hex\");\n this.outputDir = join(getLlmistTmpDir(), `media-${id}`);\n }\n\n /**\n * Get the output directory path.\n */\n getOutputDir(): string {\n return this.outputDir;\n }\n\n /**\n * Ensure the output directory exists.\n * @throws Error if directory creation fails\n */\n private async ensureDir(): Promise<void> {\n if (this.initialized) return;\n\n try {\n await mkdir(this.outputDir, { recursive: true });\n this.initialized = true;\n } catch (error) {\n throw new Error(\n `MediaStore: Failed to create directory ${this.outputDir}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Generate a unique media ID.\n * Format: \"media_\" + 6 random alphanumeric characters\n */\n private generateId(): string {\n const chars = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n let id = \"media_\";\n const bytes = randomBytes(6);\n for (let i = 0; i < 6; i++) {\n id += chars[bytes[i] % chars.length];\n }\n return id;\n }\n\n /**\n * Get file extension from MIME type.\n */\n private getExtension(mimeType: string): string {\n return MIME_TO_EXTENSION[mimeType] ?? \".bin\";\n }\n\n /**\n * Store media and return stored metadata with ID.\n *\n * @param media - The media output from a gadget\n * @param gadgetName - Name of the gadget that created this media\n * @returns Stored media information including generated ID\n * @throws Error if file write fails\n */\n async store(media: GadgetMediaOutput, gadgetName: string): Promise<StoredMedia> {\n await this.ensureDir();\n\n const id = this.generateId();\n const ext = this.getExtension(media.mimeType);\n // Use provided fileName or generate one\n const filename =\n media.fileName ?? `${gadgetName}_${String(++this.counter).padStart(3, \"0\")}${ext}`;\n const filePath = join(this.outputDir, filename);\n\n // Decode base64 and write to file\n const buffer = Buffer.from(media.data, \"base64\");\n\n try {\n await writeFile(filePath, buffer);\n } catch (error) {\n throw new Error(\n `MediaStore: Failed to write media file ${filePath}: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n const stored: StoredMedia = {\n id,\n kind: media.kind,\n path: filePath,\n mimeType: media.mimeType,\n sizeBytes: buffer.length,\n description: media.description,\n metadata: media.metadata,\n gadgetName,\n createdAt: new Date(),\n };\n\n this.items.set(id, stored);\n return stored;\n }\n\n /**\n * Get stored media by ID.\n *\n * @param id - The media ID (e.g., \"media_a1b2c3\")\n * @returns The stored media or undefined if not found\n */\n get(id: string): StoredMedia | undefined {\n return this.items.get(id);\n }\n\n /**\n * Get the actual file path for a media ID.\n * Convenience method for gadgets that need the raw path.\n *\n * @param id - The media ID\n * @returns The file path or undefined if not found\n */\n getPath(id: string): string | undefined {\n return this.items.get(id)?.path;\n }\n\n /**\n * List all stored media, optionally filtered by kind.\n *\n * @param kind - Optional media kind to filter by\n * @returns Array of stored media items\n */\n list(kind?: MediaKind): StoredMedia[] {\n const all = Array.from(this.items.values());\n if (kind) {\n return all.filter((item) => item.kind === kind);\n }\n return all;\n }\n\n /**\n * Get the count of stored media items.\n */\n get size(): number {\n return this.items.size;\n }\n\n /**\n * Check if a media ID exists.\n */\n has(id: string): boolean {\n return this.items.has(id);\n }\n\n /**\n * Clear in-memory store without deleting files.\n * Resets the counter but leaves files on disk.\n */\n clear(): void {\n this.items.clear();\n this.counter = 0;\n }\n\n /**\n * Delete all stored files and clear memory.\n * Removes the entire session directory.\n */\n async cleanup(): Promise<void> {\n if (this.initialized) {\n try {\n await rm(this.outputDir, { recursive: true, force: true });\n } catch {\n // Ignore cleanup errors (directory may already be deleted)\n }\n this.initialized = false;\n }\n this.clear();\n }\n}\n","/**\n * Signal that a gadget throws to indicate task completion and agent termination.\n *\n * When a gadget throws this signal, the agent loop will:\n * 1. Complete the current iteration\n * 2. Return the signal 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 TaskCompletionSignal(message);\n * }\n * }\n * ```\n */\nexport class TaskCompletionSignal extends Error {\n constructor(message?: string) {\n super(message ?? \"Agent loop terminated by gadget\");\n this.name = \"TaskCompletionSignal\";\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 `requestHumanInput` 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 HumanInputRequiredException(params.question);\n * }\n * }\n * ```\n */\nexport class HumanInputRequiredException extends Error {\n public readonly question: string;\n\n constructor(question: string) {\n super(`Human input required: ${question}`);\n this.name = \"HumanInputRequiredException\";\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\n/**\n * Exception thrown when gadget execution is aborted.\n *\n * Gadgets can throw this exception when they detect the abort signal has been\n * triggered. This is typically used via the `throwIfAborted()` helper method\n * on the Gadget base class.\n *\n * @example\n * ```typescript\n * class LongRunningGadget extends Gadget({\n * name: 'LongRunning',\n * description: 'Performs a long operation with checkpoints',\n * schema: z.object({ data: z.string() }),\n * }) {\n * async execute(params: this['params'], ctx: ExecutionContext): Promise<string> {\n * // Check at key points - throws AbortException if aborted\n * this.throwIfAborted(ctx);\n *\n * await this.doPartOne(params.data);\n *\n * this.throwIfAborted(ctx);\n *\n * await this.doPartTwo(params.data);\n *\n * return 'completed';\n * }\n * }\n * ```\n */\nexport class AbortException extends Error {\n constructor(message?: string) {\n super(message || \"Gadget execution was aborted\");\n this.name = \"AbortException\";\n }\n}\n\n","import { createWriteStream, mkdirSync, type WriteStream } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { type ILogObj, Logger } from \"tslog\";\n\nconst LEVEL_NAME_TO_ID: Record<string, number> = {\n silly: 0,\n trace: 1,\n debug: 2,\n info: 3,\n warn: 4,\n error: 5,\n fatal: 6,\n};\n\nfunction parseLogLevel(value?: string): number | undefined {\n if (!value) {\n return undefined;\n }\n\n const normalized = value.trim().toLowerCase();\n\n if (normalized === \"\") {\n return undefined;\n }\n\n const numericLevel = Number(normalized);\n if (Number.isFinite(numericLevel)) {\n return Math.max(0, Math.min(6, Math.floor(numericLevel)));\n }\n\n return LEVEL_NAME_TO_ID[normalized];\n}\n\n/**\n * Logger configuration options for the library.\n */\nexport interface LoggerOptions {\n /**\n * Log level: 0=silly, 1=trace, 2=debug, 3=info, 4=warn, 5=error, 6=fatal\n * @default 4 (warn)\n */\n minLevel?: number;\n\n /**\n * Output type: 'pretty' for development, 'json' for production\n * @default 'pretty'\n */\n type?: \"pretty\" | \"json\" | \"hidden\";\n\n /**\n * Logger name (appears in logs)\n */\n name?: string;\n\n /**\n * When true, reset (truncate) the log file instead of appending.\n * Useful for getting clean logs per session.\n * @default false\n */\n logReset?: boolean;\n}\n\n/**\n * Parses a boolean environment variable.\n */\nfunction parseEnvBoolean(value?: string): boolean | undefined {\n if (!value) return undefined;\n const normalized = value.trim().toLowerCase();\n if (normalized === \"true\" || normalized === \"1\") return true;\n if (normalized === \"false\" || normalized === \"0\") return false;\n return undefined;\n}\n\n// Singleton state for file logging - ensures all loggers share one WriteStream\nlet sharedLogFilePath: string | undefined;\nlet sharedLogFileStream: WriteStream | undefined;\nlet logFileInitialized = false;\nlet writeErrorCount = 0;\nlet writeErrorReported = false;\nconst MAX_WRITE_ERRORS_BEFORE_DISABLE = 5;\n\n// Standard log line template for both console and file output\nconst LOG_TEMPLATE =\n \"{{yyyy}}-{{mm}}-{{dd}} {{hh}}:{{MM}}:{{ss}}:{{ms}}\\t{{logLevelName}}\\t[{{name}}]\\t\";\n\n/**\n * Strips ANSI color codes from a string.\n */\nexport function stripAnsi(str: string): string {\n // biome-ignore lint/suspicious/noControlCharactersInRegex: ANSI escape codes use control characters\n return str.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n}\n\n/**\n * Resets the shared file logging state. Used for testing.\n * @internal\n */\nexport function _resetFileLoggingState(): void {\n if (sharedLogFileStream) {\n sharedLogFileStream.end();\n sharedLogFileStream = undefined;\n }\n sharedLogFilePath = undefined;\n logFileInitialized = false;\n writeErrorCount = 0;\n writeErrorReported = false;\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 // Initialize log file and WriteStream (only once per path)\n if (envLogFile && (!logFileInitialized || sharedLogFilePath !== envLogFile)) {\n try {\n // Close previous stream if path changed\n if (sharedLogFileStream) {\n sharedLogFileStream.end();\n sharedLogFileStream = undefined;\n }\n\n mkdirSync(dirname(envLogFile), { recursive: true });\n\n // Use \"w\" (write/truncate) when logReset is true, \"a\" (append) otherwise\n const flags = logReset ? \"w\" : \"a\";\n sharedLogFileStream = createWriteStream(envLogFile, { flags });\n sharedLogFilePath = envLogFile;\n logFileInitialized = true;\n writeErrorCount = 0;\n writeErrorReported = false;\n\n // Handle stream errors\n sharedLogFileStream.on(\"error\", (error) => {\n writeErrorCount++;\n if (!writeErrorReported) {\n console.error(`[llmist] Log file write error: ${error.message}`);\n writeErrorReported = true;\n }\n if (writeErrorCount >= MAX_WRITE_ERRORS_BEFORE_DISABLE) {\n console.error(\n `[llmist] Too many log file errors (${writeErrorCount}), disabling file logging`,\n );\n sharedLogFileStream?.end();\n sharedLogFileStream = undefined;\n }\n });\n } catch (error) {\n console.error(\"Failed to initialize LLMIST_LOG_FILE output:\", error);\n }\n }\n\n // When file logging is enabled, use \"pretty\" type with overwrite to redirect to file\n // This lets tslog handle all formatting via prettyLogTemplate\n const useFileLogging = Boolean(sharedLogFileStream);\n\n const logger = new Logger<ILogObj>({\n name,\n minLevel,\n type: useFileLogging ? \"pretty\" : defaultType,\n // Hide log position for file logging and non-pretty types\n hideLogPositionForProduction: useFileLogging || defaultType !== \"pretty\",\n prettyLogTemplate: LOG_TEMPLATE,\n // Use overwrite to redirect tslog's formatted output to file instead of console\n overwrite: useFileLogging\n ? {\n transportFormatted: (\n logMetaMarkup: string,\n logArgs: unknown[],\n _logErrors: string[],\n ) => {\n // Skip if stream was disabled due to errors\n if (!sharedLogFileStream) return;\n\n // tslog provides formatted meta (timestamp, level, name) and args separately\n // Strip ANSI colors for clean file output\n const meta = stripAnsi(logMetaMarkup);\n const args = logArgs.map((arg) =>\n typeof arg === \"string\" ? stripAnsi(arg) : JSON.stringify(arg),\n );\n const line = `${meta}${args.join(\" \")}\\n`;\n\n // Use async stream.write() - non-blocking and buffered\n sharedLogFileStream.write(line);\n },\n }\n : undefined,\n });\n\n return logger;\n}\n\n/**\n * Default logger instance for the library.\n * Users can replace this with their own configured logger.\n */\nexport const defaultLogger = createLogger();\n","/**\n * Zod schema to JSON Schema conversion with instance mismatch detection.\n *\n * When consumers use their own `import { z } from \"zod\"` instead of\n * `import { z } from \"llmist\"`, the `.describe()` metadata can be lost\n * because Zod stores metadata on schema instances and `toJSONSchema()`\n * only reads from schemas created by the same Zod module instance.\n *\n * This module provides a `schemaToJSONSchema()` function that:\n * 1. Converts Zod schema to JSON Schema using the standard API\n * 2. Detects if descriptions were lost due to instance mismatch\n * 3. Logs a warning recommending `import { z } from \"llmist\"`\n * 4. Falls back to extracting descriptions from `schema._def`\n *\n * @module gadgets/schema-to-json\n */\n\nimport type { ZodTypeAny } from \"zod\";\nimport * as z from \"zod\";\nimport { defaultLogger } from \"../logging/logger.js\";\n\n/**\n * Convert a Zod schema to JSON Schema with description fallback.\n *\n * If descriptions exist in schema._def but are missing from the generated\n * JSON Schema (indicating a Zod instance mismatch), this function:\n * 1. Logs a warning recommending `import { z } from \"llmist\"`\n * 2. Extracts descriptions from _def and merges them into the JSON Schema\n *\n * @param schema - Zod schema to convert\n * @param options - Conversion options (target JSON Schema version)\n * @returns JSON Schema object with descriptions preserved\n *\n * @example\n * ```typescript\n * import { schemaToJSONSchema } from './schema-to-json.js';\n * import { z } from 'zod';\n *\n * const schema = z.object({\n * name: z.string().describe('User name'),\n * });\n *\n * const jsonSchema = schemaToJSONSchema(schema);\n * // { type: 'object', properties: { name: { type: 'string', description: 'User name' } } }\n * ```\n */\nexport function schemaToJSONSchema(\n schema: ZodTypeAny,\n options?: { target?: \"draft-7\" | \"draft-2020-12\" },\n): Record<string, unknown> {\n const jsonSchema = z.toJSONSchema(schema, options ?? { target: \"draft-7\" });\n\n // Check for instance mismatch by comparing _def descriptions with JSON schema\n const mismatches = detectDescriptionMismatch(schema, jsonSchema);\n\n if (mismatches.length > 0) {\n defaultLogger.warn(\n `Zod instance mismatch detected: ${mismatches.length} description(s) lost. ` +\n `For best results, use: import { z } from \"llmist\"`,\n );\n\n // Merge descriptions from _def into JSON schema\n return mergeDescriptions(schema, jsonSchema);\n }\n\n return jsonSchema;\n}\n\n/**\n * Detect if schema._def contains descriptions that are missing from JSON schema.\n * Returns array of paths where descriptions were lost.\n */\nfunction detectDescriptionMismatch(\n schema: ZodTypeAny,\n jsonSchema: Record<string, unknown>,\n): string[] {\n const mismatches: string[] = [];\n\n function checkSchema(zodSchema: ZodTypeAny, json: unknown, path: string): void {\n if (!zodSchema || typeof zodSchema !== \"object\") return;\n\n const def = zodSchema._def as unknown as Record<string, unknown> | undefined;\n const jsonObj = json as Record<string, unknown> | undefined;\n\n // Check if _def has description but JSON schema doesn't\n if (def?.description && !jsonObj?.description) {\n mismatches.push(path || \"root\");\n }\n\n // Recursively check object properties\n if (def?.typeName === \"ZodObject\" && def?.shape) {\n const shape =\n typeof def.shape === \"function\"\n ? (def.shape as () => Record<string, ZodTypeAny>)()\n : def.shape;\n for (const [key, fieldSchema] of Object.entries(shape as Record<string, ZodTypeAny>)) {\n const properties = jsonObj?.properties as Record<string, unknown> | undefined;\n const jsonProp = properties?.[key];\n checkSchema(fieldSchema, jsonProp, path ? `${path}.${key}` : key);\n }\n }\n\n // Check array items\n if (def?.typeName === \"ZodArray\" && def?.type) {\n checkSchema(def.type as ZodTypeAny, jsonObj?.items, path ? `${path}[]` : \"[]\");\n }\n\n // Check optional/nullable wrapped types\n if ((def?.typeName === \"ZodOptional\" || def?.typeName === \"ZodNullable\") && def?.innerType) {\n checkSchema(def.innerType as ZodTypeAny, json, path);\n }\n\n // Check default wrapped types\n if (def?.typeName === \"ZodDefault\" && def?.innerType) {\n checkSchema(def.innerType as ZodTypeAny, json, path);\n }\n }\n\n checkSchema(schema, jsonSchema, \"\");\n return mismatches;\n}\n\n/**\n * Merge descriptions from schema._def into JSON schema.\n * Returns a new JSON schema object with descriptions filled in from _def.\n */\nfunction mergeDescriptions(\n schema: ZodTypeAny,\n jsonSchema: Record<string, unknown>,\n): Record<string, unknown> {\n function merge(zodSchema: ZodTypeAny, json: unknown): unknown {\n if (!json || typeof json !== \"object\") return json;\n\n const def = zodSchema._def as unknown as Record<string, unknown> | undefined;\n const jsonObj = json as Record<string, unknown>;\n const merged: Record<string, unknown> = { ...jsonObj };\n\n // Copy description from _def if missing in JSON\n if (def?.description && !jsonObj.description) {\n merged.description = def.description;\n }\n\n // Recursively merge object properties\n if (def?.typeName === \"ZodObject\" && def?.shape && jsonObj.properties) {\n const shape =\n typeof def.shape === \"function\"\n ? (def.shape as () => Record<string, ZodTypeAny>)()\n : def.shape;\n const properties = jsonObj.properties as Record<string, unknown>;\n merged.properties = { ...properties };\n for (const [key, fieldSchema] of Object.entries(shape as Record<string, ZodTypeAny>)) {\n if (properties[key]) {\n (merged.properties as Record<string, unknown>)[key] = merge(fieldSchema, properties[key]);\n }\n }\n }\n\n // Merge array items\n if (def?.typeName === \"ZodArray\" && def?.type && jsonObj.items) {\n merged.items = merge(def.type as ZodTypeAny, jsonObj.items);\n }\n\n // Handle optional/nullable wrapped types\n if ((def?.typeName === \"ZodOptional\" || def?.typeName === \"ZodNullable\") && def?.innerType) {\n return merge(def.innerType as ZodTypeAny, json);\n }\n\n // Handle default wrapped types\n if (def?.typeName === \"ZodDefault\" && def?.innerType) {\n return merge(def.innerType as ZodTypeAny, json);\n }\n\n return merged;\n }\n\n return merge(schema, jsonSchema) as Record<string, unknown>;\n}\n","import type { ZodTypeAny } from \"zod\";\n\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport { AbortException } from \"./exceptions.js\";\nimport { schemaToJSONSchema } from \"./schema-to-json.js\";\nimport { validateGadgetSchema } from \"./schema-validator.js\";\nimport type { ExecutionContext, GadgetExample, GadgetExecuteReturn } from \"./types.js\";\n\n/**\n * Format parameters object as Block format for use in examples.\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 formatParamsForBlockExample(\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(formatParamsForBlockExample(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(formatParamsForBlockExample(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(\n schema: Record<string, unknown>,\n indent = \"\",\n atRoot = true,\n): 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 * Abstract base class for gadgets. Most users should use the `Gadget()` factory\n * or `createGadget()` function instead, as they provide better type safety\n * and simpler APIs.\n *\n * Extend this class directly only when you need advanced control over gadget behavior.\n */\nexport abstract class AbstractGadget {\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 * @param ctx - Optional execution context for cost reporting and LLM access\n * @returns Result as a string, or an object with result and optional cost\n *\n * @example\n * ```typescript\n * // Simple string return (free gadget)\n * execute(params) {\n * return \"result\";\n * }\n *\n * // Object return with cost tracking\n * execute(params) {\n * return { result: \"data\", cost: 0.001 };\n * }\n *\n * // Using context for callback-based cost reporting\n * execute(params, ctx) {\n * ctx.reportCost(0.001);\n * return \"result\";\n * }\n *\n * // Using wrapped LLMist for automatic cost tracking\n * async execute(params, ctx) {\n * const summary = await ctx.llmist.complete('Summarize: ' + params.text);\n * return summary;\n * }\n * ```\n */\n abstract execute(\n params: Record<string, unknown>,\n ctx?: ExecutionContext,\n ): GadgetExecuteReturn | Promise<GadgetExecuteReturn>;\n\n /**\n * Throws an AbortException if the execution has been aborted.\n *\n * Call this at key checkpoints in long-running gadgets to allow early exit\n * when the gadget has been cancelled (e.g., due to timeout). This enables\n * resource cleanup and prevents unnecessary work after cancellation.\n *\n * @param ctx - The execution context containing the abort signal\n * @throws AbortException if ctx.signal.aborted is true\n *\n * @example\n * ```typescript\n * class DataProcessor extends Gadget({\n * description: 'Processes data in multiple steps',\n * schema: z.object({ items: z.array(z.string()) }),\n * }) {\n * async execute(params: this['params'], ctx?: ExecutionContext): Promise<string> {\n * const results: string[] = [];\n *\n * for (const item of params.items) {\n * // Check before each expensive operation\n * this.throwIfAborted(ctx);\n *\n * results.push(await this.processItem(item));\n * }\n *\n * return results.join(', ');\n * }\n * }\n * ```\n */\n throwIfAborted(ctx?: ExecutionContext): void {\n if (ctx?.signal?.aborted) {\n throw new AbortException();\n }\n }\n\n /**\n * Register a cleanup function to run when execution is aborted (timeout or cancellation).\n * The cleanup function is called immediately if the signal is already aborted.\n * Errors thrown by the cleanup function are silently ignored.\n *\n * Use this to clean up resources like browser instances, database connections,\n * or child processes when the gadget is cancelled due to timeout.\n *\n * @param ctx - The execution context containing the abort signal\n * @param cleanup - Function to run on abort (can be sync or async)\n *\n * @example\n * ```typescript\n * class BrowserGadget extends Gadget({\n * description: 'Fetches web page content',\n * schema: z.object({ url: z.string() }),\n * }) {\n * async execute(params: this['params'], ctx?: ExecutionContext): Promise<string> {\n * const browser = await chromium.launch();\n * this.onAbort(ctx, () => browser.close());\n *\n * const page = await browser.newPage();\n * this.onAbort(ctx, () => page.close());\n *\n * await page.goto(params.url);\n * const content = await page.content();\n *\n * await browser.close();\n * return content;\n * }\n * }\n * ```\n */\n onAbort(ctx: ExecutionContext | undefined, cleanup: () => void | Promise<void>): void {\n if (!ctx?.signal) return;\n\n const safeCleanup = () => {\n try {\n const result = cleanup();\n if (result && typeof result === \"object\" && \"catch\" in result) {\n (result as Promise<void>).catch(() => {});\n }\n } catch {\n // Swallow synchronous errors\n }\n };\n\n if (ctx.signal.aborted) {\n // Already aborted, run cleanup immediately\n safeCleanup();\n return;\n }\n\n ctx.signal.addEventListener(\"abort\", safeCleanup, { once: true });\n }\n\n /**\n * Create an AbortController linked to the execution context's signal.\n * When the parent signal aborts, the returned controller also aborts with the same reason.\n *\n * Useful for passing abort signals to child operations like fetch() while still\n * being able to abort them independently if needed.\n *\n * @param ctx - The execution context containing the parent abort signal\n * @returns A new AbortController linked to the parent signal\n *\n * @example\n * ```typescript\n * class FetchGadget extends Gadget({\n * description: 'Fetches data from URL',\n * schema: z.object({ url: z.string() }),\n * }) {\n * async execute(params: this['params'], ctx?: ExecutionContext): Promise<string> {\n * const controller = this.createLinkedAbortController(ctx);\n *\n * // fetch() will automatically abort when parent times out\n * const response = await fetch(params.url, { signal: controller.signal });\n * return response.text();\n * }\n * }\n * ```\n */\n createLinkedAbortController(ctx?: ExecutionContext): AbortController {\n const controller = new AbortController();\n\n if (ctx?.signal) {\n if (ctx.signal.aborted) {\n controller.abort(ctx.signal.reason);\n } else {\n ctx.signal.addEventListener(\n \"abort\",\n () => {\n controller.abort(ctx.signal.reason);\n },\n { once: true },\n );\n }\n }\n\n return controller;\n }\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(\n optionsOrArgPrefix?: string | { argPrefix?: string; startPrefix?: string; endPrefix?: string },\n ): string {\n // Handle backwards compatibility: if string is passed, treat it as argPrefix\n const options =\n 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(\n formatParamsForBlockExample(example.params as Record<string, unknown>, \"\", effectiveArgPrefix),\n );\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","/**\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 { AbstractGadget } from \"./gadget.js\";\nimport type { ExecutionContext, GadgetExample, GadgetExecuteReturn } 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 /**\n * Execution function with typed parameters.\n * Can return string or { result, cost? }.\n * Optionally receives ExecutionContext for callback-based cost reporting.\n */\n execute: (\n params: InferSchema<TSchema>,\n ctx?: ExecutionContext,\n ) => GadgetExecuteReturn | Promise<GadgetExecuteReturn>;\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): AbstractGadget {\n class DynamicGadget extends AbstractGadget {\n name = config.name;\n description = config.description;\n parameterSchema = config.schema;\n timeoutMs = config.timeoutMs;\n examples = config.examples;\n\n execute(\n params: Record<string, unknown>,\n ctx?: ExecutionContext,\n ): GadgetExecuteReturn | Promise<GadgetExecuteReturn> {\n // Cast to inferred type and call user's function with context\n return config.execute(params as InferSchema<TSchema>, ctx);\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/** Default max output in characters (~19k tokens at 4 chars/token) */\nconst DEFAULT_MAX_OUTPUT_CHARS = 76_800;\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 * @param maxOutputChars - Maximum characters to return (default: 76,800 = ~19k tokens)\n * @returns A GadgetOutputViewer gadget instance\n *\n * @example\n * ```typescript\n * const store = new GadgetOutputStore();\n * const viewer = createGadgetOutputViewer(store, 76_800);\n * registry.register(\"GadgetOutputViewer\", viewer);\n * ```\n */\nexport function createGadgetOutputViewer(\n store: GadgetOutputStore,\n maxOutputChars: number = DEFAULT_MAX_OUTPUT_CHARS,\n) {\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 // Step 3: Build output string\n let output = lines.join(\"\\n\");\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 // Step 4: Apply output size limit to prevent context explosion\n let truncatedBySize = false;\n let linesIncluded = returnedLines;\n if (output.length > maxOutputChars) {\n truncatedBySize = true;\n let truncatedOutput = \"\";\n linesIncluded = 0;\n\n for (const line of lines) {\n if (truncatedOutput.length + line.length + 1 > maxOutputChars) break;\n truncatedOutput += line + \"\\n\";\n linesIncluded++;\n }\n\n output = truncatedOutput;\n }\n\n // Build header with appropriate messaging\n let header: string;\n if (truncatedBySize) {\n const remainingLines = returnedLines - linesIncluded;\n header =\n `[Showing ${linesIncluded} of ${totalLines} lines (truncated due to size limit)]\\n` +\n `[... ${remainingLines.toLocaleString()} more lines. Use limit parameter to paginate, e.g., limit: \"${linesIncluded + 1}-${linesIncluded + 200}\"]\\n`;\n } else if (returnedLines < totalLines) {\n header = `[Showing ${returnedLines} of ${totalLines} lines]\\n`;\n } else {\n header = `[Showing all ${totalLines} lines]\\n`;\n }\n\n return header + output;\n },\n });\n}\n\n// Export helpers for testing\nexport { applyPattern, applyPatterns, applyLineLimit };\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 * Retry configuration for LLM API calls.\n *\n * Provides exponential backoff with jitter to handle transient failures\n * like rate limits (429), server errors (5xx), and connection issues.\n */\n\n/**\n * Configuration options for retry behavior.\n *\n * @example\n * ```typescript\n * // Custom retry with monitoring\n * const agent = LLMist.createAgent()\n * .withRetry({\n * retries: 5,\n * minTimeout: 2000,\n * onRetry: (error, attempt) => console.log(`Retry ${attempt}`),\n * })\n * .ask(\"Hello\");\n * ```\n */\nexport interface RetryConfig {\n /**\n * Whether retry is enabled.\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Maximum number of retry attempts.\n * @default 3\n */\n retries?: number;\n\n /**\n * Minimum delay before the first retry in milliseconds.\n * @default 1000\n */\n minTimeout?: number;\n\n /**\n * Maximum delay between retries in milliseconds.\n * @default 30000\n */\n maxTimeout?: number;\n\n /**\n * Exponential factor for backoff calculation.\n * @default 2\n */\n factor?: number;\n\n /**\n * Whether to add random jitter to prevent thundering herd.\n * @default true\n */\n randomize?: boolean;\n\n /**\n * Called before each retry attempt.\n * Use for logging or metrics.\n */\n onRetry?: (error: Error, attempt: number) => void;\n\n /**\n * Called when all retries are exhausted and the operation fails.\n * The error will still be thrown after this callback.\n */\n onRetriesExhausted?: (error: Error, attempts: number) => void;\n\n /**\n * Custom function to determine if an error should trigger a retry.\n * If not provided, uses the default `isRetryableError` classification.\n *\n * @returns true to retry, false to fail immediately\n */\n shouldRetry?: (error: Error) => boolean;\n}\n\n/**\n * Resolved retry configuration with all defaults applied.\n */\nexport interface ResolvedRetryConfig {\n enabled: boolean;\n retries: number;\n minTimeout: number;\n maxTimeout: number;\n factor: number;\n randomize: boolean;\n onRetry?: (error: Error, attempt: number) => void;\n onRetriesExhausted?: (error: Error, attempts: number) => void;\n shouldRetry?: (error: Error) => boolean;\n}\n\n/**\n * Default retry configuration values.\n * Conservative defaults: 3 retries with up to 30s delay.\n */\nexport const DEFAULT_RETRY_CONFIG: Omit<\n ResolvedRetryConfig,\n \"onRetry\" | \"onRetriesExhausted\" | \"shouldRetry\"\n> = {\n enabled: true,\n retries: 3,\n minTimeout: 1000,\n maxTimeout: 30000,\n factor: 2,\n randomize: true,\n};\n\n/**\n * Resolves a partial retry configuration by applying defaults.\n *\n * @param config - Partial configuration (optional)\n * @returns Fully resolved configuration with defaults applied\n */\nexport function resolveRetryConfig(config?: RetryConfig): ResolvedRetryConfig {\n if (!config) {\n return { ...DEFAULT_RETRY_CONFIG };\n }\n\n return {\n enabled: config.enabled ?? DEFAULT_RETRY_CONFIG.enabled,\n retries: config.retries ?? DEFAULT_RETRY_CONFIG.retries,\n minTimeout: config.minTimeout ?? DEFAULT_RETRY_CONFIG.minTimeout,\n maxTimeout: config.maxTimeout ?? DEFAULT_RETRY_CONFIG.maxTimeout,\n factor: config.factor ?? DEFAULT_RETRY_CONFIG.factor,\n randomize: config.randomize ?? DEFAULT_RETRY_CONFIG.randomize,\n onRetry: config.onRetry,\n onRetriesExhausted: config.onRetriesExhausted,\n shouldRetry: config.shouldRetry,\n };\n}\n\n/**\n * Determines if an error is retryable based on common LLM API error patterns.\n *\n * Retryable errors include:\n * - Rate limits (429)\n * - Server errors (500, 502, 503, 504)\n * - Timeouts and connection errors\n * - Provider-specific transient errors\n *\n * Non-retryable errors include:\n * - Authentication errors (401, 403)\n * - Bad request errors (400)\n * - Not found errors (404)\n * - Content policy violations\n *\n * @param error - The error to classify\n * @returns true if the error is retryable\n */\nexport function isRetryableError(error: Error): boolean {\n const message = error.message.toLowerCase();\n const name = error.name;\n\n // Rate limits (429) - always retry\n if (message.includes(\"429\") || message.includes(\"rate limit\") || message.includes(\"rate_limit\")) {\n return true;\n }\n\n // Server errors (5xx) - retry\n if (\n message.includes(\"500\") ||\n message.includes(\"502\") ||\n message.includes(\"503\") ||\n message.includes(\"504\") ||\n message.includes(\"internal server error\") ||\n message.includes(\"bad gateway\") ||\n message.includes(\"service unavailable\") ||\n message.includes(\"gateway timeout\")\n ) {\n return true;\n }\n\n // Timeouts - retry\n if (\n message.includes(\"timeout\") ||\n message.includes(\"etimedout\") ||\n message.includes(\"timed out\")\n ) {\n return true;\n }\n\n // Connection errors - retry\n if (\n message.includes(\"econnreset\") ||\n message.includes(\"econnrefused\") ||\n message.includes(\"enotfound\") ||\n message.includes(\"connection\") ||\n message.includes(\"network\")\n ) {\n return true;\n }\n\n // Provider-specific error names (from Anthropic, OpenAI SDKs)\n if (\n name === \"APIConnectionError\" ||\n name === \"RateLimitError\" ||\n name === \"InternalServerError\" ||\n name === \"ServiceUnavailableError\" ||\n name === \"APITimeoutError\"\n ) {\n return true;\n }\n\n // Overloaded errors (common with Claude)\n if (message.includes(\"overloaded\") || message.includes(\"capacity\")) {\n return true;\n }\n\n // Don't retry authentication, bad requests, or content policy errors\n if (\n message.includes(\"401\") ||\n message.includes(\"403\") ||\n message.includes(\"400\") ||\n message.includes(\"404\") ||\n message.includes(\"authentication\") ||\n message.includes(\"unauthorized\") ||\n message.includes(\"forbidden\") ||\n message.includes(\"invalid\") ||\n message.includes(\"content policy\") ||\n name === \"AuthenticationError\" ||\n name === \"BadRequestError\" ||\n name === \"NotFoundError\" ||\n name === \"PermissionDeniedError\"\n ) {\n return false;\n }\n\n // Default: don't retry unknown errors\n return false;\n}\n\n/**\n * Formats an LLM API error into a clean, user-friendly message.\n *\n * Extracts the most relevant information from provider error objects,\n * hiding verbose JSON/stack traces while preserving actionable details.\n *\n * @param error - The error to format\n * @returns A clean, single-line error message\n *\n * @example\n * ```typescript\n * // Gemini RESOURCE_EXHAUSTED error\n * formatLLMError(error);\n * // Returns: \"Rate limit exceeded (429) - retry after a few seconds\"\n *\n * // Anthropic overloaded error\n * formatLLMError(error);\n * // Returns: \"API overloaded - retry later\"\n * ```\n */\nexport function formatLLMError(error: Error): string {\n const message = error.message;\n const name = error.name;\n\n // Gemini RESOURCE_EXHAUSTED\n if (message.includes(\"RESOURCE_EXHAUSTED\") || message.includes(\"429\")) {\n return \"Rate limit exceeded (429) - retry after a few seconds\";\n }\n\n // Rate limits\n if (message.toLowerCase().includes(\"rate limit\") || message.toLowerCase().includes(\"rate_limit\")) {\n return \"Rate limit exceeded - retry after a few seconds\";\n }\n\n // Overloaded/capacity errors\n if (message.toLowerCase().includes(\"overloaded\") || message.toLowerCase().includes(\"capacity\")) {\n return \"API overloaded - retry later\";\n }\n\n // Server errors\n if (message.includes(\"500\") || message.toLowerCase().includes(\"internal server error\")) {\n return \"Internal server error (500) - the API is experiencing issues\";\n }\n if (message.includes(\"502\") || message.toLowerCase().includes(\"bad gateway\")) {\n return \"Bad gateway (502) - the API is temporarily unavailable\";\n }\n if (message.includes(\"503\") || message.toLowerCase().includes(\"service unavailable\")) {\n return \"Service unavailable (503) - the API is temporarily down\";\n }\n if (message.includes(\"504\") || message.toLowerCase().includes(\"gateway timeout\")) {\n return \"Gateway timeout (504) - the request took too long\";\n }\n\n // Timeout errors\n if (message.toLowerCase().includes(\"timeout\") || message.toLowerCase().includes(\"timed out\")) {\n return \"Request timed out - the API took too long to respond\";\n }\n\n // Connection errors\n if (message.toLowerCase().includes(\"econnrefused\")) {\n return \"Connection refused - unable to reach the API\";\n }\n if (message.toLowerCase().includes(\"econnreset\")) {\n return \"Connection reset - the API closed the connection\";\n }\n if (message.toLowerCase().includes(\"enotfound\")) {\n return \"DNS error - unable to resolve API hostname\";\n }\n\n // Auth errors\n if (message.includes(\"401\") || message.toLowerCase().includes(\"unauthorized\") || name === \"AuthenticationError\") {\n return \"Authentication failed - check your API key\";\n }\n if (message.includes(\"403\") || message.toLowerCase().includes(\"forbidden\") || name === \"PermissionDeniedError\") {\n return \"Permission denied - your API key lacks required permissions\";\n }\n\n // Bad request\n if (message.includes(\"400\") || name === \"BadRequestError\") {\n // Try to extract a useful message from the error\n const match = message.match(/message['\":\\s]+['\"]?([^'\"}\\]]+)/i);\n if (match) {\n return `Bad request: ${match[1].trim()}`;\n }\n return \"Bad request - check your input parameters\";\n }\n\n // Content policy\n if (message.toLowerCase().includes(\"content policy\") || message.toLowerCase().includes(\"safety\")) {\n return \"Content policy violation - the request was blocked\";\n }\n\n // Try to extract a clean message from JSON errors\n // First try proper JSON parsing (handles nested structures and escaped quotes)\n try {\n const parsed = JSON.parse(message);\n // Support common API error structures: {error: {message: \"...\"}} or {message: \"...\"}\n const extractedMessage = parsed?.error?.message || parsed?.message;\n if (typeof extractedMessage === \"string\" && extractedMessage.length > 0) {\n return extractedMessage.trim();\n }\n } catch {\n // Not valid JSON, fall through to regex\n }\n\n // Fall back to regex extraction for malformed JSON or partial strings\n const jsonMatch = message.match(/[\"']?message[\"']?\\s*[:=]\\s*[\"']([^\"']+)[\"']/i);\n if (jsonMatch) {\n return jsonMatch[1].trim();\n }\n\n // If the message is very long (likely JSON dump), truncate it\n if (message.length > 200) {\n // Try to find the first sentence or meaningful part\n const firstPart = message.split(/[.!?\\n]/)[0];\n if (firstPart && firstPart.length > 10 && firstPart.length < 150) {\n return firstPart.trim();\n }\n return message.slice(0, 150).trim() + \"...\";\n }\n\n // Return the original message if we couldn't simplify it\n return message;\n}\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(config: CompactionConfig = {}): 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 =\n \"[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 { HybridStrategy } from \"./hybrid.js\";\nexport { SlidingWindowStrategy } from \"./sliding-window.js\";\nexport { SummarizationStrategy } from \"./summarization.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 { LLMMessage } from \"../../core/messages.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 {\n HybridStrategy,\n SlidingWindowStrategy,\n SummarizationStrategy,\n} from \"./strategies/index.js\";\nimport type { CompactionStrategy } from \"./strategy.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 * ConversationManager handles conversation state and message building.\n * Extracted from AgentLoop to follow Single Responsibility Principle.\n */\n\nimport type { MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, type LLMMessage, LLMMessageBuilder } from \"../core/messages.js\";\nimport type { GadgetMediaOutput } from \"../gadgets/types.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: MessageContent): void {\n this.historyBuilder.addUser(content);\n }\n\n addAssistantMessage(content: string): void {\n this.historyBuilder.addAssistant(content);\n }\n\n addGadgetCallResult(\n gadgetName: string,\n parameters: Record<string, unknown>,\n result: string,\n invocationId: string,\n media?: GadgetMediaOutput[],\n mediaIds?: string[],\n ): void {\n this.historyBuilder.addGadgetCallResult(gadgetName, parameters, result, invocationId, media, mediaIds);\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 // Assistant messages are always text, extract if multimodal\n this.historyBuilder.addAssistant(extractMessageText(msg.content));\n }\n // System messages are not added to history (they're in baseMessages)\n }\n }\n\n getConversationHistory(): LLMMessage[] {\n // Returns full conversation history: initial messages (from previous sessions via withHistory())\n // plus runtime history (from current session). Excludes base messages (system prompt, gadget instructions).\n return [...this.initialMessages, ...this.historyBuilder.build()];\n }\n}\n","/**\n * Event handler sugar for cleaner event processing.\n *\n * Instead of verbose if/else chains, use named handlers\n * for each event type.\n *\n * @example\n * ```typescript\n * await agent.runWith({\n * onText: (content) => console.log(\"LLM:\", content),\n * onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\n\nimport type { StreamEvent } from \"../gadgets/types.js\";\n\n/**\n * Named event handlers for different event types.\n */\nexport interface EventHandlers {\n /** Called when text is generated by the LLM */\n onText?: (content: string) => void | Promise<void>;\n\n /** Called when a gadget is about to be executed */\n onGadgetCall?: (call: {\n gadgetName: string;\n invocationId: string;\n parameters?: Record<string, unknown>;\n parametersRaw: string;\n dependencies: string[];\n }) => void | Promise<void>;\n\n /** Called when a gadget execution completes */\n onGadgetResult?: (result: {\n gadgetName: string;\n invocationId: 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 invocationId: event.call.invocationId,\n parameters: event.call.parameters,\n parametersRaw: event.call.parametersRaw,\n dependencies: event.call.dependencies,\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 * 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 * Runtime validators for hook action types.\n *\n * These validators ensure that controllers return valid action objects,\n * catching common mistakes like missing required fields.\n */\n\nimport type {\n AfterGadgetExecutionAction,\n AfterLLMCallAction,\n AfterLLMErrorAction,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n} from \"./hooks.js\";\n\nexport class HookValidationError extends Error {\n constructor(hookName: string, message: string) {\n super(`Invalid action from ${hookName}: ${message}`);\n this.name = \"HookValidationError\";\n }\n}\n\n/**\n * Validate beforeLLMCall action.\n */\nexport function validateBeforeLLMCallAction(action: BeforeLLMCallAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"beforeLLMCall\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"proceed\" && actionType !== \"skip\") {\n throw new HookValidationError(\n \"beforeLLMCall\",\n `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n );\n }\n\n if (actionType === \"skip\" && !action.syntheticResponse) {\n throw new HookValidationError(\n \"beforeLLMCall\",\n \"When action is 'skip', syntheticResponse is required\",\n );\n }\n}\n\n/**\n * Validate afterLLMCall action.\n */\nexport function validateAfterLLMCallAction(action: AfterLLMCallAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n const validActions = [\"continue\", \"append_messages\", \"modify_and_continue\", \"append_and_modify\"];\n if (!validActions.includes(actionType)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Invalid action type: ${actionType}. Must be one of: ${validActions.join(\", \")}`,\n );\n }\n\n if (actionType === \"append_messages\" || actionType === \"append_and_modify\") {\n if (!(\"messages\" in action) || !action.messages || !Array.isArray(action.messages)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', messages array is required`,\n );\n }\n\n if (action.messages.length === 0) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', messages array must not be empty`,\n );\n }\n\n // Validate each message\n for (let i = 0; i < action.messages.length; i++) {\n const msg = action.messages[i];\n if (!msg || typeof msg !== \"object\") {\n throw new HookValidationError(\"afterLLMCall\", `Message at index ${i} must be an object`);\n }\n if (!msg.role || !msg.content) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Message at index ${i} must have 'role' and 'content' fields`,\n );\n }\n if (![\"system\", \"user\", \"assistant\"].includes(msg.role)) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `Message at index ${i} has invalid role: ${msg.role}`,\n );\n }\n }\n }\n\n if (actionType === \"modify_and_continue\" || actionType === \"append_and_modify\") {\n if (!(\"modifiedMessage\" in action) || !action.modifiedMessage) {\n throw new HookValidationError(\n \"afterLLMCall\",\n `When action is '${actionType}', modifiedMessage is required`,\n );\n }\n }\n}\n\n/**\n * Validate afterLLMError action.\n */\nexport function validateAfterLLMErrorAction(action: AfterLLMErrorAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterLLMError\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"rethrow\" && actionType !== \"recover\") {\n throw new HookValidationError(\n \"afterLLMError\",\n `Invalid action type: ${actionType}. Must be 'rethrow' or 'recover'`,\n );\n }\n\n if (actionType === \"recover\" && !action.fallbackResponse) {\n throw new HookValidationError(\n \"afterLLMError\",\n \"When action is 'recover', fallbackResponse is required\",\n );\n }\n}\n\n/**\n * Validate beforeGadgetExecution action.\n */\nexport function validateBeforeGadgetExecutionAction(action: BeforeGadgetExecutionAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"proceed\" && actionType !== \"skip\") {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n );\n }\n\n if (actionType === \"skip\" && !action.syntheticResult) {\n throw new HookValidationError(\n \"beforeGadgetExecution\",\n \"When action is 'skip', syntheticResult is required\",\n );\n }\n}\n\n/**\n * Validate afterGadgetExecution action.\n */\nexport function validateAfterGadgetExecutionAction(action: AfterGadgetExecutionAction): void {\n if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n \"Must return an action object with an 'action' field\",\n );\n }\n\n const actionType = action.action;\n if (actionType !== \"continue\" && actionType !== \"recover\") {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n `Invalid action type: ${actionType}. Must be 'continue' or 'recover'`,\n );\n }\n\n if (actionType === \"recover\" && !action.fallbackResult) {\n throw new HookValidationError(\n \"afterGadgetExecution\",\n \"When action is 'recover', fallbackResult is required\",\n );\n }\n}\n","/**\n * 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: 0.8,\n output: 4.0,\n cachedInput: 0.08,\n cacheWriteInput: 1.0,\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 // Dated Opus 4.5\n {\n provider: \"anthropic\",\n modelId: \"claude-opus-4-5-20251124\",\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: \"Most powerful model for coding and computer use. Extended thinking support.\",\n },\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: 0.8,\n output: 4.0,\n cachedInput: 0.08,\n cacheWriteInput: 1.0,\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.buildApiRequest(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: Normalize provider-specific stream into universal format\n yield* this.normalizeProviderStream(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 API request.\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 request object ready for the API call\n */\n protected abstract buildApiRequest(\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 * Normalize 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 normalizeProviderStream(rawStream: AsyncIterable<unknown>): LLMStream;\n}\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 ContentBlockParam,\n ImageBlockParam,\n MessageCreateParamsStreaming,\n MessageStreamEvent,\n TextBlockParam,\n} from \"@anthropic-ai/sdk/resources/messages\";\nimport type { ContentPart, ImageContentPart, ImageMimeType } from \"../core/input-content.js\";\nimport type { LLMMessage, MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, normalizeMessageContent } 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 // =========================================================================\n // Image Generation (Not Supported)\n // =========================================================================\n\n supportsImageGeneration(_modelId: string): boolean {\n return false;\n }\n\n async generateImage(): Promise<never> {\n throw new Error(\n \"Anthropic does not support image generation. Use OpenAI (DALL-E, GPT Image) or Google Gemini (Imagen) instead.\",\n );\n }\n\n // =========================================================================\n // Speech Generation (Not Supported)\n // =========================================================================\n\n supportsSpeechGeneration(_modelId: string): boolean {\n return false;\n }\n\n async generateSpeech(): Promise<never> {\n throw new Error(\n \"Anthropic does not support speech generation. Use OpenAI (TTS) or Google Gemini (TTS) instead.\",\n );\n }\n\n protected buildApiRequest(\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 // System messages are always text-only\n const system =\n systemMessages.length > 0\n ? systemMessages.map((m, index) => ({\n type: \"text\" as const,\n text: extractMessageText(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 multimodal content support\n // Cache_control is added to the last part of the last user message\n const conversation = nonSystemMessages.map((message, index) => ({\n role: message.role,\n content: this.convertToAnthropicContent(\n message.content,\n message.role === \"user\" && index === lastUserIndex,\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 /**\n * Convert llmist content to Anthropic's content block format.\n * Handles text, images (base64 only), and applies cache_control.\n */\n private convertToAnthropicContent(\n content: MessageContent,\n addCacheControl: boolean,\n ): ContentBlockParam[] {\n const parts = normalizeMessageContent(content);\n\n return parts.map((part, index) => {\n const isLastPart = index === parts.length - 1;\n const cacheControl =\n addCacheControl && isLastPart ? { cache_control: { type: \"ephemeral\" as const } } : {};\n\n if (part.type === \"text\") {\n return {\n type: \"text\" as const,\n text: part.text,\n ...cacheControl,\n } as TextBlockParam;\n }\n\n if (part.type === \"image\") {\n return this.convertImagePart(part, cacheControl);\n }\n\n if (part.type === \"audio\") {\n throw new Error(\n \"Anthropic does not support audio input. Use Google Gemini for audio processing.\",\n );\n }\n\n throw new Error(`Unsupported content type: ${(part as ContentPart).type}`);\n });\n }\n\n /**\n * Convert an image content part to Anthropic's image block format.\n */\n private convertImagePart(\n part: ImageContentPart,\n cacheControl: { cache_control?: { type: \"ephemeral\" } },\n ): ImageBlockParam {\n if (part.source.type === \"url\") {\n throw new Error(\n \"Anthropic does not support image URLs. Please provide base64-encoded image data instead.\",\n );\n }\n\n return {\n type: \"image\" as const,\n source: {\n type: \"base64\" as const,\n media_type: part.source.mediaType as ImageMimeType,\n data: part.source.data,\n },\n ...cacheControl,\n };\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 *normalizeProviderStream(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\n ? systemMessages.map((m) => extractMessageText(m.content)).join(\"\\n\\n\")\n : undefined;\n\n // Convert messages to Anthropic format, handling multimodal content\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: this.convertToAnthropicContent(message.content, false),\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 // For multimodal, extract text and estimate; images add ~1000 tokens\n let totalChars = 0;\n let imageCount = 0;\n for (const msg of messages) {\n const parts = normalizeMessageContent(msg.content);\n for (const part of parts) {\n if (part.type === \"text\") {\n totalChars += part.text.length;\n } else if (part.type === \"image\") {\n imageCount++;\n }\n }\n }\n // Anthropic charges ~1000 tokens per image (rough estimate).\n // Source: https://docs.anthropic.com/en/docs/build-with-claude/vision\n // Actual cost depends on image size, but this provides a reasonable fallback.\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN) + imageCount * 1000;\n }\n }\n}\n\nexport function createAnthropicProviderFromEnv(): AnthropicMessagesProvider | null {\n return createProviderFromEnv(\"ANTHROPIC_API_KEY\", Anthropic, AnthropicMessagesProvider);\n}\n","/**\n * Google Gemini Image Generation Model Catalog\n *\n * Pricing as of December 2025:\n *\n * Imagen 4 Family (standalone image generation):\n * - imagen-4.0-fast-generate-001: $0.02 per image\n * - imagen-4.0-generate-001: $0.04 per image\n * - imagen-4.0-ultra-generate-001: $0.06 per image\n *\n * Gemini Native Image Generation (multimodal):\n * - gemini-2.5-flash-image: $0.039 per output image\n * - gemini-3-pro-image-preview: ~$0.134 per 1K/2K image, $0.24 per 4K\n *\n * @see https://ai.google.dev/gemini-api/docs/pricing\n * @see https://ai.google.dev/gemini-api/docs/imagen\n */\n\nimport type { ImageModelSpec } from \"../core/media-types.js\";\n\n/** Imagen 4 supported aspect ratios */\nexport const IMAGEN4_ASPECT_RATIOS = [\"1:1\", \"3:4\", \"4:3\", \"9:16\", \"16:9\"] as const;\nexport type Imagen4AspectRatio = (typeof IMAGEN4_ASPECT_RATIOS)[number];\n\n/** Gemini native image supported aspect ratios */\nexport const GEMINI_IMAGE_ASPECT_RATIOS = [\"1:1\", \"3:4\", \"4:3\", \"9:16\", \"16:9\"] as const;\n\n/**\n * Google Image Model Specifications\n */\nexport const geminiImageModels: ImageModelSpec[] = [\n // Imagen 4 Family (standalone image generation)\n {\n provider: \"gemini\",\n modelId: \"imagen-4.0-fast-generate-001\",\n displayName: \"Imagen 4 Fast\",\n pricing: {\n perImage: 0.02,\n },\n supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n maxImages: 4,\n defaultSize: \"1:1\",\n features: {\n textRendering: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"imagen-4.0-generate-001\",\n displayName: \"Imagen 4\",\n pricing: {\n perImage: 0.04,\n },\n supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n maxImages: 4,\n defaultSize: \"1:1\",\n features: {\n textRendering: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"imagen-4.0-ultra-generate-001\",\n displayName: \"Imagen 4 Ultra\",\n pricing: {\n perImage: 0.06,\n },\n supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n maxImages: 4,\n defaultSize: \"1:1\",\n features: {\n textRendering: true,\n },\n },\n // Preview versions\n {\n provider: \"gemini\",\n modelId: \"imagen-4.0-generate-preview-06-06\",\n displayName: \"Imagen 4 (Preview)\",\n pricing: {\n perImage: 0.04,\n },\n supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n maxImages: 4,\n defaultSize: \"1:1\",\n features: {\n textRendering: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"imagen-4.0-ultra-generate-preview-06-06\",\n displayName: \"Imagen 4 Ultra (Preview)\",\n pricing: {\n perImage: 0.06,\n },\n supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n maxImages: 4,\n defaultSize: \"1:1\",\n features: {\n textRendering: true,\n },\n },\n // Gemini Native Image Generation (multimodal models)\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-flash-image\",\n displayName: \"Gemini 2.5 Flash Image\",\n pricing: {\n perImage: 0.039,\n },\n supportedSizes: [...GEMINI_IMAGE_ASPECT_RATIOS],\n maxImages: 1,\n defaultSize: \"1:1\",\n features: {\n conversational: true,\n textRendering: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-flash-image-preview\",\n displayName: \"Gemini 2.5 Flash Image (Preview)\",\n pricing: {\n perImage: 0.039,\n },\n supportedSizes: [...GEMINI_IMAGE_ASPECT_RATIOS],\n maxImages: 1,\n defaultSize: \"1:1\",\n features: {\n conversational: true,\n textRendering: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"gemini-3-pro-image-preview\",\n displayName: \"Gemini 3 Pro Image (Preview)\",\n pricing: {\n // Token-based: ~$0.134 per 1K/2K image, $0.24 per 4K\n // Using 2K as default\n bySize: {\n \"1K\": 0.134,\n \"2K\": 0.134,\n \"4K\": 0.24,\n },\n },\n supportedSizes: [\"1K\", \"2K\", \"4K\"],\n maxImages: 1,\n defaultSize: \"2K\",\n features: {\n conversational: true,\n textRendering: true,\n },\n },\n // Alias: nano-banana-pro-preview is gemini-3-pro-image-preview\n {\n provider: \"gemini\",\n modelId: \"nano-banana-pro-preview\",\n displayName: \"Nano Banana Pro (Gemini 3 Pro Image)\",\n pricing: {\n bySize: {\n \"1K\": 0.134,\n \"2K\": 0.134,\n \"4K\": 0.24,\n },\n },\n supportedSizes: [\"1K\", \"2K\", \"4K\"],\n maxImages: 1,\n defaultSize: \"2K\",\n features: {\n conversational: true,\n textRendering: true,\n },\n },\n];\n\n/**\n * Get image model spec by model ID.\n */\nexport function getGeminiImageModelSpec(modelId: string): ImageModelSpec | undefined {\n return geminiImageModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is a Gemini image model.\n */\nexport function isGeminiImageModel(modelId: string): boolean {\n return geminiImageModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for image generation.\n *\n * @param modelId - The model ID\n * @param size - Image size (for models with size-based pricing)\n * @param n - Number of images\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateGeminiImageCost(modelId: string, size = \"1:1\", n = 1): number | undefined {\n const spec = getGeminiImageModelSpec(modelId);\n if (!spec) return undefined;\n\n // Simple per-image pricing (Imagen 4, Gemini Flash Image)\n if (spec.pricing.perImage !== undefined) {\n return spec.pricing.perImage * n;\n }\n\n // Size-based pricing (Gemini 3 Pro Image)\n if (spec.pricing.bySize) {\n const sizePrice = spec.pricing.bySize[size];\n if (typeof sizePrice === \"number\") {\n return sizePrice * n;\n }\n }\n\n return undefined;\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-12-20\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 3 Flash (Preview)\n {\n provider: \"gemini\",\n modelId: \"gemini-3-flash-preview\",\n displayName: \"Gemini 3 Flash (Preview)\",\n contextWindow: 1_048_576,\n maxOutputTokens: 65_536,\n pricing: {\n input: 0.4, // $0.40 for text/image/video\n output: 3.0,\n cachedInput: 0.04,\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-12\",\n notes: \"Fast, cost-effective model with Deep Think mode. Good for agentic tasks.\",\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","/**\n * Google Gemini Speech (TTS) Model Catalog\n *\n * Pricing as of December 2025 (per 1M tokens):\n *\n * Gemini 2.5 Flash Preview TTS:\n * - Input (text): $0.50\n * - Output (audio): $10.00\n *\n * Gemini 2.5 Pro Preview TTS:\n * - Input (text): $1.00\n * - Output (audio): $20.00\n *\n * @see https://ai.google.dev/gemini-api/docs/pricing\n * @see https://ai.google.dev/gemini-api/docs/speech-generation\n */\n\nimport type { AudioFormat, SpeechModelSpec } from \"../core/media-types.js\";\n\n/**\n * Gemini TTS voices (30 prebuilt voices)\n * Each has distinct characteristics like \"Bright\", \"Upbeat\", \"Breathy\", \"Warm\", etc.\n */\nexport const GEMINI_TTS_VOICES = [\n \"Zephyr\", // Bright\n \"Puck\", // Upbeat\n \"Charon\", // Informative\n \"Kore\", // Firm\n \"Fenrir\", // Excitable\n \"Leda\", // Youthful\n \"Orus\", // Firm\n \"Aoede\", // Breezy\n \"Callirrhoe\", // Easy-going\n \"Autonoe\", // Bright\n \"Enceladus\", // Breathy\n \"Iapetus\", // Clear\n \"Umbriel\", // Easy-going\n \"Algieba\", // Smooth\n \"Despina\", // Smooth\n \"Erinome\", // Clear\n \"Algenib\", // Gravelly\n \"Rasalgethi\", // Informative\n \"Laomedeia\", // Upbeat\n \"Achernar\", // Soft\n \"Alnilam\", // Firm\n \"Schedar\", // Even\n \"Gacrux\", // Mature\n \"Pulcherrima\", // Forward\n \"Achird\", // Friendly\n \"Zubenelgenubi\", // Casual\n \"Vindemiatrix\", // Gentle\n \"Sadachbia\", // Lively\n \"Sadaltager\", // Knowledgeable\n \"Sulafat\", // Warm\n] as const;\n\nexport type GeminiTTSVoice = (typeof GEMINI_TTS_VOICES)[number];\n\n/** Gemini TTS supported audio format (PCM only, converted to WAV) */\nexport const GEMINI_TTS_FORMATS: AudioFormat[] = [\"pcm\", \"wav\"];\n\n/**\n * Gemini Speech Model Specifications\n */\nexport const geminiSpeechModels: SpeechModelSpec[] = [\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-flash-preview-tts\",\n displayName: \"Gemini 2.5 Flash TTS (Preview)\",\n pricing: {\n // $0.50 per 1M input tokens = $0.0000005 per token\n perInputToken: 0.0000005,\n // $10.00 per 1M audio output tokens = $0.00001 per token\n perAudioOutputToken: 0.00001,\n // Rough estimate: ~$0.01 per minute of audio\n perMinute: 0.01,\n },\n voices: [...GEMINI_TTS_VOICES],\n formats: GEMINI_TTS_FORMATS,\n maxInputLength: 8000, // bytes (text + prompt combined)\n defaultVoice: \"Zephyr\",\n defaultFormat: \"wav\",\n features: {\n multiSpeaker: true,\n languages: 24,\n voiceInstructions: true,\n },\n },\n {\n provider: \"gemini\",\n modelId: \"gemini-2.5-pro-preview-tts\",\n displayName: \"Gemini 2.5 Pro TTS (Preview)\",\n pricing: {\n // $1.00 per 1M input tokens = $0.000001 per token\n perInputToken: 0.000001,\n // $20.00 per 1M audio output tokens = $0.00002 per token\n perAudioOutputToken: 0.00002,\n // Rough estimate: ~$0.02 per minute of audio\n perMinute: 0.02,\n },\n voices: [...GEMINI_TTS_VOICES],\n formats: GEMINI_TTS_FORMATS,\n maxInputLength: 8000, // bytes\n defaultVoice: \"Zephyr\",\n defaultFormat: \"wav\",\n features: {\n multiSpeaker: true,\n languages: 24,\n voiceInstructions: true,\n },\n },\n];\n\n/**\n * Get speech model spec by model ID.\n */\nexport function getGeminiSpeechModelSpec(modelId: string): SpeechModelSpec | undefined {\n return geminiSpeechModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is a Gemini speech model.\n */\nexport function isGeminiSpeechModel(modelId: string): boolean {\n return geminiSpeechModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for speech generation.\n *\n * Uses per-minute approximation since exact token counts are hard to predict.\n *\n * @param modelId - The model ID\n * @param characterCount - Number of characters in the input\n * @param estimatedMinutes - Optional: estimated audio duration\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateGeminiSpeechCost(\n modelId: string,\n characterCount: number,\n estimatedMinutes?: number,\n): number | undefined {\n const spec = getGeminiSpeechModelSpec(modelId);\n if (!spec) return undefined;\n\n // Use per-minute approximation\n if (spec.pricing.perMinute !== undefined) {\n if (estimatedMinutes !== undefined) {\n return estimatedMinutes * spec.pricing.perMinute;\n }\n // Fallback: rough estimate based on ~150 words/min, ~5 chars/word\n // ~750 chars/min of audio\n const approxMinutes = characterCount / 750;\n return approxMinutes * spec.pricing.perMinute;\n }\n\n return undefined;\n}\n","import { FunctionCallingConfigMode, GoogleGenAI, Modality } from \"@google/genai\";\nimport type { ContentPart } from \"../core/input-content.js\";\nimport type {\n ImageGenerationOptions,\n ImageGenerationResult,\n ImageModelSpec,\n SpeechGenerationOptions,\n SpeechGenerationResult,\n SpeechModelSpec,\n} from \"../core/media-types.js\";\nimport type { LLMMessage, MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, normalizeMessageContent } 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 {\n calculateGeminiImageCost,\n geminiImageModels,\n getGeminiImageModelSpec,\n isGeminiImageModel,\n} from \"./gemini-image-models.js\";\nimport { GEMINI_MODELS } from \"./gemini-models.js\";\nimport {\n calculateGeminiSpeechCost,\n geminiSpeechModels,\n getGeminiSpeechModelSpec,\n isGeminiSpeechModel,\n} from \"./gemini-speech-models.js\";\nimport { createProviderFromEnv } from \"./utils.js\";\n\n/**\n * Gemini content part - can be text or inline data (images/audio).\n */\ntype GeminiPart = { text: string } | { inlineData: { mimeType: string; data: string } };\n\n/**\n * Gemini content with role and multimodal parts.\n */\ntype GeminiContent = {\n role: string;\n parts: GeminiPart[];\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\n/**\n * Wraps raw PCM audio data in a WAV file container.\n *\n * WAV format structure:\n * - RIFF header (12 bytes)\n * - fmt chunk (24 bytes) - describes audio format\n * - data chunk (8 bytes + audio data)\n *\n * @param pcmData - Raw PCM audio samples\n * @param sampleRate - Sample rate in Hz (e.g., 24000)\n * @param bitsPerSample - Bits per sample (e.g., 16)\n * @param numChannels - Number of audio channels (1 = mono, 2 = stereo)\n * @returns ArrayBuffer containing valid WAV file\n */\nfunction wrapPcmInWav(\n pcmData: Uint8Array,\n sampleRate: number,\n bitsPerSample: number,\n numChannels: number,\n): ArrayBuffer {\n const byteRate = (sampleRate * numChannels * bitsPerSample) / 8;\n const blockAlign = (numChannels * bitsPerSample) / 8;\n const dataSize = pcmData.length;\n const headerSize = 44;\n const fileSize = headerSize + dataSize - 8; // File size minus RIFF header\n\n const buffer = new ArrayBuffer(headerSize + dataSize);\n const view = new DataView(buffer);\n const uint8 = new Uint8Array(buffer);\n\n // RIFF header\n view.setUint32(0, 0x52494646, false); // \"RIFF\"\n view.setUint32(4, fileSize, true); // File size - 8\n view.setUint32(8, 0x57415645, false); // \"WAVE\"\n\n // fmt chunk\n view.setUint32(12, 0x666d7420, false); // \"fmt \"\n view.setUint32(16, 16, true); // fmt chunk size (16 for PCM)\n view.setUint16(20, 1, true); // Audio format (1 = PCM)\n view.setUint16(22, numChannels, true); // Number of channels\n view.setUint32(24, sampleRate, true); // Sample rate\n view.setUint32(28, byteRate, true); // Byte rate\n view.setUint16(32, blockAlign, true); // Block align\n view.setUint16(34, bitsPerSample, true); // Bits per sample\n\n // data chunk\n view.setUint32(36, 0x64617461, false); // \"data\"\n view.setUint32(40, dataSize, true); // Data size\n\n // Copy PCM data\n uint8.set(pcmData, headerSize);\n\n return buffer;\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 // =========================================================================\n // Image Generation\n // =========================================================================\n\n getImageModelSpecs(): ImageModelSpec[] {\n return geminiImageModels;\n }\n\n supportsImageGeneration(modelId: string): boolean {\n return isGeminiImageModel(modelId);\n }\n\n async generateImage(options: ImageGenerationOptions): Promise<ImageGenerationResult> {\n const client = this.client as GoogleGenAI;\n const spec = getGeminiImageModelSpec(options.model);\n const isImagenModel = options.model.startsWith(\"imagen\");\n\n const aspectRatio = options.size ?? spec?.defaultSize ?? \"1:1\";\n const n = options.n ?? 1;\n\n if (isImagenModel) {\n // Use Imagen API for imagen models\n // Note: safetyFilterLevel and personGeneration can be configured for less restrictive filtering\n // Valid safetyFilterLevel values: \"BLOCK_NONE\" | \"BLOCK_ONLY_HIGH\" | \"BLOCK_MEDIUM_AND_ABOVE\" | \"BLOCK_LOW_AND_ABOVE\"\n // Valid personGeneration values: \"ALLOW_ALL\" | \"ALLOW_ADULT\" | \"DONT_ALLOW\"\n const response = await client.models.generateImages({\n model: options.model,\n prompt: options.prompt,\n config: {\n numberOfImages: n,\n aspectRatio: aspectRatio,\n outputMimeType: options.responseFormat === \"b64_json\" ? \"image/png\" : \"image/jpeg\",\n },\n });\n\n const images = response.generatedImages ?? [];\n const cost = calculateGeminiImageCost(options.model, aspectRatio, images.length);\n\n return {\n // Gemini's imageBytes is already base64 encoded, so use it directly\n images: images.map((img) => ({\n b64Json: img.image?.imageBytes ?? undefined,\n })),\n model: options.model,\n usage: {\n imagesGenerated: images.length,\n size: aspectRatio,\n quality: \"standard\",\n },\n cost,\n };\n }\n // Use native Gemini image generation for gemini-* models\n const response = await client.models.generateContent({\n model: options.model,\n contents: [{ role: \"user\", parts: [{ text: options.prompt }] }],\n config: {\n responseModalities: [Modality.IMAGE, Modality.TEXT],\n },\n });\n\n // Extract images from response\n const images: Array<{ b64Json?: string; url?: string }> = [];\n const candidate = response.candidates?.[0];\n if (candidate?.content?.parts) {\n for (const part of candidate.content.parts) {\n if (\"inlineData\" in part && part.inlineData) {\n images.push({\n b64Json: part.inlineData.data,\n });\n }\n }\n }\n\n const cost = calculateGeminiImageCost(options.model, aspectRatio, images.length);\n\n return {\n images,\n model: options.model,\n usage: {\n imagesGenerated: images.length,\n size: aspectRatio,\n quality: \"standard\",\n },\n cost,\n };\n }\n\n // =========================================================================\n // Speech Generation\n // =========================================================================\n\n getSpeechModelSpecs(): SpeechModelSpec[] {\n return geminiSpeechModels;\n }\n\n supportsSpeechGeneration(modelId: string): boolean {\n return isGeminiSpeechModel(modelId);\n }\n\n async generateSpeech(options: SpeechGenerationOptions): Promise<SpeechGenerationResult> {\n const client = this.client as GoogleGenAI;\n const spec = getGeminiSpeechModelSpec(options.model);\n\n const voice = options.voice ?? spec?.defaultVoice ?? \"Zephyr\";\n\n // Gemini TTS uses speech configuration\n const response = await client.models.generateContent({\n model: options.model,\n contents: [\n {\n role: \"user\",\n parts: [{ text: options.input }],\n },\n ],\n config: {\n responseModalities: [Modality.AUDIO],\n speechConfig: {\n voiceConfig: {\n prebuiltVoiceConfig: {\n voiceName: voice,\n },\n },\n },\n },\n });\n\n // Extract audio from response\n let pcmData: Uint8Array | undefined;\n const candidate = response.candidates?.[0];\n if (candidate?.content?.parts) {\n for (const part of candidate.content.parts) {\n if (\"inlineData\" in part && part.inlineData?.data) {\n // Convert base64 to Uint8Array\n const base64 = part.inlineData.data;\n const binary = atob(base64);\n pcmData = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n pcmData[i] = binary.charCodeAt(i);\n }\n break;\n }\n }\n }\n\n if (!pcmData) {\n throw new Error(\"No audio data in Gemini TTS response\");\n }\n\n // Wrap raw PCM data in WAV headers (Gemini returns 24kHz, 16-bit, mono PCM)\n const audioData = wrapPcmInWav(pcmData, 24000, 16, 1);\n\n const cost = calculateGeminiSpeechCost(options.model, options.input.length);\n\n return {\n audio: audioData,\n model: options.model,\n usage: {\n characterCount: options.input.length,\n },\n cost,\n format: spec?.defaultFormat ?? \"wav\",\n };\n }\n\n protected buildApiRequest(\n options: LLMGenerationOptions,\n descriptor: ModelDescriptor,\n _spec: ModelSpec | undefined,\n messages: LLMMessage[],\n ): {\n model: string;\n contents: GeminiContent[];\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,\n config,\n };\n }\n\n protected async executeStreamRequest(\n payload: {\n model: string;\n contents: GeminiContent[];\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: Array<{ role: LLMMessage[\"role\"]; content: MessageContent }> = [];\n\n for (const message of messages) {\n if (message.role === \"system\") {\n // Convert system message to user+model exchange\n // System messages are always text-only\n expandedMessages.push({\n role: \"user\",\n content: extractMessageText(message.content),\n });\n expandedMessages.push({\n role: \"assistant\",\n content: \"Understood.\",\n });\n } else {\n expandedMessages.push({\n role: message.role,\n content: message.content,\n });\n }\n }\n\n return this.mergeConsecutiveMessages(expandedMessages);\n }\n\n /**\n * Merge consecutive messages with the same role (required by Gemini).\n * Handles multimodal content by converting to Gemini's part format.\n */\n private mergeConsecutiveMessages(\n messages: Array<{ role: LLMMessage[\"role\"]; content: MessageContent }>,\n ): 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 const geminiParts = this.convertToGeminiParts(message.content);\n\n if (currentGroup && currentGroup.role === geminiRole) {\n // Merge into current group\n currentGroup.parts.push(...geminiParts);\n } else {\n // Start new group\n if (currentGroup) {\n result.push(currentGroup);\n }\n currentGroup = {\n role: geminiRole,\n parts: geminiParts,\n };\n }\n }\n\n // Push the last group\n if (currentGroup) {\n result.push(currentGroup);\n }\n\n return result;\n }\n\n /**\n * Convert llmist content to Gemini's part format.\n * Handles text, images, and audio (Gemini supports all three).\n */\n private convertToGeminiParts(content: MessageContent): GeminiPart[] {\n const parts = normalizeMessageContent(content);\n\n return parts.map((part) => {\n if (part.type === \"text\") {\n return { text: part.text };\n }\n\n if (part.type === \"image\") {\n if (part.source.type === \"url\") {\n throw new Error(\n \"Gemini does not support image URLs directly. Please provide base64-encoded image data.\",\n );\n }\n return {\n inlineData: {\n mimeType: part.source.mediaType,\n data: part.source.data,\n },\n };\n }\n\n if (part.type === \"audio\") {\n return {\n inlineData: {\n mimeType: part.source.mediaType,\n data: part.source.data,\n },\n };\n }\n\n throw new Error(`Unsupported content type: ${(part as ContentPart).type}`);\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 *normalizeProviderStream(iterable: AsyncIterable<unknown>): LLMStream {\n const stream = iterable as AsyncIterable<GeminiChunk>;\n for await (const chunk of stream) {\n const text = this.extractMessageText(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 extractMessageText(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 // This now handles multimodal content\n const contents = this.convertMessagesToContents(messages);\n\n // Return 0 for empty messages - Gemini API requires non-empty contents\n if (!contents || contents.length === 0) {\n return 0;\n }\n\n try {\n // Use Gemini's count_tokens method\n const response = await client.models.countTokens({\n model: descriptor.name,\n 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 // For multimodal, extract text and estimate; images/audio add tokens\n let totalChars = 0;\n let mediaCount = 0;\n for (const msg of messages) {\n const parts = normalizeMessageContent(msg.content);\n for (const part of parts) {\n if (part.type === \"text\") {\n totalChars += part.text.length;\n } else if (part.type === \"image\" || part.type === \"audio\") {\n mediaCount++;\n }\n }\n }\n // Gemini charges ~258 tokens per image/audio (for standard size).\n // Source: https://ai.google.dev/gemini-api/docs/tokens\n // Actual cost varies by media type and dimensions.\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN) + mediaCount * 258;\n }\n }\n}\n\nexport function createGeminiProviderFromEnv(): GeminiGenerativeProvider | null {\n return createProviderFromEnv(\"GEMINI_API_KEY\", GoogleGenAI, GeminiGenerativeProvider);\n}\n","/**\n * OpenAI Image Generation Model Catalog\n *\n * Pricing as of December 2025:\n *\n * GPT Image 1.5 (flagship):\n * - Low quality: ~$0.008 per image\n * - Medium quality: ~$0.03 per image\n * - High quality: ~$0.13 per image\n *\n * GPT Image 1 (previous gen):\n * - Low quality: ~$0.011 per image\n * - Medium quality: ~$0.04 per image\n * - High quality: ~$0.17 per image\n *\n * GPT Image 1 Mini (cost-effective):\n * - Low quality: ~$0.005 per image\n * - Medium quality: ~$0.02 per image\n * - High quality: ~$0.052 per image\n *\n * Sora 2 (video generation):\n * - Standard quality: ~$0.50 per 5-second clip\n * - High quality: ~$1.00 per 5-second clip\n *\n * DALL-E 3 (deprecated):\n * - 1024x1024: $0.040 (standard), $0.080 (hd)\n * - 1024x1792: $0.080 (standard), $0.120 (hd)\n * - 1792x1024: $0.080 (standard), $0.120 (hd)\n *\n * DALL-E 2 (deprecated):\n * - 256x256: $0.016\n * - 512x512: $0.018\n * - 1024x1024: $0.020\n *\n * @see https://platform.openai.com/docs/guides/images\n */\n\nimport type { ImageModelSpec } from \"../core/media-types.js\";\n\n/** GPT Image supported sizes */\nexport const GPT_IMAGE_SIZES = [\"1024x1024\", \"1024x1536\", \"1536x1024\", \"1920x1080\", \"auto\"] as const;\nexport type GptImageSize = (typeof GPT_IMAGE_SIZES)[number];\n\n/** GPT Image quality levels */\nexport const GPT_IMAGE_QUALITIES = [\"low\", \"medium\", \"high\"] as const;\nexport type GptImageQuality = (typeof GPT_IMAGE_QUALITIES)[number];\n\n/** Sora video durations */\nexport const SORA_DURATIONS = [\"5s\", \"10s\", \"15s\", \"20s\"] as const;\nexport type SoraDuration = (typeof SORA_DURATIONS)[number];\n\n/** DALL-E 3 supported sizes (deprecated) */\nexport const DALLE3_SIZES = [\"1024x1024\", \"1024x1792\", \"1792x1024\"] as const;\nexport type DallE3Size = (typeof DALLE3_SIZES)[number];\n\n/** DALL-E 3 quality levels (deprecated) */\nexport const DALLE3_QUALITIES = [\"standard\", \"hd\"] as const;\nexport type DallE3Quality = (typeof DALLE3_QUALITIES)[number];\n\n/** DALL-E 2 supported sizes (deprecated) */\nexport const DALLE2_SIZES = [\"256x256\", \"512x512\", \"1024x1024\"] as const;\nexport type DallE2Size = (typeof DALLE2_SIZES)[number];\n\n/**\n * OpenAI Image Model Specifications\n */\nexport const openaiImageModels: ImageModelSpec[] = [\n // GPT Image 1.5 Family (flagship)\n {\n provider: \"openai\",\n modelId: \"gpt-image-1.5\",\n displayName: \"GPT Image 1.5\",\n pricing: {\n bySize: {\n \"1024x1024\": { low: 0.008, medium: 0.03, high: 0.13 },\n \"1024x1536\": { low: 0.012, medium: 0.045, high: 0.195 },\n \"1536x1024\": { low: 0.012, medium: 0.045, high: 0.195 },\n \"1920x1080\": { low: 0.016, medium: 0.06, high: 0.26 },\n },\n },\n supportedSizes: [...GPT_IMAGE_SIZES],\n supportedQualities: [...GPT_IMAGE_QUALITIES],\n maxImages: 1,\n defaultSize: \"1024x1024\",\n defaultQuality: \"medium\",\n features: {\n textRendering: true,\n transparency: true,\n editing: true,\n },\n },\n // GPT Image 1 Family (previous gen)\n {\n provider: \"openai\",\n modelId: \"gpt-image-1\",\n displayName: \"GPT Image 1\",\n pricing: {\n bySize: {\n \"1024x1024\": { low: 0.011, medium: 0.04, high: 0.17 },\n \"1024x1536\": { low: 0.016, medium: 0.06, high: 0.25 },\n \"1536x1024\": { low: 0.016, medium: 0.06, high: 0.25 },\n },\n },\n supportedSizes: [\"1024x1024\", \"1024x1536\", \"1536x1024\"],\n supportedQualities: [...GPT_IMAGE_QUALITIES],\n maxImages: 1,\n defaultSize: \"1024x1024\",\n defaultQuality: \"medium\",\n features: {\n textRendering: true,\n transparency: true,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-image-1-mini\",\n displayName: \"GPT Image 1 Mini\",\n pricing: {\n bySize: {\n \"1024x1024\": { low: 0.005, medium: 0.02, high: 0.052 },\n \"1024x1536\": { low: 0.0075, medium: 0.03, high: 0.078 },\n \"1536x1024\": { low: 0.0075, medium: 0.03, high: 0.078 },\n },\n },\n supportedSizes: [\"1024x1024\", \"1024x1536\", \"1536x1024\"],\n supportedQualities: [...GPT_IMAGE_QUALITIES],\n maxImages: 1,\n defaultSize: \"1024x1024\",\n defaultQuality: \"medium\",\n features: {\n textRendering: true,\n transparency: true,\n },\n },\n // Sora Video Generation Models\n {\n provider: \"openai\",\n modelId: \"sora-2\",\n displayName: \"Sora 2\",\n pricing: {\n bySize: {\n \"1920x1080\": { standard: 0.5, high: 1.0 },\n \"1080x1920\": { standard: 0.5, high: 1.0 },\n \"1024x1024\": { standard: 0.4, high: 0.8 },\n },\n },\n supportedSizes: [\"1920x1080\", \"1080x1920\", \"1024x1024\"],\n supportedQualities: [\"standard\", \"high\"],\n maxImages: 1,\n defaultSize: \"1920x1080\",\n defaultQuality: \"standard\",\n features: {\n videoGeneration: true,\n },\n },\n {\n provider: \"openai\",\n modelId: \"sora-2-pro\",\n displayName: \"Sora 2 Pro\",\n pricing: {\n bySize: {\n \"1920x1080\": { standard: 1.0, high: 2.0 },\n \"1080x1920\": { standard: 1.0, high: 2.0 },\n \"1024x1024\": { standard: 0.8, high: 1.6 },\n },\n },\n supportedSizes: [\"1920x1080\", \"1080x1920\", \"1024x1024\"],\n supportedQualities: [\"standard\", \"high\"],\n maxImages: 1,\n defaultSize: \"1920x1080\",\n defaultQuality: \"standard\",\n features: {\n videoGeneration: true,\n extendedDuration: true,\n },\n },\n // DALL-E Family (deprecated - use GPT Image models instead)\n {\n provider: \"openai\",\n modelId: \"dall-e-3\",\n displayName: \"DALL-E 3 (Deprecated)\",\n pricing: {\n bySize: {\n \"1024x1024\": { standard: 0.04, hd: 0.08 },\n \"1024x1792\": { standard: 0.08, hd: 0.12 },\n \"1792x1024\": { standard: 0.08, hd: 0.12 },\n },\n },\n supportedSizes: [...DALLE3_SIZES],\n supportedQualities: [...DALLE3_QUALITIES],\n maxImages: 1, // DALL-E 3 only supports n=1\n defaultSize: \"1024x1024\",\n defaultQuality: \"standard\",\n features: {\n textRendering: true,\n },\n },\n {\n provider: \"openai\",\n modelId: \"dall-e-2\",\n displayName: \"DALL-E 2 (Deprecated)\",\n pricing: {\n bySize: {\n \"256x256\": 0.016,\n \"512x512\": 0.018,\n \"1024x1024\": 0.02,\n },\n },\n supportedSizes: [...DALLE2_SIZES],\n maxImages: 10,\n defaultSize: \"1024x1024\",\n },\n];\n\n/**\n * Get image model spec by model ID.\n */\nexport function getOpenAIImageModelSpec(modelId: string): ImageModelSpec | undefined {\n return openaiImageModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is an OpenAI image model.\n */\nexport function isOpenAIImageModel(modelId: string): boolean {\n return openaiImageModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for image generation.\n *\n * @param modelId - The model ID (dall-e-3 or dall-e-2)\n * @param size - Image size\n * @param quality - Quality level (for DALL-E 3)\n * @param n - Number of images\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateOpenAIImageCost(\n modelId: string,\n size: string,\n quality = \"standard\",\n n = 1,\n): number | undefined {\n const spec = getOpenAIImageModelSpec(modelId);\n if (!spec) return undefined;\n\n // Get price for this size\n const sizePrice = spec.pricing.bySize?.[size];\n if (sizePrice === undefined) return undefined;\n\n let pricePerImage: number;\n\n if (typeof sizePrice === \"number\") {\n // Flat pricing (DALL-E 2)\n pricePerImage = sizePrice;\n } else {\n // Quality-based pricing (DALL-E 3)\n pricePerImage = sizePrice[quality];\n if (pricePerImage === undefined) return undefined;\n }\n\n return pricePerImage * n;\n}\n","/**\n * OpenAI Model Specifications\n *\n * Model data for OpenAI models including GPT-5.2, GPT-5.1, 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-12-20\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const OPENAI_MODELS: ModelSpec[] = [\n // GPT-5.2 Family (Latest flagship)\n {\n provider: \"openai\",\n modelId: \"gpt-5.2\",\n displayName: \"GPT-5.2\",\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n pricing: {\n input: 1.25,\n output: 10.0,\n cachedInput: 0.125,\n },\n knowledgeCutoff: \"2025-03-31\",\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.2\",\n releaseDate: \"2025-12-01\",\n notes: \"Latest flagship model with 1M context window and enhanced reasoning.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5.2-pro\",\n displayName: \"GPT-5.2 Pro\",\n contextWindow: 1_000_000,\n maxOutputTokens: 128_000,\n pricing: {\n input: 15.0,\n output: 120.0,\n },\n knowledgeCutoff: \"2025-03-31\",\n features: {\n streaming: true,\n functionCalling: true,\n vision: true,\n reasoning: true,\n structuredOutputs: true,\n },\n metadata: {\n family: \"GPT-5.2\",\n releaseDate: \"2025-12-01\",\n notes: \"Premium tier GPT-5.2 with enhanced reasoning. Does not support prompt caching.\",\n supportsTemperature: false,\n },\n },\n\n // GPT-5.1 Family\n {\n provider: \"openai\",\n modelId: \"gpt-5.1\",\n displayName: \"GPT-5.1\",\n contextWindow: 1_000_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.1\",\n releaseDate: \"2025-11-12\",\n notes: \"GPT-5 variant with improved instruction following. 2-3x faster than GPT-5.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5.1-codex\",\n displayName: \"GPT-5.1 Codex\",\n contextWindow: 1_000_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 },\n metadata: {\n family: \"GPT-5.1\",\n notes: \"GPT-5.1 variant optimized for code generation and analysis.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5.1-codex-max\",\n displayName: \"GPT-5.1 Codex Max\",\n contextWindow: 1_000_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 },\n metadata: {\n family: \"GPT-5.1\",\n notes: \"Extended thinking variant of GPT-5.1 Codex for complex code tasks.\",\n supportsTemperature: false,\n },\n },\n\n // GPT-5 Family\n {\n provider: \"openai\",\n modelId: \"gpt-5\",\n displayName: \"GPT-5\",\n contextWindow: 1_000_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: \"High-capability model for coding and agentic tasks. 90% caching discount.\",\n supportsTemperature: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"gpt-5-codex\",\n displayName: \"GPT-5 Codex\",\n contextWindow: 1_000_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 },\n metadata: {\n family: \"GPT-5\",\n notes: \"GPT-5 variant optimized for code generation and analysis.\",\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: \"o1-pro\",\n displayName: \"o1 Pro\",\n contextWindow: 200_000,\n maxOutputTokens: 100_000,\n pricing: {\n input: 150.0,\n output: 600.0,\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: \"Premium tier o1 with extended reasoning. Does not support prompt caching.\",\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","/**\n * OpenAI Speech (TTS) Model Catalog\n *\n * Pricing as of December 2025:\n * - tts-1: $15.00 per 1M characters\n * - tts-1-hd: $30.00 per 1M characters\n * - gpt-4o-mini-tts: $0.60/1M input tokens + $12/1M audio output tokens (~$0.015/min)\n *\n * @see https://platform.openai.com/docs/guides/text-to-speech\n */\n\nimport type { AudioFormat, SpeechModelSpec } from \"../core/media-types.js\";\n\n/** OpenAI TTS voices for standard models (tts-1, tts-1-hd) */\nexport const OPENAI_TTS_VOICES = [\"alloy\", \"echo\", \"fable\", \"onyx\", \"nova\", \"shimmer\"] as const;\n\n/** Additional voices available in gpt-4o-mini-tts */\nexport const OPENAI_TTS_EXTENDED_VOICES = [\n ...OPENAI_TTS_VOICES,\n \"ash\",\n \"ballad\",\n \"coral\",\n \"sage\",\n \"verse\",\n] as const;\n\nexport type OpenAITTSVoice = (typeof OPENAI_TTS_VOICES)[number];\nexport type OpenAITTSExtendedVoice = (typeof OPENAI_TTS_EXTENDED_VOICES)[number];\n\n/** OpenAI supported audio formats */\nexport const OPENAI_TTS_FORMATS: AudioFormat[] = [\"mp3\", \"opus\", \"aac\", \"flac\", \"wav\", \"pcm\"];\n\n/**\n * OpenAI Speech Model Specifications\n */\nexport const openaiSpeechModels: SpeechModelSpec[] = [\n // Standard TTS models (character-based pricing)\n {\n provider: \"openai\",\n modelId: \"tts-1\",\n displayName: \"TTS-1\",\n pricing: {\n // $15 per 1M characters = $0.000015 per character\n perCharacter: 0.000015,\n },\n voices: [...OPENAI_TTS_VOICES],\n formats: OPENAI_TTS_FORMATS,\n maxInputLength: 4096,\n defaultVoice: \"alloy\",\n defaultFormat: \"mp3\",\n features: {\n voiceInstructions: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"tts-1-1106\",\n displayName: \"TTS-1 (Nov 2023)\",\n pricing: {\n perCharacter: 0.000015,\n },\n voices: [...OPENAI_TTS_VOICES],\n formats: OPENAI_TTS_FORMATS,\n maxInputLength: 4096,\n defaultVoice: \"alloy\",\n defaultFormat: \"mp3\",\n features: {\n voiceInstructions: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"tts-1-hd\",\n displayName: \"TTS-1 HD\",\n pricing: {\n // $30 per 1M characters = $0.00003 per character\n perCharacter: 0.00003,\n },\n voices: [...OPENAI_TTS_VOICES],\n formats: OPENAI_TTS_FORMATS,\n maxInputLength: 4096,\n defaultVoice: \"alloy\",\n defaultFormat: \"mp3\",\n features: {\n voiceInstructions: false,\n },\n },\n {\n provider: \"openai\",\n modelId: \"tts-1-hd-1106\",\n displayName: \"TTS-1 HD (Nov 2023)\",\n pricing: {\n perCharacter: 0.00003,\n },\n voices: [...OPENAI_TTS_VOICES],\n formats: OPENAI_TTS_FORMATS,\n maxInputLength: 4096,\n defaultVoice: \"alloy\",\n defaultFormat: \"mp3\",\n features: {\n voiceInstructions: false,\n },\n },\n // Token-based TTS model with voice instructions support\n {\n provider: \"openai\",\n modelId: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o Mini TTS\",\n pricing: {\n // $0.60 per 1M input tokens = $0.0000006 per token\n perInputToken: 0.0000006,\n // $12 per 1M audio output tokens = $0.000012 per token\n perAudioOutputToken: 0.000012,\n // ~$0.015 per minute of audio\n perMinute: 0.015,\n },\n voices: [...OPENAI_TTS_EXTENDED_VOICES],\n formats: OPENAI_TTS_FORMATS,\n maxInputLength: 2000, // tokens, not characters\n defaultVoice: \"alloy\",\n defaultFormat: \"mp3\",\n features: {\n voiceInstructions: true,\n },\n },\n];\n\n/**\n * Get speech model spec by model ID.\n */\nexport function getOpenAISpeechModelSpec(modelId: string): SpeechModelSpec | undefined {\n return openaiSpeechModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is an OpenAI speech model.\n */\nexport function isOpenAISpeechModel(modelId: string): boolean {\n return openaiSpeechModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for speech generation.\n *\n * For character-based models (tts-1, tts-1-hd): cost = characters * perCharacter\n * For token-based models (gpt-4o-mini-tts): uses perMinute approximation\n *\n * @param modelId - The model ID\n * @param characterCount - Number of characters in the input\n * @param estimatedMinutes - Optional: estimated audio duration for token-based models\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateOpenAISpeechCost(\n modelId: string,\n characterCount: number,\n estimatedMinutes?: number,\n): number | undefined {\n const spec = getOpenAISpeechModelSpec(modelId);\n if (!spec) return undefined;\n\n // Character-based pricing (tts-1, tts-1-hd)\n if (spec.pricing.perCharacter !== undefined) {\n return characterCount * spec.pricing.perCharacter;\n }\n\n // Token-based pricing (gpt-4o-mini-tts) - use per-minute approximation\n if (spec.pricing.perMinute !== undefined && estimatedMinutes !== undefined) {\n return estimatedMinutes * spec.pricing.perMinute;\n }\n\n // Fallback: rough estimate based on ~150 words/min, ~5 chars/word\n // ~750 chars/min of audio\n if (spec.pricing.perMinute !== undefined) {\n const approxMinutes = characterCount / 750;\n return approxMinutes * spec.pricing.perMinute;\n }\n\n return undefined;\n}\n","import OpenAI from \"openai\";\nimport type {\n ChatCompletionChunk,\n ChatCompletionContentPart,\n ChatCompletionMessageParam,\n} from \"openai/resources/chat/completions\";\nimport { encoding_for_model, type TiktokenModel } from \"tiktoken\";\nimport type { ContentPart, ImageContentPart } from \"../core/input-content.js\";\nimport type {\n ImageGenerationOptions,\n ImageGenerationResult,\n ImageModelSpec,\n SpeechGenerationOptions,\n SpeechGenerationResult,\n SpeechModelSpec,\n} from \"../core/media-types.js\";\nimport type { LLMMessage, MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, normalizeMessageContent } 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 {\n calculateOpenAIImageCost,\n getOpenAIImageModelSpec,\n isOpenAIImageModel,\n openaiImageModels,\n} from \"./openai-image-models.js\";\nimport { OPENAI_MODELS } from \"./openai-models.js\";\nimport {\n calculateOpenAISpeechCost,\n getOpenAISpeechModelSpec,\n isOpenAISpeechModel,\n openaiSpeechModels,\n} from \"./openai-speech-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 // =========================================================================\n // Image Generation\n // =========================================================================\n\n getImageModelSpecs(): ImageModelSpec[] {\n return openaiImageModels;\n }\n\n supportsImageGeneration(modelId: string): boolean {\n return isOpenAIImageModel(modelId);\n }\n\n async generateImage(options: ImageGenerationOptions): Promise<ImageGenerationResult> {\n const client = this.client as OpenAI;\n const spec = getOpenAIImageModelSpec(options.model);\n\n const size = options.size ?? spec?.defaultSize ?? \"1024x1024\";\n const quality = options.quality ?? spec?.defaultQuality ?? \"standard\";\n const n = options.n ?? 1;\n\n // Determine which parameters to include based on model capabilities\n const isDallE2 = options.model === \"dall-e-2\";\n const isGptImage = options.model.startsWith(\"gpt-image\");\n\n // Build request payload conditionally\n // - DALL-E 2: no quality parameter, no response_format\n // - GPT Image: quality uses low/medium/high, no response_format (uses output_format)\n // - DALL-E 3: supports quality (standard/hd) and response_format\n const requestParams: Parameters<typeof client.images.generate>[0] = {\n model: options.model,\n prompt: options.prompt,\n size: size as \"1024x1024\" | \"1024x1792\" | \"1792x1024\" | \"256x256\" | \"512x512\",\n n,\n };\n\n // Only DALL-E 3 supports the quality parameter with standard/hd values\n if (!isDallE2 && !isGptImage) {\n requestParams.quality = quality as \"standard\" | \"hd\";\n }\n\n // GPT Image models use output_format instead of response_format\n if (isGptImage) {\n // GPT Image supports: png, webp, jpeg\n // Map b64_json to the default format (png) since GPT Image API is different\n // For now, we'll always return URLs for GPT Image models\n // Note: GPT Image API uses different response structure\n } else if (!isDallE2) {\n // DALL-E 3 supports response_format\n requestParams.response_format = options.responseFormat ?? \"url\";\n }\n\n const response = await client.images.generate(requestParams);\n\n const cost = calculateOpenAIImageCost(options.model, size, quality, n);\n // Type assertion: we're not using streaming, so response is ImagesResponse\n const images = (response as OpenAI.Images.ImagesResponse).data ?? [];\n\n return {\n images: images.map((img) => ({\n url: img.url,\n b64Json: img.b64_json,\n revisedPrompt: img.revised_prompt,\n })),\n model: options.model,\n usage: {\n imagesGenerated: images.length,\n size,\n quality,\n },\n cost,\n };\n }\n\n // =========================================================================\n // Speech Generation\n // =========================================================================\n\n getSpeechModelSpecs(): SpeechModelSpec[] {\n return openaiSpeechModels;\n }\n\n supportsSpeechGeneration(modelId: string): boolean {\n return isOpenAISpeechModel(modelId);\n }\n\n async generateSpeech(options: SpeechGenerationOptions): Promise<SpeechGenerationResult> {\n const client = this.client as OpenAI;\n const spec = getOpenAISpeechModelSpec(options.model);\n\n const format = options.responseFormat ?? spec?.defaultFormat ?? \"mp3\";\n const voice = options.voice ?? spec?.defaultVoice ?? \"alloy\";\n\n const response = await client.audio.speech.create({\n model: options.model,\n input: options.input,\n voice: voice as \"alloy\" | \"echo\" | \"fable\" | \"onyx\" | \"nova\" | \"shimmer\",\n response_format: format,\n speed: options.speed ?? 1.0,\n });\n\n const audioBuffer = await response.arrayBuffer();\n const cost = calculateOpenAISpeechCost(options.model, options.input.length);\n\n return {\n audio: audioBuffer,\n model: options.model,\n usage: {\n characterCount: options.input.length,\n },\n cost,\n format,\n };\n }\n\n protected buildApiRequest(\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) => this.convertToOpenAIMessage(message)),\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 /**\n * Convert an LLMMessage to OpenAI's ChatCompletionMessageParam.\n * Handles role-specific content type requirements:\n * - system/assistant: string content only\n * - user: string or multimodal array content\n */\n private convertToOpenAIMessage(message: LLMMessage): ChatCompletionMessageParam {\n const role = ROLE_MAP[message.role];\n\n // User messages support multimodal content\n if (role === \"user\") {\n const content = this.convertToOpenAIContent(message.content);\n return {\n role: \"user\",\n content,\n ...(message.name ? { name: message.name } : {}),\n };\n }\n\n // System and assistant messages only support string content\n const textContent =\n typeof message.content === \"string\" ? message.content : extractMessageText(message.content);\n\n if (role === \"system\") {\n return {\n role: \"system\",\n content: textContent,\n ...(message.name ? { name: message.name } : {}),\n };\n }\n\n // Assistant role\n return {\n role: \"assistant\",\n content: textContent,\n ...(message.name ? { name: message.name } : {}),\n };\n }\n\n /**\n * Convert llmist content to OpenAI's content format.\n * Optimizes by returning string for text-only content, array for multimodal.\n */\n private convertToOpenAIContent(content: MessageContent): string | ChatCompletionContentPart[] {\n // Optimization: keep simple string content as-is\n if (typeof content === \"string\") {\n return content;\n }\n\n // Convert array content to OpenAI format\n return content.map((part) => {\n if (part.type === \"text\") {\n return { type: \"text\" as const, text: part.text };\n }\n\n if (part.type === \"image\") {\n return this.convertImagePart(part);\n }\n\n if (part.type === \"audio\") {\n throw new Error(\n \"OpenAI chat completions do not support audio input. Use Whisper for transcription or Gemini for audio understanding.\",\n );\n }\n\n throw new Error(`Unsupported content type: ${(part as ContentPart).type}`);\n });\n }\n\n /**\n * Convert an image content part to OpenAI's image_url format.\n * Supports both URLs and base64 data URLs.\n */\n private convertImagePart(part: ImageContentPart): ChatCompletionContentPart {\n if (part.source.type === \"url\") {\n return {\n type: \"image_url\" as const,\n image_url: { url: part.source.url },\n };\n }\n\n // Convert base64 to data URL format\n return {\n type: \"image_url\" as const,\n image_url: {\n url: `data:${part.source.mediaType};base64,${part.source.data}`,\n },\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 *normalizeProviderStream(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 let imageCount = 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\n // Handle multimodal content\n const textContent = extractMessageText(message.content);\n tokenCount += encoding.encode(textContent).length;\n\n // Count images for estimation (each image ~85 tokens base + variable)\n const parts = normalizeMessageContent(message.content);\n for (const part of parts) {\n if (part.type === \"image\") {\n imageCount++;\n }\n }\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 // Add ~765 tokens per image (low detail mode).\n // Source: https://platform.openai.com/docs/guides/vision\n // High detail mode varies by image size (510-1105 tokens per 512px tile + 85 base).\n tokenCount += imageCount * 765;\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 let totalChars = 0;\n let imageCount = 0;\n for (const msg of messages) {\n const parts = normalizeMessageContent(msg.content);\n for (const part of parts) {\n if (part.type === \"text\") {\n totalChars += part.text.length;\n } else if (part.type === \"image\") {\n imageCount++;\n }\n }\n }\n // Use same image token estimate as tiktoken path (765 tokens per image).\n return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN) + imageCount * 765;\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, optionally with provider prefix\n * (e.g., 'gpt-5', 'claude-sonnet-4-5-20250929', 'anthropic:claude-sonnet-4-5')\n * @returns ModelSpec if found, undefined otherwise\n */\n getModelSpec(modelId: string): ModelSpec | undefined {\n // Support provider-prefixed model IDs (e.g., \"anthropic:claude-sonnet-4-5\")\n // Strip the prefix to match against the registry's model IDs\n const normalizedId = modelId.includes(\":\") ? modelId.split(\":\")[1] : modelId;\n return this.modelSpecs.find((model) => model.modelId === normalizedId);\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","/**\n * Image Generation Namespace\n *\n * Provides image generation methods.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * const result = await llmist.image.generate({\n * model: \"dall-e-3\",\n * prompt: \"A cat in space\",\n * size: \"1024x1024\",\n * quality: \"hd\",\n * });\n *\n * console.log(result.images[0].url);\n * console.log(\"Cost:\", result.cost);\n * ```\n */\n\nimport type { ProviderAdapter } from \"../../providers/provider.js\";\nimport type {\n ImageGenerationOptions,\n ImageGenerationResult,\n ImageModelSpec,\n} from \"../media-types.js\";\n\nexport class ImageNamespace {\n constructor(\n private readonly adapters: ProviderAdapter[],\n private readonly defaultProvider: string,\n ) {}\n\n /**\n * Generate images from a text prompt.\n *\n * @param options - Image generation options\n * @returns Promise resolving to the generation result with images and cost\n * @throws Error if the provider doesn't support image generation\n */\n async generate(options: ImageGenerationOptions): Promise<ImageGenerationResult> {\n const modelId = options.model;\n\n // Find an adapter that supports this image model\n const adapter = this.findImageAdapter(modelId);\n if (!adapter || !adapter.generateImage) {\n throw new Error(\n `No provider supports image generation for model \"${modelId}\". ` +\n `Available image models: ${this.listModels()\n .map((m) => m.modelId)\n .join(\", \")}`,\n );\n }\n\n return adapter.generateImage(options);\n }\n\n /**\n * List all available image generation models.\n */\n listModels(): ImageModelSpec[] {\n const models: ImageModelSpec[] = [];\n for (const adapter of this.adapters) {\n if (adapter.getImageModelSpecs) {\n models.push(...adapter.getImageModelSpecs());\n }\n }\n return models;\n }\n\n /**\n * Check if a model is supported for image generation.\n */\n supportsModel(modelId: string): boolean {\n return this.findImageAdapter(modelId) !== undefined;\n }\n\n private findImageAdapter(modelId: string): ProviderAdapter | undefined {\n return this.adapters.find((adapter) => adapter.supportsImageGeneration?.(modelId) ?? false);\n }\n}\n","/**\n * Speech Generation Namespace\n *\n * Provides text-to-speech generation methods.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * const result = await llmist.speech.generate({\n * model: \"tts-1-hd\",\n * input: \"Hello, world!\",\n * voice: \"nova\",\n * });\n *\n * // Save the audio\n * fs.writeFileSync(\"output.mp3\", Buffer.from(result.audio));\n * console.log(\"Cost:\", result.cost);\n * ```\n */\n\nimport type { ProviderAdapter } from \"../../providers/provider.js\";\nimport type {\n SpeechGenerationOptions,\n SpeechGenerationResult,\n SpeechModelSpec,\n} from \"../media-types.js\";\n\nexport class SpeechNamespace {\n constructor(\n private readonly adapters: ProviderAdapter[],\n private readonly defaultProvider: string,\n ) {}\n\n /**\n * Generate speech audio from text.\n *\n * @param options - Speech generation options\n * @returns Promise resolving to the generation result with audio and cost\n * @throws Error if the provider doesn't support speech generation\n */\n async generate(options: SpeechGenerationOptions): Promise<SpeechGenerationResult> {\n const modelId = options.model;\n\n // Find an adapter that supports this speech model\n const adapter = this.findSpeechAdapter(modelId);\n if (!adapter || !adapter.generateSpeech) {\n throw new Error(\n `No provider supports speech generation for model \"${modelId}\". ` +\n `Available speech models: ${this.listModels()\n .map((m) => m.modelId)\n .join(\", \")}`,\n );\n }\n\n return adapter.generateSpeech(options);\n }\n\n /**\n * List all available speech generation models.\n */\n listModels(): SpeechModelSpec[] {\n const models: SpeechModelSpec[] = [];\n for (const adapter of this.adapters) {\n if (adapter.getSpeechModelSpecs) {\n models.push(...adapter.getSpeechModelSpecs());\n }\n }\n return models;\n }\n\n /**\n * Check if a model is supported for speech generation.\n */\n supportsModel(modelId: string): boolean {\n return this.findSpeechAdapter(modelId) !== undefined;\n }\n\n private findSpeechAdapter(modelId: string): ProviderAdapter | undefined {\n return this.adapters.find((adapter) => adapter.supportsSpeechGeneration?.(modelId) ?? false);\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 text generation methods (complete/stream).\n */\nexport interface TextGenerationOptions {\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: TextGenerationOptions = {},\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: TextGenerationOptions = {},\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","/**\n * Text Generation Namespace\n *\n * Provides text completion and streaming methods.\n * Replaces the deprecated llmist.complete() and llmist.stream() methods.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * // Complete\n * const answer = await llmist.text.complete(\"What is 2+2?\");\n *\n * // Stream\n * for await (const chunk of llmist.text.stream(\"Tell me a story\")) {\n * process.stdout.write(chunk);\n * }\n * ```\n */\n\nimport type { LLMist } from \"../client.js\";\nimport { complete, type TextGenerationOptions, stream } from \"../quick-methods.js\";\n\nexport class TextNamespace {\n constructor(private readonly client: LLMist) {}\n\n /**\n * Generate a complete text response.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Complete text response\n */\n async complete(prompt: string, options?: TextGenerationOptions): Promise<string> {\n return complete(this.client, prompt, options);\n }\n\n /**\n * Stream text chunks.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Async generator yielding text chunks\n */\n stream(prompt: string, options?: TextGenerationOptions): AsyncGenerator<string> {\n return stream(this.client, prompt, options);\n }\n}\n","/**\n * Vision Analysis Namespace\n *\n * Provides one-shot image analysis without agent setup.\n * Useful for quick image understanding tasks.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * const description = await llmist.vision.analyze({\n * model: \"gpt-4o\",\n * image: await readFile(\"photo.jpg\"),\n * prompt: \"Describe this image in detail\",\n * });\n *\n * console.log(description);\n * ```\n */\n\nimport type { LLMist } from \"../client.js\";\nimport type { ImageMimeType } from \"../input-content.js\";\nimport {\n detectImageMimeType,\n imageFromBuffer,\n imageFromUrl,\n isDataUrl,\n parseDataUrl,\n text,\n} from \"../input-content.js\";\nimport { LLMMessageBuilder } from \"../messages.js\";\n\n/**\n * Options for vision analysis.\n */\nexport interface VisionAnalyzeOptions {\n /** Model to use (must support vision, e.g., \"gpt-4o\", \"claude-sonnet-4-20250514\", \"gemini-2.5-flash\") */\n model: string;\n\n /** Image data: Buffer, Uint8Array, base64 string, data URL, or HTTPS URL */\n image: string | Buffer | Uint8Array;\n\n /** Analysis prompt describing what to do with the image */\n prompt: string;\n\n /** MIME type (auto-detected if not provided for Buffer/Uint8Array) */\n mimeType?: ImageMimeType;\n\n /** System prompt for analysis context */\n systemPrompt?: string;\n\n /** Max tokens for response */\n maxTokens?: number;\n\n /** Temperature (0-1) */\n temperature?: number;\n}\n\n/**\n * Result of vision analysis.\n */\nexport interface VisionAnalyzeResult {\n /** The analysis text */\n text: string;\n\n /** Model used */\n model: string;\n\n /** Token usage if available */\n usage?: {\n inputTokens: number;\n outputTokens: number;\n totalTokens: number;\n };\n}\n\nexport class VisionNamespace {\n constructor(private readonly client: LLMist) {}\n\n /**\n * Build a message builder with the image content attached.\n * Handles URLs, data URLs, base64 strings, and binary buffers.\n */\n private buildImageMessage(options: VisionAnalyzeOptions): LLMMessageBuilder {\n const builder = new LLMMessageBuilder();\n\n if (options.systemPrompt) {\n builder.addSystem(options.systemPrompt);\n }\n\n // Handle different image source types\n if (typeof options.image === \"string\") {\n if (options.image.startsWith(\"http://\") || options.image.startsWith(\"https://\")) {\n // URL - only supported by OpenAI\n builder.addUserWithImageUrl(options.prompt, options.image);\n } else if (isDataUrl(options.image)) {\n // Data URL - parse and use\n const parsed = parseDataUrl(options.image);\n if (!parsed) {\n throw new Error(\"Invalid data URL format\");\n }\n builder.addUserWithImage(options.prompt, parsed.data, parsed.mimeType as ImageMimeType);\n } else {\n // Assume base64 string\n const buffer = Buffer.from(options.image, \"base64\");\n builder.addUserWithImage(options.prompt, buffer, options.mimeType);\n }\n } else {\n // Buffer or Uint8Array\n builder.addUserWithImage(options.prompt, options.image, options.mimeType);\n }\n\n return builder;\n }\n\n /**\n * Stream the response and collect text and usage information.\n */\n private async streamAndCollect(\n options: VisionAnalyzeOptions,\n builder: LLMMessageBuilder,\n ): Promise<{ text: string; usage?: VisionAnalyzeResult[\"usage\"] }> {\n let response = \"\";\n let finalUsage: VisionAnalyzeResult[\"usage\"] | undefined;\n\n for await (const chunk of this.client.stream({\n model: options.model,\n messages: builder.build(),\n maxTokens: options.maxTokens,\n temperature: options.temperature,\n })) {\n response += chunk.text;\n if (chunk.usage) {\n finalUsage = {\n inputTokens: chunk.usage.inputTokens,\n outputTokens: chunk.usage.outputTokens,\n totalTokens: chunk.usage.totalTokens,\n };\n }\n }\n\n return { text: response.trim(), usage: finalUsage };\n }\n\n /**\n * Analyze an image with a vision-capable model.\n * Returns the analysis as a string.\n *\n * @param options - Vision analysis options\n * @returns Promise resolving to the analysis text\n * @throws Error if the image format is unsupported or model doesn't support vision\n *\n * @example\n * ```typescript\n * // From file\n * const result = await llmist.vision.analyze({\n * model: \"gpt-4o\",\n * image: await fs.readFile(\"photo.jpg\"),\n * prompt: \"What's in this image?\",\n * });\n *\n * // From URL (OpenAI only)\n * const result = await llmist.vision.analyze({\n * model: \"gpt-4o\",\n * image: \"https://example.com/image.jpg\",\n * prompt: \"Describe this image\",\n * });\n * ```\n */\n async analyze(options: VisionAnalyzeOptions): Promise<string> {\n const builder = this.buildImageMessage(options);\n const { text } = await this.streamAndCollect(options, builder);\n return text;\n }\n\n /**\n * Analyze an image and return detailed result with usage info.\n *\n * @param options - Vision analysis options\n * @returns Promise resolving to the analysis result with usage info\n */\n async analyzeWithUsage(options: VisionAnalyzeOptions): Promise<VisionAnalyzeResult> {\n const builder = this.buildImageMessage(options);\n const { text, usage } = await this.streamAndCollect(options, builder);\n\n return {\n text,\n model: options.model,\n usage,\n };\n }\n\n /**\n * Check if a model supports vision/image input.\n *\n * @param modelId - Model ID to check\n * @returns True if the model supports vision\n */\n supportsModel(modelId: string): boolean {\n const spec = this.client.modelRegistry.getModelSpec(modelId);\n return spec?.features?.vision === true;\n }\n\n /**\n * List all models that support vision.\n *\n * @returns Array of model IDs that support vision\n */\n listModels(): string[] {\n return this.client.modelRegistry\n .listModels()\n .filter((spec) => spec.features?.vision === true)\n .map((spec) => spec.modelId);\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","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 { ImageNamespace } from \"./namespaces/image.js\";\nimport { SpeechNamespace } from \"./namespaces/speech.js\";\nimport { TextNamespace } from \"./namespaces/text.js\";\nimport { VisionNamespace } from \"./namespaces/vision.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"./options.js\";\nimport { ModelIdentifierParser } from \"./options.js\";\nimport {\n complete as completeHelper,\n type TextGenerationOptions,\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 private readonly defaultProvider: string;\n readonly modelRegistry: ModelRegistry;\n private readonly adapters: ProviderAdapter[];\n\n // Namespaces for different generation types\n readonly text: TextNamespace;\n readonly image: ImageNamespace;\n readonly speech: SpeechNamespace;\n readonly vision: VisionNamespace;\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.defaultProvider = resolvedDefaultProvider;\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 // Initialize generation namespaces\n this.text = new TextNamespace(this);\n this.image = new ImageNamespace(this.adapters, this.defaultProvider);\n this.speech = new SpeechNamespace(this.adapters, this.defaultProvider);\n this.vision = new VisionNamespace(this);\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?: TextGenerationOptions): 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?: TextGenerationOptions): 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?: TextGenerationOptions): 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?: TextGenerationOptions): 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","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(schema: ZodTypeAny): 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\") 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 ? new SchemaIntrospector(options.schema) : 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(value: string, expectedType?: TypeHint): 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","/**\n * LLMist client wrapper that automatically reports LLM costs via callback.\n *\n * Used internally by ExecutionContext to provide ctx.llmist for gadgets.\n * All LLM calls made through this wrapper will have their costs automatically\n * tracked and reported via the provided callback.\n *\n * @module gadgets/cost-reporting-client\n */\n\nimport type { LLMist } from \"../core/client.js\";\nimport type {\n ImageGenerationOptions,\n ImageGenerationResult,\n SpeechGenerationOptions,\n SpeechGenerationResult,\n} from \"../core/media-types.js\";\nimport type { ModelRegistry } from \"../core/model-registry.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { LLMGenerationOptions, LLMStream, LLMStreamChunk } from \"../core/options.js\";\nimport type { TextGenerationOptions } from \"../core/quick-methods.js\";\nimport type {\n CostReportingImageNamespace,\n CostReportingLLMist,\n CostReportingSpeechNamespace,\n} from \"./types.js\";\n\n/**\n * Callback type for reporting costs.\n */\nexport type CostReporter = (amount: number) => void;\n\n/**\n * LLMist client wrapper that automatically reports LLM costs.\n *\n * This wrapper intercepts all LLM calls, tracks token usage from responses,\n * calculates costs using ModelRegistry, and reports them via the callback.\n *\n * @example\n * ```typescript\n * let totalCost = 0;\n * const wrapper = new CostReportingLLMistWrapper(client, (cost) => {\n * totalCost += cost;\n * });\n *\n * // LLM cost automatically reported after completion\n * const result = await wrapper.complete(\"Hello\");\n * console.log(`Cost: $${totalCost}`);\n * ```\n */\nexport class CostReportingLLMistWrapper implements CostReportingLLMist {\n readonly image: CostReportingImageNamespace;\n readonly speech: CostReportingSpeechNamespace;\n\n constructor(\n private readonly client: LLMist,\n private readonly reportCost: CostReporter,\n ) {\n // Initialize image namespace with cost reporting\n this.image = {\n generate: async (options: ImageGenerationOptions): Promise<ImageGenerationResult> => {\n const result = await this.client.image.generate(options);\n // Report cost if available in the result\n if (result.cost !== undefined && result.cost > 0) {\n this.reportCost(result.cost);\n }\n return result;\n },\n };\n\n // Initialize speech namespace with cost reporting\n this.speech = {\n generate: async (options: SpeechGenerationOptions): Promise<SpeechGenerationResult> => {\n const result = await this.client.speech.generate(options);\n // Report cost if available in the result\n if (result.cost !== undefined && result.cost > 0) {\n this.reportCost(result.cost);\n }\n return result;\n },\n };\n }\n\n /**\n * Access to model registry for cost estimation.\n */\n get modelRegistry(): ModelRegistry {\n return this.client.modelRegistry;\n }\n\n /**\n * Quick completion with automatic cost reporting.\n *\n * Streams internally to track token usage, then reports the calculated cost.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration (model, temperature, etc.)\n * @returns Complete text response\n */\n async complete(prompt: string, options?: TextGenerationOptions): Promise<string> {\n const model = resolveModel(options?.model ?? \"haiku\");\n let result = \"\";\n let inputTokens = 0;\n let outputTokens = 0;\n let cachedInputTokens = 0;\n let cacheCreationInputTokens = 0;\n\n const messages = [\n ...(options?.systemPrompt\n ? [{ role: \"system\" as const, content: options.systemPrompt }]\n : []),\n { role: \"user\" as const, content: prompt },\n ];\n\n for await (const chunk of this.client.stream({\n model,\n messages,\n temperature: options?.temperature,\n maxTokens: options?.maxTokens,\n })) {\n result += chunk.text ?? \"\";\n if (chunk.usage) {\n inputTokens = chunk.usage.inputTokens;\n outputTokens = chunk.usage.outputTokens;\n cachedInputTokens = chunk.usage.cachedInputTokens ?? 0;\n cacheCreationInputTokens = chunk.usage.cacheCreationInputTokens ?? 0;\n }\n }\n\n this.reportCostFromUsage(\n model,\n inputTokens,\n outputTokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n );\n return result;\n }\n\n /**\n * Quick streaming with automatic cost reporting when stream completes.\n *\n * Yields text chunks as they arrive, then reports cost in finally block.\n *\n * @param prompt - User prompt\n * @param options - Optional configuration (model, temperature, etc.)\n * @returns Async generator yielding text chunks\n */\n async *streamText(prompt: string, options?: TextGenerationOptions): AsyncGenerator<string> {\n const model = resolveModel(options?.model ?? \"haiku\");\n let inputTokens = 0;\n let outputTokens = 0;\n let cachedInputTokens = 0;\n let cacheCreationInputTokens = 0;\n\n const messages = [\n ...(options?.systemPrompt\n ? [{ role: \"system\" as const, content: options.systemPrompt }]\n : []),\n { role: \"user\" as const, content: prompt },\n ];\n\n try {\n for await (const chunk of this.client.stream({\n model,\n messages,\n temperature: options?.temperature,\n maxTokens: options?.maxTokens,\n })) {\n if (chunk.text) {\n yield chunk.text;\n }\n if (chunk.usage) {\n inputTokens = chunk.usage.inputTokens;\n outputTokens = chunk.usage.outputTokens;\n cachedInputTokens = chunk.usage.cachedInputTokens ?? 0;\n cacheCreationInputTokens = chunk.usage.cacheCreationInputTokens ?? 0;\n }\n }\n } finally {\n // Report cost when stream ends (success or early exit)\n this.reportCostFromUsage(\n model,\n inputTokens,\n outputTokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n );\n }\n }\n\n /**\n * Low-level stream access with automatic cost reporting.\n *\n * Returns a wrapped stream that reports costs when iteration completes.\n *\n * @param options - Full LLM generation options\n * @returns Wrapped LLM stream that auto-reports costs\n */\n stream(options: LLMGenerationOptions): LLMStream {\n return this.createCostReportingStream(options);\n }\n\n /**\n * Creates a wrapped stream that tracks usage and reports costs on completion.\n */\n private createCostReportingStream(options: LLMGenerationOptions): LLMStream {\n const innerStream = this.client.stream(options);\n const reportCostFromUsage = this.reportCostFromUsage.bind(this);\n const model = options.model;\n\n async function* costReportingWrapper(): AsyncGenerator<LLMStreamChunk> {\n let inputTokens = 0;\n let outputTokens = 0;\n let cachedInputTokens = 0;\n let cacheCreationInputTokens = 0;\n\n try {\n for await (const chunk of innerStream) {\n if (chunk.usage) {\n inputTokens = chunk.usage.inputTokens;\n outputTokens = chunk.usage.outputTokens;\n cachedInputTokens = chunk.usage.cachedInputTokens ?? 0;\n cacheCreationInputTokens = chunk.usage.cacheCreationInputTokens ?? 0;\n }\n yield chunk;\n }\n } finally {\n // Report cost when stream completes (success or early exit)\n if (inputTokens > 0 || outputTokens > 0) {\n reportCostFromUsage(\n model,\n inputTokens,\n outputTokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n );\n }\n }\n }\n\n return costReportingWrapper();\n }\n\n /**\n * Calculates and reports cost from token usage.\n */\n private reportCostFromUsage(\n model: string,\n inputTokens: number,\n outputTokens: number,\n cachedInputTokens = 0,\n cacheCreationInputTokens = 0,\n ): void {\n if (inputTokens === 0 && outputTokens === 0) return;\n\n // Model registry now handles provider-prefixed model IDs internally\n const estimate = this.client.modelRegistry.estimateCost(\n model,\n inputTokens,\n outputTokens,\n cachedInputTokens,\n cacheCreationInputTokens,\n );\n\n if (estimate && estimate.totalCost > 0) {\n this.reportCost(estimate.totalCost);\n }\n }\n}\n","import type { ZodError } from \"zod\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { AbstractGadget } 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 execution errors with helpful context for LLM self-correction.\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 GadgetExecutionErrorFormatter {\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: AbstractGadget): 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: AbstractGadget | 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 GadgetExecutionErrorFormatter instance\n */\nexport function createErrorFormatter(\n options: ErrorFormatterOptions = {},\n): GadgetExecutionErrorFormatter {\n return new GadgetExecutionErrorFormatter(options);\n}\n","import { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport { parseBlockParams } from \"./block-params.js\";\nimport type { StreamEvent } from \"./types.js\";\n\nexport type ParameterFormat = \"block\";\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\n/**\n * Parser for extracting gadget invocations from LLM text output.\n * Processes text chunks incrementally and emits events for text and gadget calls.\n */\nexport class GadgetCallParser {\n private buffer = \"\";\n private lastEmittedTextOffset = 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 /**\n * Extract and consume text up to the given index.\n * Returns undefined if no meaningful text to emit.\n */\n private extractTextSegment(index: number): string | undefined {\n if (index <= this.lastEmittedTextOffset) {\n return undefined;\n }\n\n const segment = this.buffer.slice(this.lastEmittedTextOffset, index);\n this.lastEmittedTextOffset = index;\n\n return segment.trim().length > 0 ? segment : undefined;\n }\n\n /**\n * Parse gadget invocation metadata from the header line.\n *\n * Supported formats:\n * - `GadgetName` - Auto-generate ID, no dependencies\n * - `GadgetName:my_id` - Explicit ID, no dependencies\n * - `GadgetName:my_id:dep1,dep2` - Explicit ID with dependencies\n *\n * Dependencies must be comma-separated invocation IDs.\n */\n private parseInvocationMetadata(headerLine: string): {\n gadgetName: string;\n invocationId: string;\n dependencies: string[];\n } {\n const parts = headerLine.split(\":\");\n\n if (parts.length === 1) {\n // Just name: GadgetName\n return {\n gadgetName: parts[0],\n invocationId: `gadget_${++globalInvocationCounter}`,\n dependencies: [],\n };\n } else if (parts.length === 2) {\n // Name + ID: GadgetName:calc_1\n return {\n gadgetName: parts[0],\n invocationId: parts[1].trim(),\n dependencies: [],\n };\n } else {\n // Name + ID + deps: GadgetName:calc_1:dep1,dep2\n const deps = parts[2]\n .split(\",\")\n .map((d) => d.trim())\n .filter((d) => d.length > 0);\n return {\n gadgetName: parts[0],\n invocationId: parts[1].trim(),\n dependencies: deps,\n };\n }\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.extractTextSegment(partStartIndex);\n if (textBefore !== undefined) {\n yield { type: \"text\", content: textBefore };\n }\n\n // Extract gadget metadata from header line\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 headerLine = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n const { gadgetName, invocationId, dependencies } = this.parseInvocationMetadata(headerLine);\n\n const contentStartIndex = metadataEndIndex + 1;\n\n let partEndIndex: number;\n let endMarkerLength = 0;\n\n // 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 end marker\n const endPos = this.buffer.indexOf(this.endPrefix, contentStartIndex);\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 && (endPos === -1 || nextStartPos < endPos)) {\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 (endPos !== -1) {\n // Found proper end marker\n partEndIndex = endPos;\n endMarkerLength = this.endPrefix.length;\n } else {\n // Neither end marker nor next start found - wait for more data\n break;\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,\n invocationId,\n parametersRaw,\n parameters,\n parseError,\n dependencies,\n },\n };\n\n // Move past this gadget\n startIndex = partEndIndex + endMarkerLength;\n\n this.lastEmittedTextOffset = startIndex;\n }\n\n // Keep unprocessed data in buffer\n if (startIndex > 0) {\n this.buffer = this.buffer.substring(startIndex);\n this.lastEmittedTextOffset = 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.lastEmittedTextOffset);\n\n if (startIndex !== -1) {\n // There's an incomplete gadget - try to parse it\n const textBefore = this.extractTextSegment(startIndex);\n if (textBefore !== undefined) {\n yield { type: \"text\", content: textBefore };\n }\n\n // Extract gadget metadata from header line\n const metadataStartIndex = startIndex + this.startPrefix.length;\n const metadataEndIndex = this.buffer.indexOf(\"\\n\", metadataStartIndex);\n\n if (metadataEndIndex !== -1) {\n const headerLine = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n const { gadgetName, invocationId, dependencies } = this.parseInvocationMetadata(headerLine);\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,\n invocationId,\n parametersRaw: parametersRaw,\n parameters,\n parseError,\n dependencies,\n },\n };\n\n return;\n }\n }\n\n // No incomplete gadget - just emit remaining text\n const remainingText = this.extractTextSegment(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.lastEmittedTextOffset = 0;\n }\n}\n\n","/**\n * Type-safe gadget factory with automatic parameter inference.\n *\n * Gadget eliminates the need for manual type assertions\n * by automatically inferring parameter types from the Zod schema.\n *\n * @example\n * ```typescript\n * class Calculator extends Gadget({\n * description: \"Performs arithmetic operations\",\n * schema: z.object({\n * operation: z.enum([\"add\", \"subtract\"]),\n * a: z.number(),\n * b: z.number(),\n * }),\n * }) {\n * // ✨ params is automatically typed!\n * execute(params: this['params']): string {\n * const { operation, a, b } = params; // All typed!\n * return operation === \"add\" ? String(a + b) : String(a - b);\n * }\n * }\n * ```\n */\n\nimport type { ZodType } from \"zod\";\nimport { AbstractGadget } from \"./gadget.js\";\nimport type { ExecutionContext, GadgetExample, GadgetExecuteReturn } from \"./types.js\";\n\n/**\n * Infer the TypeScript type from a Zod schema.\n */\ntype InferSchema<T> = T extends ZodType<infer U> ? U : never;\n\n/**\n * Configuration for creating a typed gadget.\n */\nexport interface GadgetConfig<TSchema extends ZodType> {\n /** Human-readable description of what the gadget does */\n description: string;\n\n /** Zod schema for parameter validation */\n schema: TSchema;\n\n /** Optional custom name (defaults to class name) */\n name?: string;\n\n /** Optional timeout in milliseconds */\n timeoutMs?: number;\n\n /** Optional usage examples to help LLMs understand proper invocation */\n examples?: GadgetExample<InferSchema<TSchema>>[];\n}\n\n/**\n * Factory function to create a typed gadget base class.\n *\n * The returned class automatically infers parameter types from the Zod schema,\n * eliminating the need for manual type assertions in the execute method.\n *\n * @param config - Configuration with description and schema\n * @returns Base class to extend with typed execute method\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { Gadget } from 'llmist';\n *\n * class Calculator extends Gadget({\n * description: \"Performs arithmetic operations\",\n * schema: z.object({\n * operation: z.enum([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n * a: z.number().describe(\"First number\"),\n * b: z.number().describe(\"Second number\"),\n * }),\n * }) {\n * execute(params: this['params']): string {\n * // params is automatically typed as:\n * // { operation: \"add\" | \"subtract\" | \"multiply\" | \"divide\"; a: number; b: number }\n * const { operation, a, b } = params;\n *\n * switch (operation) {\n * case \"add\": return String(a + b);\n * case \"subtract\": return String(a - b);\n * case \"multiply\": return String(a * b);\n * case \"divide\": return String(a / b);\n * }\n * }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // With async execution\n * class WeatherGadget extends Gadget({\n * description: \"Fetches weather for a city\",\n * schema: z.object({\n * city: z.string().min(1).describe(\"City name\"),\n * }),\n * timeoutMs: 10000,\n * }) {\n * async execute(params: this['params']): Promise<string> {\n * const { city } = params; // Automatically typed as { city: string }\n * const weather = await fetchWeather(city);\n * return `Weather in ${city}: ${weather}`;\n * }\n * }\n * ```\n */\nexport function Gadget<TSchema extends ZodType>(config: GadgetConfig<TSchema>) {\n abstract class GadgetBase extends AbstractGadget {\n description = config.description;\n parameterSchema = config.schema;\n name = config.name;\n timeoutMs = config.timeoutMs;\n examples = config.examples;\n\n /**\n * Type helper property for accessing inferred parameter type.\n * This is used in the execute method signature: `execute(params: this['params'])`\n *\n * Note: This is just for type inference - the actual params in execute()\n * will be Record<string, unknown> which you can safely cast to this['params']\n */\n readonly params!: InferSchema<TSchema>;\n\n /**\n * Execute the gadget. Subclasses should cast params to this['params'].\n *\n * @param params - Validated parameters from the LLM\n * @param ctx - Optional execution context for cost reporting and LLM access\n * @returns Result as a string, or an object with result and optional cost\n *\n * @example\n * ```typescript\n * // Simple string return (free gadget)\n * execute(params: this['params']) {\n * return String(params.a + params.b);\n * }\n *\n * // Using context for callback-based cost reporting\n * execute(params: this['params'], ctx) {\n * ctx.reportCost(0.001);\n * return \"result\";\n * }\n *\n * // Using wrapped LLMist for automatic cost tracking\n * async execute(params: this['params'], ctx) {\n * return ctx.llmist.complete('Summarize: ' + params.text);\n * }\n * ```\n */\n abstract execute(\n params: Record<string, unknown>,\n ctx?: ExecutionContext,\n ): GadgetExecuteReturn | Promise<GadgetExecuteReturn>;\n }\n\n return GadgetBase as {\n new (): GadgetBase & { params: InferSchema<TSchema> };\n };\n}\n","import equal from \"fast-deep-equal\";\nimport type { ILogObj, Logger } from \"tslog\";\nimport { z } from \"zod\";\nimport { AgentBuilder } from \"../agent/builder.js\";\nimport { LLMist } from \"../core/client.js\";\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { ExecutionTree, type NodeId } from \"../core/execution-tree.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { parseBlockParams } from \"./block-params.js\";\nimport { CostReportingLLMistWrapper } from \"./cost-reporting-client.js\";\nimport { createGadget } from \"./create-gadget.js\";\nimport { type ErrorFormatterOptions, GadgetExecutionErrorFormatter } from \"./error-formatter.js\";\nimport {\n AbortException,\n HumanInputRequiredException,\n TaskCompletionSignal,\n TimeoutException,\n} from \"./exceptions.js\";\nimport type { MediaStore } from \"./media-store.js\";\nimport { stripMarkdownFences } from \"./parser.js\";\nimport type { GadgetRegistry } from \"./registry.js\";\nimport { Gadget } from \"./typed-gadget.js\";\nimport type {\n AgentContextConfig,\n ExecutionContext,\n GadgetExecuteResult,\n GadgetExecuteResultWithMedia,\n GadgetExecutionResult,\n GadgetMediaOutput,\n HostExports,\n ParsedGadgetCall,\n SubagentConfigMap,\n SubagentEvent,\n} from \"./types.js\";\n\n/**\n * Lazily create host exports to avoid circular dependency issues.\n * Cached after first call.\n */\nlet cachedHostExports: HostExports | undefined;\nfunction getHostExportsInternal(): HostExports {\n if (!cachedHostExports) {\n cachedHostExports = {\n AgentBuilder,\n Gadget,\n createGadget,\n ExecutionTree,\n LLMist,\n z,\n };\n }\n return cachedHostExports;\n}\n\nexport class GadgetExecutor {\n private readonly logger: Logger<ILogObj>;\n private readonly errorFormatter: GadgetExecutionErrorFormatter;\n private readonly argPrefix: string;\n\n constructor(\n private readonly registry: GadgetRegistry,\n private readonly requestHumanInput?: (question: string) => Promise<string>,\n logger?: Logger<ILogObj>,\n private readonly defaultGadgetTimeoutMs?: number,\n errorFormatterOptions?: ErrorFormatterOptions,\n private readonly client?: LLMist,\n private readonly mediaStore?: MediaStore,\n private readonly agentConfig?: AgentContextConfig,\n private readonly subagentConfig?: SubagentConfigMap,\n private readonly onSubagentEvent?: (event: SubagentEvent) => void,\n // Execution Tree context for gadget execution\n private readonly tree?: ExecutionTree,\n private readonly parentNodeId?: NodeId | null,\n private readonly baseDepth?: number,\n ) {\n this.logger = logger ?? createLogger({ name: \"llmist:executor\" });\n this.errorFormatter = new GadgetExecutionErrorFormatter(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 * Aborts the provided AbortController before rejecting, allowing gadgets to clean up.\n * Returns both the promise and a cancel function to clear the timeout when no longer needed.\n */\n private createTimeoutPromise(\n gadgetName: string,\n timeoutMs: number,\n abortController: AbortController,\n ): { promise: Promise<never>; cancel: () => void } {\n let timeoutId: ReturnType<typeof setTimeout>;\n\n const promise = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n const timeoutError = new TimeoutException(gadgetName, timeoutMs);\n // Signal abort FIRST so gadgets can clean up before exception is thrown\n // Pass the timeout message as reason for better debugging context\n abortController.abort(timeoutError.message);\n reject(timeoutError);\n }, timeoutMs);\n });\n\n return {\n promise,\n cancel: () => clearTimeout(timeoutId),\n };\n }\n\n /**\n * Unify gadget execute result to consistent internal format.\n * Handles string returns (backwards compat), object returns with cost,\n * and object returns with media.\n */\n private unifyExecuteResult(\n raw: string | GadgetExecuteResult | GadgetExecuteResultWithMedia,\n ): { result: string; media?: GadgetMediaOutput[]; cost: number } {\n if (typeof raw === \"string\") {\n return { result: raw, cost: 0 };\n }\n // Check if it has media property (GadgetExecuteResultWithMedia)\n if (\"media\" in raw && raw.media) {\n return { result: raw.result, media: raw.media, cost: raw.cost ?? 0 };\n }\n return { result: raw.result, cost: raw.cost ?? 0 };\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 = !equal(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: subagentConfig[name].timeoutMs > gadget.timeoutMs > defaultGadgetTimeoutMs > no timeout\n const subagentTimeout = this.subagentConfig?.[call.gadgetName]?.timeoutMs;\n const timeoutMs = subagentTimeout ?? gadget.timeoutMs ?? this.defaultGadgetTimeoutMs;\n\n // Create AbortController for cancellation support\n // Signal is always provided to gadgets, even without timeout\n const abortController = new AbortController();\n\n // Create execution context with cost accumulator and abort signal\n let callbackCost = 0;\n const reportCost = (amount: number) => {\n if (amount > 0) {\n callbackCost += amount;\n this.logger.debug(\"Gadget reported cost via callback\", {\n gadgetName: call.gadgetName,\n amount,\n totalCallbackCost: callbackCost,\n });\n }\n };\n\n // Build execution context with abort signal, agent config, and tree access\n // Look up the gadget's own node ID from the tree (not the parent LLM call's ID)\n const gadgetNodeId = this.tree?.getNodeByInvocationId(call.invocationId)?.id;\n const gadgetDepth = gadgetNodeId\n ? this.tree?.getNode(gadgetNodeId)?.depth ?? this.baseDepth\n : this.baseDepth;\n\n const ctx: ExecutionContext = {\n reportCost,\n llmist: this.client ? new CostReportingLLMistWrapper(this.client, reportCost) : undefined,\n signal: abortController.signal,\n agentConfig: this.agentConfig,\n subagentConfig: this.subagentConfig,\n invocationId: call.invocationId,\n onSubagentEvent: this.onSubagentEvent,\n // Tree context for subagent support - use gadget's own node ID\n tree: this.tree,\n nodeId: gadgetNodeId,\n depth: gadgetDepth,\n // Host exports for external gadgets to use host's llmist classes\n hostExports: getHostExportsInternal(),\n // Logger for structured logging (respects CLI's log level/file config)\n logger: this.logger,\n // Human input callback for subagents to bubble up input requests\n requestHumanInput: this.requestHumanInput,\n };\n\n // Execute gadget (handle both sync and async)\n let rawResult: string | GadgetExecuteResult;\n if (timeoutMs && timeoutMs > 0) {\n // Execute with timeout - abort signal will be triggered before timeout rejection\n this.logger.debug(\"Executing gadget with timeout\", {\n gadgetName: call.gadgetName,\n timeoutMs,\n });\n const timeout = this.createTimeoutPromise(call.gadgetName, timeoutMs, abortController);\n try {\n rawResult = await Promise.race([\n Promise.resolve(gadget.execute(validatedParameters, ctx)),\n timeout.promise,\n ]);\n } finally {\n // Always cancel the timeout to prevent it from keeping the event loop alive\n timeout.cancel();\n }\n } else {\n // Execute without timeout\n rawResult = await Promise.resolve(gadget.execute(validatedParameters, ctx));\n }\n\n // Normalize result: handle string returns (legacy), object returns with cost, and media\n const { result, media, cost: returnCost } = this.unifyExecuteResult(rawResult);\n\n // Sum callback costs + return costs\n const totalCost = callbackCost + returnCost;\n\n // Store media in MediaStore if present\n let mediaIds: string[] | undefined;\n let storedMedia: import(\"./types.js\").StoredMedia[] | undefined;\n if (media && media.length > 0 && this.mediaStore) {\n storedMedia = await Promise.all(\n media.map((item) => this.mediaStore!.store(item, call.gadgetName)),\n );\n mediaIds = storedMedia.map((m) => m.id);\n this.logger.debug(\"Stored media outputs\", {\n gadgetName: call.gadgetName,\n mediaIds,\n count: media.length,\n });\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 cost: totalCost > 0 ? totalCost : undefined,\n callbackCost: callbackCost > 0 ? callbackCost : undefined,\n returnCost: returnCost > 0 ? returnCost : undefined,\n mediaCount: media?.length,\n });\n\n this.logger.debug(\"Gadget result\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result,\n cost: totalCost,\n executionTimeMs,\n mediaIds,\n });\n\n return {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: validatedParameters,\n result,\n executionTimeMs,\n cost: totalCost,\n media,\n mediaIds,\n storedMedia,\n };\n } catch (error) {\n // Check if this is a TaskCompletionSignal\n if (error instanceof TaskCompletionSignal) {\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 an AbortException (thrown by gadgets when they detect abort signal)\n if (error instanceof AbortException) {\n this.logger.info(\"Gadget execution was aborted\", {\n gadgetName: call.gadgetName,\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 HumanInputRequiredException using duck typing\n // (handles module duplication issues in monorepos)\n const isHumanInputError =\n error instanceof Error &&\n error.name === \"HumanInputRequiredException\" &&\n \"question\" in error;\n if (isHumanInputError) {\n const question = (error as HumanInputRequiredException).question;\n this.logger.info(\"Gadget requested human input\", {\n gadgetName: call.gadgetName,\n question,\n });\n\n // If callback is provided, call it and wait for answer\n if (this.requestHumanInput) {\n try {\n const answer = await this.requestHumanInput(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","/**\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 { LLMist } from \"../core/client.js\";\nimport type { ExecutionTree, NodeId } from \"../core/execution-tree.js\";\nimport type { LLMStreamChunk, TokenUsage } from \"../core/options.js\";\nimport { GadgetExecutor } from \"../gadgets/executor.js\";\nimport type { MediaStore } from \"../gadgets/media-store.js\";\nimport { GadgetCallParser } from \"../gadgets/parser.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type {\n AgentContextConfig,\n GadgetExecutionResult,\n GadgetSkippedEvent,\n ParsedGadgetCall,\n StreamCompletionEvent,\n StreamEvent,\n SubagentConfigMap,\n SubagentEvent,\n} 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 DependencySkipAction,\n DependencySkipControllerContext,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetSkippedContext,\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 requesting human input during execution */\n requestHumanInput?: (question: string) => Promise<string>;\n\n /** Default gadget timeout */\n defaultGadgetTimeoutMs?: number;\n\n /** LLMist client for ExecutionContext.llmist */\n client?: LLMist;\n\n /** MediaStore for storing gadget media outputs */\n mediaStore?: MediaStore;\n\n /** Parent agent configuration for subagents to inherit */\n agentConfig?: AgentContextConfig;\n\n /** Subagent-specific configuration overrides */\n subagentConfig?: SubagentConfigMap;\n\n /** Callback for subagent gadgets to report subagent events to parent */\n onSubagentEvent?: (event: SubagentEvent) => void;\n\n // ==========================================================================\n // Execution Tree Context (for tree-based tracking)\n // ==========================================================================\n\n /** Execution tree for tracking LLM calls and gadget executions */\n tree?: ExecutionTree;\n\n /** Parent node ID (for gadget nodes created by this processor) */\n parentNodeId?: NodeId | null;\n\n /** Base depth for nodes created by this processor */\n baseDepth?: number;\n\n // ==========================================================================\n // Cross-Iteration Dependency Resolution\n // ==========================================================================\n\n /**\n * Set of invocation IDs that completed in previous iterations.\n * Used to resolve dependencies on gadgets from prior LLM responses.\n */\n priorCompletedInvocations?: Set<string>;\n\n /**\n * Set of invocation IDs that failed in previous iterations.\n * Used to skip gadgets that depend on previously-failed gadgets.\n */\n priorFailedInvocations?: Set<string>;\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: GadgetCallParser;\n private readonly executor: GadgetExecutor;\n\n // Execution Tree context\n private readonly tree?: ExecutionTree;\n private readonly parentNodeId: NodeId | null;\n private readonly baseDepth: number;\n\n private responseText = \"\";\n private observerFailureCount = 0;\n\n // Dependency tracking for gadget execution DAG\n /** Gadgets waiting for their dependencies to complete */\n private gadgetsAwaitingDependencies: Map<string, ParsedGadgetCall> = new Map();\n /** Completed gadget results, keyed by invocation ID */\n private completedResults: Map<string, GadgetExecutionResult> = new Map();\n /** Invocation IDs of gadgets that have failed (error or skipped due to dependency) */\n private failedInvocations: Set<string> = new Set();\n /** Promises for independent gadgets currently executing (fire-and-forget) */\n private inFlightExecutions: Map<string, Promise<void>> = new Map();\n /** Queue of completed gadget results ready to be yielded (for real-time streaming) */\n private completedResultsQueue: StreamEvent[] = [];\n\n // Concurrency limiting\n /** Subagent configuration map for checking maxConcurrent limits */\n private readonly subagentConfig?: SubagentConfigMap;\n /** Track active execution count per gadget name */\n private activeCountByGadget: Map<string, number> = new Map();\n /** Queue of gadgets waiting for a concurrency slot (per gadget name) */\n private concurrencyQueue: Map<string, ParsedGadgetCall[]> = new Map();\n\n // Cross-iteration dependency tracking\n /** Invocation IDs completed in previous iterations (read-only reference from Agent) */\n private readonly priorCompletedInvocations: Set<string>;\n /** Invocation IDs that failed in previous iterations (read-only reference from Agent) */\n private readonly priorFailedInvocations: Set<string>;\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\n // Initialize tree context\n this.tree = options.tree;\n this.parentNodeId = options.parentNodeId ?? null;\n this.baseDepth = options.baseDepth ?? 0;\n\n // Initialize cross-iteration dependency tracking (use empty sets if not provided)\n this.priorCompletedInvocations = options.priorCompletedInvocations ?? new Set();\n this.priorFailedInvocations = options.priorFailedInvocations ?? new Set();\n\n // Store subagent config for concurrency limiting\n this.subagentConfig = options.subagentConfig;\n\n this.parser = new GadgetCallParser({\n startPrefix: options.gadgetStartPrefix,\n endPrefix: options.gadgetEndPrefix,\n argPrefix: options.gadgetArgPrefix,\n });\n\n // Wrap onSubagentEvent to also push to completedResultsQueue for real-time streaming\n // during parallel gadget execution. This ensures subagent events are yielded\n // while waiting for gadgets to complete, not batched at the end.\n const wrappedOnSubagentEvent = options.onSubagentEvent\n ? (event: SubagentEvent) => {\n // Push to queue for real-time streaming during parallel execution\n this.completedResultsQueue.push({\n type: \"subagent_event\",\n subagentEvent: event,\n });\n // Also call the original callback (for Agent's queue and hooks)\n options.onSubagentEvent?.(event);\n }\n : undefined;\n\n this.executor = new GadgetExecutor(\n options.registry,\n options.requestHumanInput,\n this.logger.getSubLogger({ name: \"executor\" }),\n options.defaultGadgetTimeoutMs,\n { argPrefix: options.gadgetArgPrefix },\n options.client,\n options.mediaStore,\n options.agentConfig,\n options.subagentConfig,\n wrappedOnSubagentEvent,\n // Tree context for gadget execution\n options.tree,\n options.parentNodeId,\n options.baseDepth,\n );\n }\n\n /**\n * Process an LLM stream and yield events in real-time.\n *\n * This is an async generator that yields events immediately as they occur:\n * - Text events are yielded as text is streamed from the LLM\n * - gadget_call events are yielded immediately when a gadget call is parsed\n * - gadget_result events are yielded when gadget execution completes\n *\n * The final event is always a StreamCompletionEvent containing metadata.\n */\n async *process(stream: AsyncIterable<LLMStreamChunk>): AsyncGenerator<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.responseText,\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.responseText += 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.responseText,\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 - yield immediately\n for (const event of this.parser.feed(processedChunk)) {\n for await (const processedEvent of this.processEventGenerator(event)) {\n yield processedEvent;\n\n // Track gadget execution\n if (processedEvent.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (processedEvent.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n }\n\n // Step 4: Drain completed parallel gadget results (real-time streaming)\n // This yields results from gadgets that completed during this chunk processing\n for (const evt of this.drainCompletedResults()) {\n yield evt;\n\n if (evt.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n }\n\n // Finalize parsing\n for (const event of this.parser.finalize()) {\n for await (const processedEvent of this.processEventGenerator(event)) {\n yield processedEvent;\n\n if (processedEvent.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (processedEvent.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n }\n\n // Wait for all in-flight parallel gadgets to complete, yielding events in real-time\n // This enables subagent events to be displayed during long-running gadget execution\n for await (const evt of this.waitForInFlightExecutions()) {\n yield evt;\n\n if (evt.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n\n // Drain any remaining completed results (stragglers that finished after final poll)\n for (const evt of this.drainCompletedResults()) {\n yield evt;\n\n if (evt.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n\n // Final pass to process any remaining pending gadgets\n // This handles cases where the last gadgets in the stream have dependencies\n // (now that in-flight gadgets have completed, their dependents can execute)\n for await (const evt of this.processPendingGadgetsGenerator()) {\n yield evt;\n\n if (evt.type === \"gadget_result\") {\n didExecuteGadgets = true;\n if (evt.result.breaksLoop) {\n shouldBreakLoop = true;\n }\n }\n }\n\n // Step 4: Interceptor - Transform final message\n let finalMessage = this.responseText;\n if (this.hooks.interceptors?.interceptAssistantMessage) {\n const context: MessageInterceptorContext = {\n iteration: this.iteration,\n rawResponse: this.responseText,\n logger: this.logger,\n };\n finalMessage = this.hooks.interceptors.interceptAssistantMessage(finalMessage, context);\n }\n\n // Yield completion event with all metadata\n const completionEvent: StreamCompletionEvent = {\n type: \"stream_complete\",\n shouldBreakLoop,\n didExecuteGadgets,\n finishReason,\n usage,\n rawResponse: this.responseText,\n finalMessage,\n };\n yield completionEvent;\n }\n\n /**\n * Process a single parsed event, yielding events in real-time.\n */\n private async *processEventGenerator(event: StreamEvent): AsyncGenerator<StreamEvent> {\n if (event.type === \"text\") {\n // processTextEvent is async - need to await the result before iterating\n for (const e of await this.processTextEvent(event)) {\n yield e;\n }\n } else if (event.type === \"gadget_call\") {\n for await (const e of this.processGadgetCallGenerator(event.call)) {\n yield e;\n }\n } else {\n yield event;\n }\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.responseText,\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, yielding events in real-time.\n *\n * Yields gadget_call event IMMEDIATELY when parsed (before execution),\n * enabling real-time UI feedback.\n */\n private async *processGadgetCallGenerator(call: ParsedGadgetCall): AsyncGenerator<StreamEvent> {\n // Yield gadget_call IMMEDIATELY (real-time feedback before execution)\n yield { type: \"gadget_call\", call };\n\n // Add gadget to execution tree\n if (this.tree) {\n this.tree.addGadget({\n invocationId: call.invocationId,\n name: call.gadgetName,\n parameters: call.parameters ?? {},\n dependencies: call.dependencies,\n parentId: this.parentNodeId,\n });\n }\n\n // Check for dependencies\n if (call.dependencies.length > 0) {\n // Check for self-referential dependency (circular to self)\n if (call.dependencies.includes(call.invocationId)) {\n this.logger.warn(\"Gadget has self-referential dependency (depends on itself)\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n });\n this.failedInvocations.add(call.invocationId);\n const skipEvent: GadgetSkippedEvent = {\n type: \"gadget_skipped\",\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n failedDependency: call.invocationId,\n failedDependencyError: `Gadget \"${call.invocationId}\" cannot depend on itself (self-referential dependency)`,\n };\n yield skipEvent;\n return;\n }\n\n // Check if any dependency has failed (including from prior iterations)\n const failedDep = call.dependencies.find(\n (dep) => this.failedInvocations.has(dep) || this.priorFailedInvocations.has(dep),\n );\n if (failedDep) {\n // Dependency failed - handle skip\n const skipEvents = await this.handleFailedDependency(call, failedDep);\n for (const evt of skipEvents) {\n yield evt;\n }\n return;\n }\n\n // Check if all dependencies are satisfied (including from prior iterations)\n const unsatisfied = call.dependencies.filter(\n (dep) => !this.completedResults.has(dep) && !this.priorCompletedInvocations.has(dep),\n );\n if (unsatisfied.length > 0) {\n // Queue for later execution - gadget_call already yielded above\n this.logger.debug(\"Queueing gadget for later - waiting on dependencies\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n waitingOn: unsatisfied,\n });\n this.gadgetsAwaitingDependencies.set(call.invocationId, call);\n return; // Execution deferred, gadget_call already yielded\n }\n\n // All dependencies satisfied - execute synchronously (dependency already complete)\n for await (const evt of this.executeGadgetGenerator(call)) {\n yield evt;\n }\n\n // Check if any pending gadgets can now execute\n for await (const evt of this.processPendingGadgetsGenerator()) {\n yield evt;\n }\n return;\n }\n\n // NO dependencies - check concurrency limit before starting\n const limit = this.getConcurrencyLimit(call.gadgetName);\n const activeCount = this.activeCountByGadget.get(call.gadgetName) ?? 0;\n\n if (limit > 0 && activeCount >= limit) {\n // Queue for later execution when a slot becomes available\n this.logger.debug(\"Gadget queued due to concurrency limit\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n activeCount,\n limit,\n });\n const queue = this.concurrencyQueue.get(call.gadgetName) ?? [];\n queue.push(call);\n this.concurrencyQueue.set(call.gadgetName, queue);\n return; // Don't start yet, will be processed when a slot opens\n }\n\n // Start execution with concurrency tracking\n this.startGadgetWithConcurrencyTracking(call);\n // DON'T await - continue processing stream immediately\n }\n\n /**\n * Get the concurrency limit for a gadget from subagent config.\n * Returns 0 if no limit is set (unlimited).\n */\n private getConcurrencyLimit(gadgetName: string): number {\n const config = this.subagentConfig?.[gadgetName];\n return config?.maxConcurrent ?? 0;\n }\n\n /**\n * Start a gadget execution with concurrency tracking.\n * Increments active count, starts execution, and schedules queue processing on completion.\n */\n private startGadgetWithConcurrencyTracking(call: ParsedGadgetCall): void {\n const gadgetName = call.gadgetName;\n const currentCount = this.activeCountByGadget.get(gadgetName) ?? 0;\n this.activeCountByGadget.set(gadgetName, currentCount + 1);\n\n const executionPromise = this.executeGadgetAndCollect(call).finally(() => {\n // Decrement active count and process any queued gadgets\n const newCount = (this.activeCountByGadget.get(gadgetName) ?? 1) - 1;\n this.activeCountByGadget.set(gadgetName, newCount);\n this.processQueuedGadget(gadgetName);\n });\n\n this.inFlightExecutions.set(call.invocationId, executionPromise);\n }\n\n /**\n * Process the next queued gadget for a given gadget name if a slot is available.\n */\n private processQueuedGadget(gadgetName: string): void {\n const queue = this.concurrencyQueue.get(gadgetName);\n if (!queue || queue.length === 0) return;\n\n const limit = this.getConcurrencyLimit(gadgetName);\n const activeCount = this.activeCountByGadget.get(gadgetName) ?? 0;\n\n if (limit === 0 || activeCount < limit) {\n const nextCall = queue.shift()!;\n this.logger.debug(\"Processing queued gadget\", {\n gadgetName,\n invocationId: nextCall.invocationId,\n remainingInQueue: queue.length,\n });\n this.startGadgetWithConcurrencyTracking(nextCall);\n }\n }\n\n /**\n * Execute a gadget through the full hook lifecycle and yield events.\n * Handles parameter interception, before/after controllers, observers,\n * execution, result interception, and tree tracking.\n */\n private async *executeGadgetGenerator(call: ParsedGadgetCall): AsyncGenerator<StreamEvent> {\n // Log parse errors if present (execution continues - errors are part of the result)\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\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 // Mark gadget as running in execution tree\n if (this.tree) {\n const gadgetNode = this.tree.getNodeByInvocationId(call.invocationId);\n if (gadgetNode) {\n this.tree.startGadget(gadgetNode.id);\n }\n }\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 // Capture the raw result before any hook transformations.\n // Used in onGadgetExecutionComplete to provide both pre-hook (originalResult)\n // and post-hook (finalResult) values for observers that need to audit changes.\n const originalResult = result.result;\n\n // Step 5: Interceptor - Transform result (modifies result.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 (can further modify result)\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 cost: result.cost,\n logger: this.logger,\n };\n await this.hooks.observers?.onGadgetExecutionComplete?.(context);\n });\n }\n await this.runObserversInParallel(completeObservers);\n\n // Complete gadget in execution tree\n if (this.tree) {\n const gadgetNode = this.tree.getNodeByInvocationId(result.invocationId);\n if (gadgetNode) {\n if (result.error) {\n this.tree.completeGadget(gadgetNode.id, {\n error: result.error,\n executionTimeMs: result.executionTimeMs,\n cost: result.cost,\n });\n } else {\n this.tree.completeGadget(gadgetNode.id, {\n result: result.result,\n executionTimeMs: result.executionTimeMs,\n cost: result.cost,\n media: result.media,\n });\n }\n }\n }\n\n // Track completion for dependency resolution\n this.completedResults.set(result.invocationId, result);\n if (result.error) {\n this.failedInvocations.add(result.invocationId);\n }\n\n // Yield result event immediately\n yield { type: \"gadget_result\", result };\n }\n\n /**\n * Execute a gadget and push events to the completed results queue (non-blocking).\n * Used for fire-and-forget parallel execution of independent gadgets.\n * Results are pushed to completedResultsQueue for real-time streaming to the caller.\n */\n private async executeGadgetAndCollect(call: ParsedGadgetCall): Promise<void> {\n for await (const evt of this.executeGadgetGenerator(call)) {\n // Push each event to the queue as it's produced for real-time streaming\n this.completedResultsQueue.push(evt);\n }\n // NOTE: Don't delete from inFlightExecutions here - it creates a race condition\n // where fast-completing gadgets are removed before waitForInFlightExecutions runs.\n // The map is cleared in waitForInFlightExecutions after all promises are awaited.\n }\n\n /**\n * Drain all completed results from the queue.\n * Used to yield results as they complete during stream processing.\n * @returns Generator that yields all events currently in the queue\n */\n private *drainCompletedResults(): Generator<StreamEvent> {\n while (this.completedResultsQueue.length > 0) {\n yield this.completedResultsQueue.shift()!;\n }\n }\n\n /**\n * Wait for all in-flight gadget executions to complete, yielding events in real-time.\n * Called at stream end to ensure all parallel executions finish.\n * Results and subagent events are pushed to completedResultsQueue during execution.\n * This generator yields queued events while polling, enabling real-time display\n * of subagent activity (LLM calls, nested gadgets) during long-running gadgets.\n * Clears the inFlightExecutions map after all gadgets complete.\n */\n private async *waitForInFlightExecutions(): AsyncGenerator<StreamEvent> {\n if (this.inFlightExecutions.size === 0 && !this.hasQueuedGadgets()) {\n return;\n }\n\n this.logger.debug(\"Waiting for in-flight gadget executions\", {\n count: this.inFlightExecutions.size,\n invocationIds: Array.from(this.inFlightExecutions.keys()),\n queuedCount: this.getQueuedGadgetCount(),\n });\n\n // Poll interval for draining queue (100ms provides responsive updates)\n const POLL_INTERVAL_MS = 100;\n\n // Poll loop: yield queued events while waiting for gadgets to complete\n // Continue while there are in-flight executions OR queued gadgets waiting\n while (this.inFlightExecutions.size > 0 || this.hasQueuedGadgets()) {\n // Create a combined promise that resolves when current gadgets complete\n const allDone =\n this.inFlightExecutions.size > 0\n ? Promise.all(this.inFlightExecutions.values()).then(() => \"done\" as const)\n : Promise.resolve(\"done\" as const);\n\n // Race between: all current gadgets completing OR poll timeout\n const result = await Promise.race([\n allDone,\n new Promise<\"poll\">((resolve) => setTimeout(() => resolve(\"poll\"), POLL_INTERVAL_MS)),\n ]);\n\n // Yield any events that accumulated in the queue\n yield* this.drainCompletedResults();\n\n if (result === \"done\" && this.getTotalActiveGadgetCount() === 0 && !this.hasQueuedGadgets()) {\n // All gadgets complete (none active), no more queued - exit loop\n break;\n }\n // Continue polling - either more gadgets will be started from queue,\n // or we're still waiting for in-flight gadgets\n }\n\n // Clear the map after all promises have completed\n this.inFlightExecutions.clear();\n }\n\n /**\n * Check if there are any gadgets waiting in concurrency queues.\n */\n private hasQueuedGadgets(): boolean {\n for (const queue of this.concurrencyQueue.values()) {\n if (queue.length > 0) return true;\n }\n return false;\n }\n\n /**\n * Get total count of queued gadgets across all queues.\n */\n private getQueuedGadgetCount(): number {\n let count = 0;\n for (const queue of this.concurrencyQueue.values()) {\n count += queue.length;\n }\n return count;\n }\n\n /**\n * Get total count of actively executing gadgets across all types.\n * Used to know when all work is truly complete (not just when allDone resolves).\n */\n private getTotalActiveGadgetCount(): number {\n let total = 0;\n for (const count of this.activeCountByGadget.values()) {\n total += count;\n }\n return total;\n }\n\n /**\n * Handle a gadget that cannot execute because a dependency failed.\n * Calls the onDependencySkipped controller to allow customization.\n */\n private async handleFailedDependency(\n call: ParsedGadgetCall,\n failedDep: string,\n ): Promise<StreamEvent[]> {\n const events: StreamEvent[] = [];\n const depResult = this.completedResults.get(failedDep);\n const depError = depResult?.error ?? \"Dependency failed\";\n\n // Call controller to allow customization of skip behavior\n let action: DependencySkipAction = { action: \"skip\" };\n if (this.hooks.controllers?.onDependencySkipped) {\n const context: DependencySkipControllerContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n failedDependency: failedDep,\n failedDependencyError: depError,\n logger: this.logger,\n };\n action = await this.hooks.controllers.onDependencySkipped(context);\n }\n\n if (action.action === \"skip\") {\n // Mark as failed so downstream dependents also skip\n this.failedInvocations.add(call.invocationId);\n\n // Skip gadget in execution tree\n if (this.tree) {\n const gadgetNode = this.tree.getNodeByInvocationId(call.invocationId);\n if (gadgetNode) {\n this.tree.skipGadget(gadgetNode.id, failedDep, depError, \"dependency_failed\");\n }\n }\n\n // Emit skip event\n const skipEvent: GadgetSkippedEvent = {\n type: \"gadget_skipped\",\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n failedDependency: failedDep,\n failedDependencyError: depError,\n };\n events.push(skipEvent);\n\n // Call observer\n if (this.hooks.observers?.onGadgetSkipped) {\n const observeContext: ObserveGadgetSkippedContext = {\n iteration: this.iteration,\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n failedDependency: failedDep,\n failedDependencyError: depError,\n logger: this.logger,\n };\n await this.safeObserve(() => this.hooks.observers?.onGadgetSkipped?.(observeContext));\n }\n\n this.logger.info(\"Gadget skipped due to failed dependency\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n failedDependency: failedDep,\n });\n } else if (action.action === \"execute_anyway\") {\n // Execute despite failed dependency\n this.logger.info(\"Executing gadget despite failed dependency (controller override)\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n failedDependency: failedDep,\n });\n for await (const evt of this.executeGadgetGenerator(call)) {\n events.push(evt);\n }\n } else if (action.action === \"use_fallback\") {\n // Use fallback result without executing\n const fallbackResult: GadgetExecutionResult = {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n parameters: call.parameters ?? {},\n result: action.fallbackResult,\n executionTimeMs: 0,\n };\n this.completedResults.set(call.invocationId, fallbackResult);\n events.push({ type: \"gadget_result\", result: fallbackResult });\n\n this.logger.info(\"Using fallback result for gadget with failed dependency\", {\n gadgetName: call.gadgetName,\n invocationId: call.invocationId,\n failedDependency: failedDep,\n });\n }\n\n return events;\n }\n\n /**\n * Process pending gadgets whose dependencies are now satisfied.\n * Yields events in real-time as gadgets complete.\n *\n * Gadgets are executed in parallel for efficiency,\n * but results are yielded as they become available.\n */\n private async *processPendingGadgetsGenerator(): AsyncGenerator<StreamEvent> {\n let progress = true;\n\n while (progress && this.gadgetsAwaitingDependencies.size > 0) {\n progress = false;\n\n // Find all gadgets that are ready to execute\n const readyToExecute: ParsedGadgetCall[] = [];\n const readyToSkip: Array<{ call: ParsedGadgetCall; failedDep: string }> = [];\n\n for (const [_invocationId, call] of this.gadgetsAwaitingDependencies) {\n // Check for failed dependency (including from prior iterations)\n const failedDep = call.dependencies.find(\n (dep) => this.failedInvocations.has(dep) || this.priorFailedInvocations.has(dep),\n );\n if (failedDep) {\n readyToSkip.push({ call, failedDep });\n continue;\n }\n\n // Check if all dependencies are satisfied (including from prior iterations)\n const allSatisfied = call.dependencies.every(\n (dep) => this.completedResults.has(dep) || this.priorCompletedInvocations.has(dep),\n );\n if (allSatisfied) {\n readyToExecute.push(call);\n }\n }\n\n // Handle skipped gadgets\n for (const { call, failedDep } of readyToSkip) {\n this.gadgetsAwaitingDependencies.delete(call.invocationId);\n const skipEvents = await this.handleFailedDependency(call, failedDep);\n for (const evt of skipEvents) {\n yield evt;\n }\n progress = true;\n }\n\n // Execute ready gadgets in parallel\n if (readyToExecute.length > 0) {\n this.logger.debug(\"Executing ready gadgets in parallel\", {\n count: readyToExecute.length,\n invocationIds: readyToExecute.map((c) => c.invocationId),\n });\n\n // Remove from pending before executing\n for (const call of readyToExecute) {\n this.gadgetsAwaitingDependencies.delete(call.invocationId);\n }\n\n // Execute all ready gadgets in parallel, collect events, then yield\n const eventSets = await Promise.all(\n readyToExecute.map(async (call) => {\n const events: StreamEvent[] = [];\n for await (const evt of this.executeGadgetGenerator(call)) {\n events.push(evt);\n }\n return events;\n }),\n );\n\n // Yield all events from parallel execution\n for (const events of eventSets) {\n for (const evt of events) {\n yield evt;\n }\n }\n\n progress = true;\n }\n }\n\n // Warn about any remaining unresolved gadgets (circular or missing dependencies)\n if (this.gadgetsAwaitingDependencies.size > 0) {\n // Collect all pending invocation IDs to detect circular dependencies\n const pendingIds = new Set(this.gadgetsAwaitingDependencies.keys());\n\n for (const [invocationId, call] of this.gadgetsAwaitingDependencies) {\n // Filter to deps that are not in current or prior completed sets\n const missingDeps = call.dependencies.filter(\n (dep) => !this.completedResults.has(dep) && !this.priorCompletedInvocations.has(dep),\n );\n\n // Categorize the dependency issue\n const circularDeps = missingDeps.filter((dep) => pendingIds.has(dep));\n const trulyMissingDeps = missingDeps.filter((dep) => !pendingIds.has(dep));\n\n let errorMessage: string;\n let logLevel: \"warn\" | \"error\" = \"warn\";\n\n if (circularDeps.length > 0 && trulyMissingDeps.length > 0) {\n errorMessage = `Dependencies unresolvable: circular=[${circularDeps.join(\", \")}], missing=[${trulyMissingDeps.join(\", \")}]`;\n logLevel = \"error\";\n } else if (circularDeps.length > 0) {\n errorMessage = `Circular dependency detected: \"${invocationId}\" depends on \"${circularDeps[0]}\" which also depends on \"${invocationId}\" (directly or indirectly)`;\n } else {\n errorMessage = `Dependency \"${missingDeps[0]}\" was never executed - check that the invocation ID exists and is spelled correctly`;\n }\n\n this.logger[logLevel](\"Gadget has unresolvable dependencies\", {\n gadgetName: call.gadgetName,\n invocationId,\n circularDependencies: circularDeps,\n missingDependencies: trulyMissingDeps,\n });\n\n // Mark as failed and emit skip event\n this.failedInvocations.add(invocationId);\n const skipEvent: GadgetSkippedEvent = {\n type: \"gadget_skipped\",\n gadgetName: call.gadgetName,\n invocationId,\n parameters: call.parameters ?? {},\n failedDependency: missingDeps[0],\n failedDependencyError: errorMessage,\n };\n yield skipEvent;\n }\n this.gadgetsAwaitingDependencies.clear();\n }\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 // Run all observers in parallel, waiting for completion\n // Errors are logged in safeObserve, no need to handle rejected promises\n await Promise.allSettled(\n observers.map((observer) => this.safeObserve(observer)),\n );\n }\n\n // ==========================================================================\n // Public accessors for cross-iteration dependency tracking\n // ==========================================================================\n\n /**\n * Get all invocation IDs that completed successfully in this iteration.\n * Used by Agent to accumulate completed IDs across iterations.\n */\n getCompletedInvocationIds(): Set<string> {\n return new Set(this.completedResults.keys());\n }\n\n /**\n * Get all invocation IDs that failed in this iteration.\n * Used by Agent to accumulate failed IDs across iterations.\n */\n getFailedInvocationIds(): Set<string> {\n return new Set(this.failedInvocations);\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 { ExecutionTree, type NodeId } from \"../core/execution-tree.js\";\nimport type { ContentPart } from \"../core/input-content.js\";\nimport type { MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, LLMMessageBuilder } from \"../core/messages.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { LLMGenerationOptions } from \"../core/options.js\";\nimport type { PromptTemplateConfig } from \"../core/prompt-config.js\";\nimport { MediaStore } from \"../gadgets/media-store.js\";\nimport { createGadgetOutputViewer } from \"../gadgets/output-viewer.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type {\n AgentContextConfig,\n LLMCallInfo,\n StreamCompletionEvent,\n StreamEvent,\n SubagentConfigMap,\n SubagentEvent,\n TextOnlyHandler,\n} from \"../gadgets/types.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { type AGENT_INTERNAL_KEY, isValidAgentKey } from \"./agent-internal-key.js\";\nimport type { CompactionConfig, CompactionEvent, CompactionStats } from \"./compaction/config.js\";\nimport type { RetryConfig, ResolvedRetryConfig } from \"../core/retry.js\";\nimport { resolveRetryConfig, isRetryableError } from \"../core/retry.js\";\nimport pRetry from \"p-retry\";\nimport { CompactionManager } from \"./compaction/manager.js\";\nimport { ConversationManager } from \"./conversation-manager.js\";\nimport type { IConversationManager } from \"./interfaces.js\";\nimport { type EventHandlers, runWithHandlers } from \"./event-handlers.js\";\nimport { GadgetOutputStore } from \"./gadget-output-store.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 GadgetResultInterceptorContext,\n LLMCallControllerContext,\n LLMErrorControllerContext,\n ObserveAbortContext,\n ObserveLLMCallContext,\n ObserveLLMCallReadyContext,\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()). Can be text or multimodal content. */\n userPrompt?: string | ContentPart[];\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 requesting human input during execution */\n requestHumanInput?: (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. User messages support multimodal content. */\n initialMessages?: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: MessageContent }>;\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 /** Default gadget timeout */\n defaultGadgetTimeoutMs?: number;\n\n /** Custom prompt configuration for gadget system prompts */\n promptConfig?: PromptTemplateConfig;\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 /** Retry configuration for LLM API calls (enabled by default) */\n retryConfig?: RetryConfig;\n\n /** Optional abort signal for cancelling requests mid-flight */\n signal?: AbortSignal;\n\n /** Subagent-specific configuration overrides (from CLI config) */\n subagentConfig?: SubagentConfigMap;\n\n /** Callback for subagent gadgets to report subagent events to parent */\n onSubagentEvent?: (event: SubagentEvent) => void;\n\n // ==========================================================================\n // Execution Tree Context (for shared tree model with subagents)\n // ==========================================================================\n\n /**\n * Shared execution tree for tracking all LLM calls and gadget executions.\n * If provided (by a parent subagent), nodes are added to this tree.\n * If not provided, the Agent creates its own tree.\n */\n parentTree?: ExecutionTree;\n\n /**\n * Parent node ID in the tree (when this agent is a subagent).\n * Used to set parentId on all nodes created by this agent.\n */\n parentNodeId?: NodeId;\n\n /**\n * Base depth for nodes created by this agent.\n * Root agents use 0; subagents use (parentDepth + 1).\n */\n baseDepth?: number;\n}\n\n/**\n * Agent: Lean orchestrator that delegates to StreamProcessor.\n *\n * Responsibilities:\n * - Run the main agent loop\n * - Call LLM API\n * - Delegate stream processing to StreamProcessor\n * - Coordinate conversation management\n * - Execute top-level lifecycle controllers\n *\n * NOT responsible for:\n * - Stream parsing (StreamProcessor)\n * - Hook coordination (StreamProcessor)\n * - Gadget execution (StreamProcessor -> GadgetExecutor)\n */\nexport class Agent {\n private readonly client: LLMist;\n private readonly model: string;\n private readonly maxIterations: number;\n private readonly temperature?: number;\n private readonly logger: Logger<ILogObj>;\n private readonly hooks: AgentHooks;\n private readonly conversation: ConversationManager;\n private readonly registry: GadgetRegistry;\n private readonly gadgetStartPrefix?: string;\n private readonly gadgetEndPrefix?: string;\n private readonly gadgetArgPrefix?: string;\n private readonly requestHumanInput?: (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 defaultGadgetTimeoutMs?: number;\n private readonly defaultMaxTokens?: number;\n private hasUserPrompt: 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 // Media storage (for gadgets returning images, audio, etc.)\n private readonly mediaStore: MediaStore;\n\n // Cancellation\n private readonly signal?: AbortSignal;\n\n // Retry configuration\n private readonly retryConfig: ResolvedRetryConfig;\n\n // Subagent configuration\n private readonly agentContextConfig: AgentContextConfig;\n private readonly subagentConfig?: SubagentConfigMap;\n\n // Subagent event callback for subagent gadgets\n private readonly userSubagentEventCallback?: (event: SubagentEvent) => void;\n // Internal queue for yielding subagent events in run()\n private readonly pendingSubagentEvents: SubagentEvent[] = [];\n // Combined callback that queues events AND calls user callback\n private readonly onSubagentEvent: (event: SubagentEvent) => void;\n // Counter for generating synthetic invocation IDs for wrapped text content\n private syntheticInvocationCounter = 0;\n\n // Cross-iteration dependency tracking - allows gadgets to depend on results from prior iterations\n private readonly completedInvocationIds: Set<string> = new Set();\n private readonly failedInvocationIds: Set<string> = new Set();\n\n // Queue for user messages injected during agent execution (REPL mid-session input)\n private readonly pendingUserMessages: string[] = [];\n\n // Execution Tree - first-class model for nested subagent support\n private readonly tree: ExecutionTree;\n private readonly parentNodeId: NodeId | null;\n private readonly baseDepth: number;\n\n /**\n * Creates a new Agent instance.\n * @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.\n */\n constructor(key: typeof AGENT_INTERNAL_KEY, options: AgentOptions) {\n if (!isValidAgentKey(key)) {\n throw new Error(\n \"Agent cannot be instantiated directly. Use LLMist.createAgent() or new AgentBuilder() instead.\",\n );\n }\n\n this.client = options.client;\n this.model = resolveModel(options.model);\n this.maxIterations = options.maxIterations ?? 10;\n this.temperature = options.temperature;\n this.logger = options.logger ?? createLogger({ name: \"llmist:agent\" });\n this.registry = options.registry;\n this.gadgetStartPrefix = options.gadgetStartPrefix;\n this.gadgetEndPrefix = options.gadgetEndPrefix;\n this.gadgetArgPrefix = options.gadgetArgPrefix;\n this.requestHumanInput = options.requestHumanInput;\n this.textOnlyHandler = options.textOnlyHandler ?? \"terminate\";\n this.textWithGadgetsHandler = options.textWithGadgetsHandler;\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 // Initialize media storage for gadgets returning images, audio, etc.\n this.mediaStore = new MediaStore();\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 // Pass the same character limit so viewer output is also bounded\n if (this.outputLimitEnabled) {\n this.registry.register(\n \"GadgetOutputViewer\",\n createGadgetOutputViewer(this.outputStore, this.outputLimitCharLimit),\n );\n }\n\n // Chain output limiter interceptor with user hooks\n this.hooks = this.chainOutputLimiterWithUserHooks(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.hasUserPrompt = !!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 // Initialize retry configuration (enabled by default)\n this.retryConfig = resolveRetryConfig(options.retryConfig);\n\n // Build agent context config for subagents to inherit\n this.agentContextConfig = {\n model: this.model,\n temperature: this.temperature,\n };\n this.subagentConfig = options.subagentConfig;\n\n // Initialize Execution Tree\n // If a parent tree is provided (subagent case), share it; otherwise create a new tree\n this.tree = options.parentTree ?? new ExecutionTree();\n this.parentNodeId = options.parentNodeId ?? null;\n this.baseDepth = options.baseDepth ?? 0;\n\n // Store user callback and create combined callback that:\n // 1. Queues events for yielding in run()\n // 2. Calls user callback if provided\n // 3. Fires hooks with subagentContext for consistent event handling\n this.userSubagentEventCallback = options.onSubagentEvent;\n this.onSubagentEvent = (event: SubagentEvent) => {\n this.pendingSubagentEvents.push(event);\n this.userSubagentEventCallback?.(event);\n\n // Fire the SAME hooks with subagentContext - enables consistent hook-based handling\n const subagentContext = {\n parentGadgetInvocationId: event.gadgetInvocationId,\n depth: event.depth,\n };\n\n // Fire hooks asynchronously but don't block\n if (event.type === \"llm_call_start\") {\n const info = event.event as LLMCallInfo;\n void this.hooks?.observers?.onLLMCallStart?.({\n iteration: info.iteration,\n options: { model: info.model, messages: [] },\n logger: this.logger,\n subagentContext,\n });\n } else if (event.type === \"llm_call_end\") {\n const info = event.event as LLMCallInfo;\n // Use full usage object if available (preserves cached tokens), fallback to basic reconstruction\n const usage = info.usage ?? (info.outputTokens\n ? {\n inputTokens: info.inputTokens ?? 0,\n outputTokens: info.outputTokens,\n totalTokens: (info.inputTokens ?? 0) + info.outputTokens,\n }\n : undefined);\n void this.hooks?.observers?.onLLMCallComplete?.({\n iteration: info.iteration,\n options: { model: info.model, messages: [] },\n finishReason: info.finishReason ?? null,\n usage,\n rawResponse: \"\",\n finalMessage: \"\",\n logger: this.logger,\n subagentContext,\n });\n } else if (event.type === \"gadget_call\") {\n const gadgetEvent = event.event as { call: { invocationId: string; gadgetName: string; parameters?: Record<string, unknown> } };\n void this.hooks?.observers?.onGadgetExecutionStart?.({\n iteration: 0,\n gadgetName: gadgetEvent.call.gadgetName,\n invocationId: gadgetEvent.call.invocationId,\n parameters: gadgetEvent.call.parameters ?? {},\n logger: this.logger,\n subagentContext,\n });\n } else if (event.type === \"gadget_result\") {\n const resultEvent = event.event as { result: { invocationId: string; gadgetName?: string; executionTimeMs?: number } };\n void this.hooks?.observers?.onGadgetExecutionComplete?.({\n iteration: 0,\n gadgetName: resultEvent.result.gadgetName ?? \"unknown\",\n invocationId: resultEvent.result.invocationId,\n parameters: {},\n executionTimeMs: resultEvent.result.executionTimeMs ?? 0,\n logger: this.logger,\n subagentContext,\n });\n }\n };\n }\n\n /**\n * Flush pending subagent events as StreamEvents.\n * Called from run() to yield queued subagent events from subagent gadgets.\n */\n private *flushPendingSubagentEvents(): Generator<StreamEvent> {\n while (this.pendingSubagentEvents.length > 0) {\n const event = this.pendingSubagentEvents.shift();\n if (event) {\n yield { type: \"subagent_event\", subagentEvent: event };\n }\n }\n }\n\n /**\n * Get the gadget registry for this agent.\n *\n * Useful for inspecting registered gadgets in tests or advanced use cases.\n *\n * @returns The GadgetRegistry instance\n *\n * @example\n * ```typescript\n * const agent = new AgentBuilder()\n * .withModel(\"sonnet\")\n * .withGadgets(Calculator, Weather)\n * .build();\n *\n * // Inspect registered gadgets\n * console.log(agent.getRegistry().getNames()); // ['Calculator', 'Weather']\n * ```\n */\n getRegistry(): GadgetRegistry {\n return this.registry;\n }\n\n /**\n * Get the media store for this agent session.\n *\n * The media store holds all media outputs (images, audio, etc.) produced by gadgets\n * during this agent's execution. Use this to:\n * - Access stored media files by ID\n * - List all stored media\n * - Clean up temporary files after execution\n *\n * @returns The MediaStore instance for this agent\n *\n * @example\n * ```typescript\n * const agent = new AgentBuilder()\n * .withModel(\"sonnet\")\n * .build();\n *\n * // After execution, access stored media\n * const store = agent.getMediaStore();\n * for (const media of store.list()) {\n * console.log(`${media.id}: ${media.path}`);\n * }\n *\n * // Clean up when done\n * await store.cleanup();\n * ```\n */\n getMediaStore(): MediaStore {\n return this.mediaStore;\n }\n\n /**\n * Get the execution tree for this agent.\n *\n * The execution tree provides a first-class model of all LLM calls and gadget executions,\n * including nested subagent activity. Use this to:\n * - Query execution state: `tree.getNode(id)`\n * - Get total cost: `tree.getTotalCost()`\n * - Get subtree cost/media/tokens: `tree.getSubtreeCost(nodeId)`\n * - Subscribe to events: `tree.on(\"llm_call_complete\", handler)`\n * - Stream all events: `for await (const event of tree.events())`\n *\n * For subagents (created with `withParentContext`), the tree is shared with the parent,\n * enabling unified tracking and real-time visibility across all nesting levels.\n *\n * @returns The ExecutionTree instance\n *\n * @example\n * ```typescript\n * const agent = LLMist.createAgent()\n * .withModel(\"sonnet\")\n * .withGadgets(BrowseWeb)\n * .ask(\"Research topic X\");\n *\n * for await (const event of agent.run()) {\n * // Process events...\n * }\n *\n * // After execution, query the tree\n * const tree = agent.getTree();\n * console.log(`Total cost: $${tree.getTotalCost().toFixed(4)}`);\n *\n * // Inspect all LLM calls\n * for (const node of tree.getAllNodes()) {\n * if (node.type === \"llm_call\") {\n * console.log(`LLM #${node.iteration}: ${node.model}`);\n * }\n * }\n * ```\n */\n getTree(): ExecutionTree {\n return this.tree;\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 * Get the conversation manager for this agent.\n * Used by REPL mode to extract session history for continuation.\n *\n * @returns The conversation manager containing all messages\n *\n * @example\n * ```typescript\n * // After running agent, extract history for next session\n * const history = agent.getConversation().getConversationHistory();\n * // Pass to next agent via builder.withHistory()\n * ```\n */\n getConversation(): IConversationManager {\n return this.conversation;\n }\n\n /**\n * Inject a user message to be processed in the next iteration.\n * Used by REPL mode to allow user input during a running session.\n *\n * The message is queued and will be added to the conversation before\n * the next LLM call. This allows users to provide additional context\n * or instructions while the agent is executing.\n *\n * @param message - The user message to inject\n *\n * @example\n * ```typescript\n * // While agent is running in TUI:\n * tui.onMidSessionInput((msg) => {\n * agent.injectUserMessage(msg);\n * });\n * ```\n */\n injectUserMessage(message: string): void {\n this.pendingUserMessages.push(message);\n this.logger.debug(\"User message queued for injection\", { message });\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.hasUserPrompt) {\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 // Check abort signal at start of each iteration\n if (await this.checkAbortAndNotify(currentIteration)) {\n return;\n }\n\n // Process any injected user messages (from REPL mid-session input)\n while (this.pendingUserMessages.length > 0) {\n const msg = this.pendingUserMessages.shift()!;\n this.conversation.addUserMessage(msg);\n this.logger.info(\"Injected user message into conversation\", {\n iteration: currentIteration,\n messageLength: msg.length,\n });\n }\n\n this.logger.debug(\"Starting iteration\", { iteration: currentIteration });\n\n try {\n // Check and perform context compaction if needed\n const compactionEvent = await this.checkAndPerformCompaction(currentIteration);\n if (compactionEvent) {\n yield compactionEvent;\n }\n\n // Prepare LLM call with hooks\n const prepared = await this.prepareLLMCall(currentIteration);\n const llmOptions = prepared.options;\n\n // Handle skip action from beforeLLMCall controller\n if (prepared.skipWithSynthetic !== undefined) {\n this.conversation.addAssistantMessage(prepared.skipWithSynthetic);\n yield { type: \"text\", content: prepared.skipWithSynthetic };\n break;\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\n // Add LLM call to execution tree\n const llmNode = this.tree.addLLMCall({\n iteration: currentIteration,\n model: llmOptions.model,\n parentId: this.parentNodeId,\n request: llmOptions.messages,\n });\n const currentLLMNodeId = llmNode.id;\n\n // Create LLM stream with retry logic (if enabled)\n const stream = await this.createStreamWithRetry(llmOptions, currentIteration);\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 requestHumanInput: this.requestHumanInput,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n client: this.client,\n mediaStore: this.mediaStore,\n agentConfig: this.agentContextConfig,\n subagentConfig: this.subagentConfig,\n onSubagentEvent: this.onSubagentEvent,\n // Tree context for execution tracking\n tree: this.tree,\n parentNodeId: currentLLMNodeId, // Gadgets are children of this LLM call\n baseDepth: this.baseDepth,\n // Cross-iteration dependency tracking\n priorCompletedInvocations: this.completedInvocationIds,\n priorFailedInvocations: this.failedInvocationIds,\n });\n\n // Consume the stream processor generator, yielding events in real-time\n // The final event is a StreamCompletionEvent containing metadata\n let streamMetadata: StreamCompletionEvent | null = null;\n let gadgetCallCount = 0;\n\n // Track outputs for conversation history (since we stream instead of batch)\n const textOutputs: string[] = [];\n const gadgetResults: StreamEvent[] = [];\n\n for await (const event of processor.process(stream)) {\n if (event.type === \"stream_complete\") {\n // Completion event - extract metadata, don't yield to consumer\n streamMetadata = event;\n continue;\n }\n\n // Track outputs for later conversation history updates\n if (event.type === \"text\") {\n textOutputs.push(event.content);\n } else if (event.type === \"gadget_result\") {\n gadgetCallCount++;\n gadgetResults.push(event);\n }\n\n // Yield event to consumer in real-time\n yield event;\n\n // Yield any subagent events that accumulated during gadget execution\n // This enables real-time display of subagent activity (Navigate, Screenshot, etc.)\n yield* this.flushPendingSubagentEvents();\n }\n\n // Ensure we received the completion metadata\n if (!streamMetadata) {\n throw new Error(\"Stream processing completed without metadata event\");\n }\n\n // Collect completed/failed invocation IDs for cross-iteration dependency tracking\n for (const id of processor.getCompletedInvocationIds()) {\n this.completedInvocationIds.add(id);\n }\n for (const id of processor.getFailedInvocationIds()) {\n this.failedInvocationIds.add(id);\n }\n\n // Use streamMetadata as the result for remaining logic\n const result = streamMetadata;\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 // Complete LLM call in execution tree (with cost calculation)\n this.completeLLMCallInTree(currentLLMNodeId, result);\n\n // Process afterLLMCall controller (may modify finalMessage or append messages)\n const finalMessage = await this.processAfterLLMCallController(\n currentIteration,\n llmOptions,\n result,\n gadgetCallCount,\n );\n\n // Update conversation with results (gadgets or text-only)\n const shouldBreakFromTextOnly = await this.updateConversationWithResults(\n result.didExecuteGadgets,\n textOutputs,\n gadgetResults,\n finalMessage,\n );\n if (shouldBreakFromTextOnly) {\n break;\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 * Create LLM stream with retry logic.\n * Wraps the stream creation with exponential backoff for transient failures.\n */\n private async createStreamWithRetry(\n llmOptions: LLMGenerationOptions,\n iteration: number,\n ): Promise<ReturnType<LLMist[\"stream\"]>> {\n // If retry is disabled, return stream directly\n if (!this.retryConfig.enabled) {\n return this.client.stream(llmOptions);\n }\n\n const { retries, minTimeout, maxTimeout, factor, randomize, onRetry, onRetriesExhausted, shouldRetry } =\n this.retryConfig;\n\n try {\n return await pRetry(\n async (attemptNumber) => {\n this.logger.debug(\"Creating LLM stream\", { attempt: attemptNumber, maxAttempts: retries + 1 });\n return this.client.stream(llmOptions);\n },\n {\n retries,\n minTimeout,\n maxTimeout,\n factor,\n randomize,\n signal: this.signal,\n onFailedAttempt: (context) => {\n const { error, attemptNumber, retriesLeft } = context;\n this.logger.warn(\n `LLM call failed (attempt ${attemptNumber}/${attemptNumber + retriesLeft}), retrying...`,\n { error: error.message, retriesLeft },\n );\n onRetry?.(error, attemptNumber);\n },\n shouldRetry: (context) => {\n // Use custom shouldRetry if provided, otherwise use default classification\n if (shouldRetry) {\n return shouldRetry(context.error);\n }\n return isRetryableError(context.error);\n },\n },\n );\n } catch (error) {\n // All retries exhausted - call observer hook before re-throwing\n this.logger.error(`LLM call failed after ${retries + 1} attempts`, {\n error: (error as Error).message,\n iteration,\n });\n onRetriesExhausted?.(error as Error, retries + 1);\n throw error;\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 * Chain the output limiter interceptor with user-provided hooks.\n * The limiter runs first, then chains to any user interceptor.\n */\n private chainOutputLimiterWithUserHooks(userHooks?: AgentHooks): AgentHooks {\n if (!this.outputLimitEnabled) {\n return userHooks ?? {};\n }\n\n const limiterInterceptor = (result: string, ctx: GadgetResultInterceptorContext): 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 // Agent Loop Helper Methods (extracted from run() for readability)\n // ==========================================================================\n\n /**\n * Check abort signal and notify observers if aborted.\n * @returns true if agent should terminate\n */\n private async checkAbortAndNotify(iteration: number): Promise<boolean> {\n if (!this.signal?.aborted) return false;\n\n this.logger.info(\"Agent loop terminated by abort signal\", {\n iteration,\n reason: this.signal.reason,\n });\n\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onAbort) {\n const context: ObserveAbortContext = {\n iteration,\n reason: this.signal?.reason,\n logger: this.logger,\n };\n await this.hooks.observers.onAbort(context);\n }\n });\n\n return true;\n }\n\n /**\n * Check and perform context compaction if needed.\n * @returns compaction stream event if compaction occurred, null otherwise\n */\n private async checkAndPerformCompaction(iteration: number): Promise<StreamEvent | null> {\n if (!this.compactionManager) return null;\n\n const compactionEvent = await this.compactionManager.checkAndCompact(\n this.conversation,\n iteration,\n );\n\n if (!compactionEvent) return null;\n\n this.logger.info(\"Context compacted\", {\n strategy: compactionEvent.strategy,\n tokensBefore: compactionEvent.tokensBefore,\n tokensAfter: compactionEvent.tokensAfter,\n });\n\n // Observer: Compaction occurred\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onCompaction) {\n await this.hooks.observers.onCompaction({\n iteration,\n event: compactionEvent,\n // biome-ignore lint/style/noNonNullAssertion: compactionManager exists if compactionEvent is truthy\n stats: this.compactionManager!.getStats(),\n logger: this.logger,\n });\n }\n });\n\n return { type: \"compaction\", event: compactionEvent } as StreamEvent;\n }\n\n /**\n * Prepare LLM call options and process beforeLLMCall controller.\n * @returns options and optional skipWithSynthetic response if controller wants to skip\n */\n private async prepareLLMCall(\n iteration: number,\n ): Promise<{ options: LLMGenerationOptions; skipWithSynthetic?: string }> {\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,\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,\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 return { options: llmOptions, skipWithSynthetic: action.syntheticResponse };\n } else if (action.action === \"proceed\" && action.modifiedOptions) {\n llmOptions = { ...llmOptions, ...action.modifiedOptions };\n }\n }\n\n // Observer: LLM call ready (after controller modifications)\n await this.safeObserve(async () => {\n if (this.hooks.observers?.onLLMCallReady) {\n const context: ObserveLLMCallReadyContext = {\n iteration,\n maxIterations: this.maxIterations,\n options: llmOptions,\n logger: this.logger,\n };\n await this.hooks.observers.onLLMCallReady(context);\n }\n });\n\n return { options: llmOptions };\n }\n\n /**\n * Calculate cost and complete LLM call in execution tree.\n */\n private completeLLMCallInTree(\n nodeId: NodeId,\n result: StreamCompletionEvent,\n ): void {\n // Calculate cost using ModelRegistry (if available)\n const llmCost = this.client.modelRegistry?.estimateCost?.(\n this.model,\n result.usage?.inputTokens ?? 0,\n result.usage?.outputTokens ?? 0,\n result.usage?.cachedInputTokens ?? 0,\n result.usage?.cacheCreationInputTokens ?? 0,\n )?.totalCost;\n\n // Complete LLM call in execution tree (including cost for automatic aggregation)\n this.tree.completeLLMCall(nodeId, {\n response: result.rawResponse,\n usage: result.usage,\n finishReason: result.finishReason,\n cost: llmCost,\n });\n }\n\n /**\n * Process afterLLMCall controller and return modified final message.\n */\n private async processAfterLLMCallController(\n iteration: number,\n llmOptions: LLMGenerationOptions,\n result: StreamCompletionEvent,\n gadgetCallCount: number,\n ): Promise<string> {\n let finalMessage = result.finalMessage;\n\n if (!this.hooks.controllers?.afterLLMCall) {\n return finalMessage;\n }\n\n const context: AfterLLMCallControllerContext = {\n iteration,\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(extractMessageText(msg.content));\n } else if (msg.role === \"system\") {\n this.conversation.addUserMessage(`[System] ${extractMessageText(msg.content)}`);\n }\n }\n }\n\n return finalMessage;\n }\n\n /**\n * Update conversation history with gadget results or text-only response.\n * @returns true if loop should break (text-only handler requested termination)\n */\n private async updateConversationWithResults(\n didExecuteGadgets: boolean,\n textOutputs: string[],\n gadgetResults: StreamEvent[],\n finalMessage: string,\n ): Promise<boolean> {\n if (didExecuteGadgets) {\n // If configured, wrap accompanying text as a synthetic gadget call\n if (this.textWithGadgetsHandler) {\n const textContent = textOutputs.join(\"\");\n\n if (textContent.trim()) {\n const { gadgetName, parameterMapping, resultMapping } = this.textWithGadgetsHandler;\n const syntheticId = `gc_text_${++this.syntheticInvocationCounter}`;\n this.conversation.addGadgetCallResult(\n gadgetName,\n parameterMapping(textContent),\n resultMapping ? resultMapping(textContent) : textContent,\n syntheticId,\n );\n }\n }\n\n // Add all gadget results to conversation\n for (const output of gadgetResults) {\n if (output.type === \"gadget_result\") {\n const gadgetResult = output.result;\n this.conversation.addGadgetCallResult(\n gadgetResult.gadgetName,\n gadgetResult.parameters,\n gadgetResult.error ?? gadgetResult.result ?? \"\",\n gadgetResult.invocationId,\n gadgetResult.media,\n gadgetResult.mediaIds,\n );\n }\n }\n\n return false; // Don't break loop\n }\n\n // No gadgets executed - wrap text as synthetic TellUser result\n if (finalMessage.trim()) {\n const syntheticId = `gc_tell_${++this.syntheticInvocationCounter}`;\n this.conversation.addGadgetCallResult(\n \"TellUser\",\n { message: finalMessage, done: false, type: \"info\" },\n `ℹ️ ${finalMessage}`,\n syntheticId,\n );\n }\n\n // Handle text-only responses\n return await this.handleTextOnlyResponse(finalMessage);\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 type { ExecutionTree, NodeId } from \"../core/execution-tree.js\";\nimport type { ContentPart, ImageMimeType } from \"../core/input-content.js\";\nimport { detectImageMimeType, text, toBase64 } from \"../core/input-content.js\";\nimport type { MessageContent } from \"../core/messages.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { PromptTemplateConfig } from \"../core/prompt-config.js\";\nimport type { GadgetOrClass } from \"../gadgets/registry.js\";\nimport { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { ExecutionContext, SubagentConfigMap, SubagentEvent, 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 type { RetryConfig } from \"../core/retry.js\";\nimport { collectText, type EventHandlers } from \"./event-handlers.js\";\nimport type { AgentHooks, BeforeLLMCallAction, LLMCallControllerContext } from \"./hooks.js\";\n\n/**\n * Message for conversation history.\n * User messages can be text (string) or multimodal (ContentPart[]).\n */\nexport type HistoryMessage =\n | { user: string | ContentPart[] }\n | { assistant: string }\n | { system: string };\n\n/**\n * Context available to trailing message functions.\n * Provides iteration information for dynamic message generation.\n */\nexport type TrailingMessageContext = Pick<LLMCallControllerContext, \"iteration\" | \"maxIterations\">;\n\n/**\n * Trailing message can be a static string or a function that generates the message.\n * The function receives context about the current iteration.\n */\nexport type TrailingMessage = string | ((ctx: TrailingMessageContext) => 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?: PromptTemplateConfig;\n private gadgets: GadgetOrClass[] = [];\n private initialMessages: Array<{\n role: \"system\" | \"user\" | \"assistant\";\n content: MessageContent;\n }> = [];\n private requestHumanInput?: (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 defaultGadgetTimeoutMs?: number;\n private gadgetOutputLimit?: boolean;\n private gadgetOutputLimitPercent?: number;\n private compactionConfig?: CompactionConfig;\n private retryConfig?: RetryConfig;\n private signal?: AbortSignal;\n private trailingMessage?: TrailingMessage;\n private subagentConfig?: SubagentConfigMap;\n private subagentEventCallback?: (event: SubagentEvent) => void;\n // Tree context for subagent support - enables shared tree model\n // When a gadget calls withParentContext(ctx), it shares the parent's tree\n private parentContext?: {\n depth: number;\n tree?: ExecutionTree;\n nodeId?: NodeId;\n };\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 * .withPromptTemplateConfig({\n * mainInstruction: \"Use the gadget markers below:\",\n * rules: [\"Always use markers\", \"Never use function calling\"]\n * })\n * ```\n */\n withPromptTemplateConfig(config: PromptTemplateConfig): 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 * Clear any previously set conversation history.\n * Used before setting new cumulative history in REPL mode.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Reset history before setting new cumulative history\n * builder.clearHistory().withHistory(cumulativeHistory);\n * ```\n */\n clearHistory(): this {\n this.initialMessages = [];\n return this;\n }\n\n /**\n * Continue conversation from a previous agent's history.\n * Extracts full conversation history and sets it as initial messages.\n *\n * This is the recommended way to implement REPL session continuation.\n * It automatically handles history extraction and format conversion.\n *\n * @param agent - The previous agent to continue from\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // REPL loop with session continuity\n * let previousAgent: Agent | null = null;\n *\n * while (true) {\n * if (previousAgent) {\n * builder.continueFrom(previousAgent);\n * }\n * const agent = builder.ask(prompt);\n * await runAgent(agent);\n * previousAgent = agent;\n * }\n * ```\n */\n continueFrom(agent: Agent): this {\n const history = agent.getConversation().getConversationHistory();\n this.clearHistory();\n\n // Add each message from the previous agent's conversation\n for (const msg of history) {\n if (msg.role === \"user\") {\n this.initialMessages.push({ role: \"user\", content: msg.content });\n } else if (msg.role === \"assistant\") {\n this.initialMessages.push({ role: \"assistant\", content: msg.content });\n }\n // Skip system messages - they're regenerated from the builder's config\n }\n\n return this;\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.requestHumanInput = 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 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 * Configure retry behavior for LLM API calls.\n *\n * Retry is enabled by default with conservative settings (3 retries, exponential backoff).\n * Use this method to customize retry behavior for rate limits, timeouts, and transient errors.\n *\n * @param config - Retry configuration options\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Custom retry configuration\n * .withRetry({\n * retries: 5,\n * minTimeout: 2000,\n * maxTimeout: 60000,\n * })\n *\n * // With monitoring callbacks\n * .withRetry({\n * onRetry: (error, attempt) => {\n * console.log(`Retry ${attempt}: ${error.message}`);\n * },\n * onRetriesExhausted: (error, attempts) => {\n * alerting.warn(`Failed after ${attempts} attempts`);\n * }\n * })\n *\n * // Custom retry logic\n * .withRetry({\n * shouldRetry: (error) => error.message.includes('429'),\n * })\n * ```\n */\n withRetry(config: RetryConfig): this {\n this.retryConfig = { ...config, enabled: config.enabled ?? true };\n return this;\n }\n\n /**\n * Disable automatic retry for LLM API calls.\n *\n * By default, retry is enabled. Use this method to explicitly disable it.\n *\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withoutRetry() // Disable automatic retry\n * ```\n */\n withoutRetry(): this {\n this.retryConfig = { 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 * Set subagent configuration overrides.\n *\n * Subagent gadgets (like BrowseWeb) can read these settings from ExecutionContext\n * to inherit model and other options from the CLI configuration.\n *\n * @param config - Subagent configuration map keyed by gadget name\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withSubagentConfig({\n * BrowseWeb: { model: \"inherit\", maxIterations: 20, headless: true },\n * CodeAnalyzer: { model: \"sonnet\", maxIterations: 10 }\n * })\n * ```\n */\n withSubagentConfig(config: SubagentConfigMap): this {\n this.subagentConfig = config;\n return this;\n }\n\n /**\n * Set the callback for subagent events.\n *\n * Subagent gadgets (like BrowseWeb) can use ExecutionContext.onSubagentEvent\n * to report their internal LLM calls and gadget executions in real-time.\n * This callback receives those events, enabling hierarchical progress display.\n *\n * @param callback - Function to handle subagent events\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * .withSubagentEventCallback((event) => {\n * if (event.type === \"llm_call_start\") {\n * console.log(` Subagent LLM #${event.event.iteration} starting...`);\n * } else if (event.type === \"gadget_call\") {\n * console.log(` ⏵ ${event.event.call.gadgetName}...`);\n * }\n * })\n * ```\n */\n withSubagentEventCallback(callback: (event: SubagentEvent) => void): this {\n this.subagentEventCallback = callback;\n return this;\n }\n\n /**\n * Enable automatic subagent event forwarding to parent agent.\n *\n * When building a subagent inside a gadget, call this method to automatically\n * forward all LLM calls and gadget events to the parent agent. This enables\n * hierarchical progress display without any manual event handling.\n *\n * The method extracts `invocationId` and `onSubagentEvent` from the execution\n * context and sets up automatic forwarding via hooks and event wrapping.\n *\n * **NEW: Shared Tree Model** - When the parent provides an ExecutionTree via context,\n * the subagent shares that tree instead of creating its own. This enables:\n * - Unified cost tracking across all nesting levels\n * - Automatic media aggregation via `tree.getSubtreeMedia(nodeId)`\n * - Real-time visibility of nested execution in the parent\n *\n * **Signal Forwarding** - When parent context includes a signal, it's automatically\n * forwarded to the subagent for proper cancellation propagation.\n *\n * **Logger Inheritance** - When parent context includes a logger, it's inherited\n * by the subagent for consistent structured logging.\n *\n * @param ctx - ExecutionContext passed to the gadget's execute() method\n * @param depth - Nesting depth (default: 1 for direct child)\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // In a subagent gadget like BrowseWeb - ONE LINE enables auto-forwarding:\n * execute: async (params, ctx) => {\n * const agent = new AgentBuilder(client)\n * .withModel(model)\n * .withGadgets(Navigate, Click, Screenshot)\n * .withParentContext(ctx) // <-- This is all you need!\n * .ask(params.task);\n *\n * for await (const event of agent.run()) {\n * // Events automatically forwarded - just process normally\n * if (event.type === \"text\") {\n * result = event.content;\n * }\n * }\n *\n * // After subagent completes, costs are automatically aggregated\n * // No manual tracking needed - use tree methods:\n * const totalCost = ctx.tree?.getSubtreeCost(ctx.nodeId!);\n * const allMedia = ctx.tree?.getSubtreeMedia(ctx.nodeId!);\n * }\n * ```\n */\n withParentContext(ctx: ExecutionContext, depth = 1): this {\n // Capture tree context for shared tree model\n // This enables subagent events to flow through the parent's tree,\n // giving the TUI (and any tree subscribers) visibility into nested activity\n if (ctx.tree) {\n this.parentContext = {\n tree: ctx.tree,\n nodeId: ctx.nodeId,\n depth,\n };\n }\n\n // Set up subagent event callback to forward events to parent\n // This enables the parent agent to create child sessions and display nested activity\n if (ctx.onSubagentEvent && ctx.invocationId) {\n this.subagentEventCallback = (event) => {\n ctx.onSubagentEvent!({\n ...event,\n gadgetInvocationId: ctx.invocationId!,\n depth: depth,\n });\n };\n }\n\n // Auto-forward abort signal from parent for proper cancellation propagation\n if (ctx.signal && !this.signal) {\n this.signal = ctx.signal;\n }\n\n // Inherit logger from parent context for consistent logging across subagents\n if (ctx.logger && !this.logger) {\n this.logger = ctx.logger;\n }\n\n return this;\n }\n\n /**\n * Add an ephemeral trailing message that appears at the end of each LLM request.\n *\n * The message is NOT persisted to conversation history - it only appears in the\n * current LLM call. This is useful for injecting context-specific instructions\n * or reminders without polluting the conversation history.\n *\n * @param message - Static string or function that generates the message\n * @returns This builder for chaining\n *\n * @example\n * ```typescript\n * // Static message\n * .withTrailingMessage(\"Always respond in JSON format.\")\n *\n * // Dynamic message based on iteration\n * .withTrailingMessage((ctx) =>\n * `[Iteration ${ctx.iteration}/${ctx.maxIterations}] Stay focused on the task.`\n * )\n * ```\n */\n withTrailingMessage(message: TrailingMessage): this {\n this.trailingMessage = message;\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, including the invocation ID so the LLM can\n * reference previous calls when building dependencies.\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 * @param invocationId - Invocation ID (shown to LLM so it can reference for dependencies)\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 * 'gc_1'\n * )\n * ```\n */\n withSyntheticGadgetCall(\n gadgetName: string,\n parameters: Record<string, unknown>,\n result: string,\n invocationId: 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 (including invocation ID)\n this.initialMessages.push({\n role: \"assistant\",\n content: `${startPrefix}${gadgetName}:${invocationId}\\n${paramStr}\\n${endPrefix}`,\n });\n\n // User message with result (including invocation ID so LLM can reference it)\n this.initialMessages.push({\n role: \"user\",\n content: `Result (${invocationId}): ${result}`,\n });\n\n return this;\n }\n\n /**\n * Compose the final hooks, including trailing message injection if configured.\n *\n * Note: Subagent event visibility is now handled entirely by the ExecutionTree.\n * When a subagent uses withParentContext(ctx), it shares the parent's tree,\n * and all events are automatically visible to tree subscribers (like the TUI).\n */\n private composeHooks(): AgentHooks | undefined {\n const hooks = this.hooks;\n\n // Handle trailing message injection\n if (!this.trailingMessage) {\n return hooks;\n }\n\n const trailingMsg = this.trailingMessage;\n const existingBeforeLLMCall = hooks?.controllers?.beforeLLMCall;\n\n const trailingMessageController = async (\n ctx: LLMCallControllerContext,\n ): Promise<BeforeLLMCallAction> => {\n // Run existing beforeLLMCall first if present\n const result: BeforeLLMCallAction = existingBeforeLLMCall\n ? await existingBeforeLLMCall(ctx)\n : { action: \"proceed\" };\n\n // If action is \"skip\", don't inject trailing message\n if (result.action === \"skip\") {\n return result;\n }\n\n // Get messages (possibly already modified by existing controller)\n const messages = [...(result.modifiedOptions?.messages || ctx.options.messages)];\n\n // Generate trailing message content\n const content =\n typeof trailingMsg === \"function\"\n ? trailingMsg({ iteration: ctx.iteration, maxIterations: ctx.maxIterations })\n : trailingMsg;\n\n // Append as ephemeral user message\n messages.push({ role: \"user\", content });\n\n return {\n action: \"proceed\",\n modifiedOptions: { ...result.modifiedOptions, messages },\n };\n };\n\n return {\n ...hooks,\n controllers: {\n ...hooks?.controllers,\n beforeLLMCall: trailingMessageController,\n },\n };\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 /**\n * Build AgentOptions with the given user prompt.\n * Centralizes options construction for ask(), askWithImage(), and askWithContent().\n */\n private buildAgentOptions(userPrompt: string | ContentPart[]): AgentOptions {\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\n const registry = GadgetRegistry.from(this.gadgets);\n\n return {\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.composeHooks(),\n promptConfig: this.promptConfig,\n initialMessages: this.initialMessages,\n requestHumanInput: this.requestHumanInput,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n textOnlyHandler: this.textOnlyHandler,\n textWithGadgetsHandler: this.textWithGadgetsHandler,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n gadgetOutputLimit: this.gadgetOutputLimit,\n gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,\n compactionConfig: this.compactionConfig,\n retryConfig: this.retryConfig,\n signal: this.signal,\n subagentConfig: this.subagentConfig,\n onSubagentEvent: this.subagentEventCallback,\n // Tree context for shared tree model (subagents share parent's tree)\n parentTree: this.parentContext?.tree,\n parentNodeId: this.parentContext?.nodeId,\n baseDepth: this.parentContext ? (this.parentContext.depth ?? 0) + 1 : 0,\n };\n }\n\n ask(userPrompt: string): Agent {\n const options = this.buildAgentOptions(userPrompt);\n return new Agent(AGENT_INTERNAL_KEY, options);\n }\n\n /**\n * Build and create the agent with a multimodal user prompt (text + image).\n * Returns the Agent instance ready to run.\n *\n * @param textPrompt - Text prompt describing what to do with the image\n * @param imageData - Image data (Buffer, Uint8Array, or base64 string)\n * @param mimeType - Optional MIME type (auto-detected if not provided)\n * @returns Configured Agent instance\n *\n * @example\n * ```typescript\n * const agent = LLMist.createAgent()\n * .withModel(\"gpt-4o\")\n * .withSystem(\"You analyze images\")\n * .askWithImage(\n * \"What's in this image?\",\n * await fs.readFile(\"photo.jpg\")\n * );\n *\n * for await (const event of agent.run()) {\n * // handle events\n * }\n * ```\n */\n askWithImage(\n textPrompt: string,\n imageData: Buffer | Uint8Array | string,\n mimeType?: ImageMimeType,\n ): Agent {\n const imageBuffer =\n typeof imageData === \"string\" ? Buffer.from(imageData, \"base64\") : imageData;\n const detectedMime = mimeType ?? detectImageMimeType(imageBuffer);\n\n if (!detectedMime) {\n throw new Error(\n \"Could not detect image MIME type. Please provide the mimeType parameter explicitly.\",\n );\n }\n\n // Build multimodal content\n const userContent: ContentPart[] = [\n text(textPrompt),\n {\n type: \"image\",\n source: {\n type: \"base64\",\n mediaType: detectedMime,\n data: toBase64(imageBuffer),\n },\n },\n ];\n\n const options = this.buildAgentOptions(userContent);\n return new Agent(AGENT_INTERNAL_KEY, options);\n }\n\n /**\n * Build and return an Agent configured with multimodal content.\n * More flexible than askWithImage - accepts any combination of content parts.\n *\n * @param content - Array of content parts (text, images, audio)\n * @returns A configured Agent ready for execution\n *\n * @example\n * ```typescript\n * import { text, imageFromBuffer, audioFromBuffer } from \"llmist\";\n *\n * const agent = LLMist.createAgent()\n * .withModel(\"gemini:gemini-2.5-flash\")\n * .askWithContent([\n * text(\"Describe this image and transcribe the audio:\"),\n * imageFromBuffer(imageData),\n * audioFromBuffer(audioData),\n * ]);\n *\n * for await (const event of agent.run()) {\n * // handle events\n * }\n * ```\n */\n askWithContent(content: ContentPart[]): Agent {\n const options = this.buildAgentOptions(content);\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.composeHooks(),\n promptConfig: this.promptConfig,\n initialMessages: this.initialMessages,\n requestHumanInput: this.requestHumanInput,\n gadgetStartPrefix: this.gadgetStartPrefix,\n gadgetEndPrefix: this.gadgetEndPrefix,\n gadgetArgPrefix: this.gadgetArgPrefix,\n textOnlyHandler: this.textOnlyHandler,\n textWithGadgetsHandler: this.textWithGadgetsHandler,\n defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n gadgetOutputLimit: this.gadgetOutputLimit,\n gadgetOutputLimitPercent: this.gadgetOutputLimitPercent,\n compactionConfig: this.compactionConfig,\n retryConfig: this.retryConfig,\n signal: this.signal,\n subagentConfig: this.subagentConfig,\n onSubagentEvent: this.subagentEventCallback,\n // Tree context for shared tree model (subagents share parent's tree)\n parentTree: this.parentContext?.tree,\n parentNodeId: this.parentContext?.nodeId,\n baseDepth: this.parentContext ? (this.parentContext.depth ?? 0) + 1 : 0,\n };\n\n return new Agent(AGENT_INTERNAL_KEY, options);\n }\n}\n","// Re-export Zod's z for schema definitions\n// Using llmist's z ensures .describe() metadata is preserved in JSON schemas\nexport { z } from \"zod\";\n// Constants for gadget block format parsing\nexport {\n GADGET_ARG_PREFIX,\n GADGET_END_PREFIX,\n GADGET_START_PREFIX,\n} from \"./core/constants.js\";\n// Provider constants (for token estimation)\nexport { FALLBACK_CHARS_PER_TOKEN } from \"./providers/constants.js\";\n// Syntactic sugar: Agent builder and event handlers\nexport type { HistoryMessage, TrailingMessage, TrailingMessageContext } from \"./agent/builder.js\";\nexport { AgentBuilder } from \"./agent/builder.js\";\nexport type { EventHandlers } from \"./agent/event-handlers.js\";\nexport { collectEvents, collectText, runWithHandlers } from \"./agent/event-handlers.js\";\n// Syntactic sugar: Hook presets\nexport type { LoggingOptions } from \"./agent/hook-presets.js\";\nexport { HookPresets } from \"./agent/hook-presets.js\";\n// Agent infrastructure\n// New clean hooks system\nexport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n AgentOptions,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n // Interceptor contexts\n ChunkInterceptorContext,\n // Context compaction\n CompactionConfig,\n CompactionContext,\n CompactionEvent,\n CompactionResult,\n CompactionStats,\n CompactionStrategy,\n Controllers,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n // LLM Assistance Hints\n HintsConfig,\n IConversationManager,\n Interceptors,\n IterationHintOptions,\n // Controller contexts and actions\n LLMCallControllerContext,\n LLMErrorControllerContext,\n MessageInterceptorContext,\n MessageTurn,\n ObserveChunkContext,\n ObserveCompactionContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetStartContext,\n // Observer contexts\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n Observers,\n ParallelGadgetHintOptions,\n ResolvedCompactionConfig,\n // Gadget output limiting\n StoredOutput,\n StreamProcessingResult,\n StreamProcessorOptions,\n // Subagent context for hook observers\n SubagentContext,\n} from \"./agent/index.js\";\nexport {\n // Compaction exports\n CompactionManager,\n // Existing exports\n ConversationManager,\n // LLM Assistance Hints\n createHints,\n DEFAULT_COMPACTION_CONFIG,\n DEFAULT_SUMMARIZATION_PROMPT,\n GadgetOutputStore,\n HybridStrategy,\n iterationProgressHint,\n parallelGadgetHint,\n SlidingWindowStrategy,\n StreamProcessor,\n SummarizationStrategy,\n} from \"./agent/index.js\";\nexport type { LLMistOptions } from \"./core/client.js\";\nexport { LLMist } from \"./core/client.js\";\n// Error utilities\nexport { isAbortError } from \"./core/errors.js\";\n// Agent class (for type references)\nexport { Agent } from \"./agent/agent.js\";\n\n// Retry configuration for LLM API calls\nexport type { RetryConfig, ResolvedRetryConfig } from \"./core/retry.js\";\nexport {\n DEFAULT_RETRY_CONFIG,\n formatLLMError,\n isRetryableError,\n resolveRetryConfig,\n} from \"./core/retry.js\";\n\n// Execution Tree - first-class model for nested subagent support\nexport type {\n AddGadgetParams,\n AddLLMCallParams,\n CompleteGadgetParams,\n CompleteLLMCallParams,\n ExecutionNode,\n ExecutionNodeType,\n GadgetNode,\n GadgetState,\n LLMCallNode,\n NodeId,\n} from \"./core/execution-tree.js\";\nexport { ExecutionTree } from \"./core/execution-tree.js\";\n\n// Unified execution events with tree context\nexport type {\n BaseExecutionEvent,\n CompactionEvent as TreeCompactionEvent,\n ExecutionEvent,\n ExecutionEventType,\n GadgetCallEvent,\n GadgetCompleteEvent,\n GadgetErrorEvent,\n GadgetEvent,\n GadgetSkippedEvent as TreeGadgetSkippedEvent,\n GadgetStartEvent,\n HumanInputRequiredEvent,\n LLMCallCompleteEvent,\n LLMCallErrorEvent,\n LLMCallStartEvent,\n LLMCallStreamEvent,\n LLMEvent,\n StreamCompleteEvent,\n TextEvent,\n} from \"./core/execution-events.js\";\nexport {\n filterByDepth,\n filterByParent,\n filterRootEvents,\n groupByParent,\n isGadgetEvent,\n isLLMEvent,\n isRootEvent,\n isSubagentEvent,\n} from \"./core/execution-events.js\";\n\n// Input content types for multimodal messages\nexport type {\n AudioContentPart,\n AudioMimeType,\n AudioSource,\n ContentPart,\n ImageBase64Source,\n ImageContentPart,\n ImageMimeType,\n ImageSource,\n ImageUrlSource,\n TextContentPart,\n} from \"./core/input-content.js\";\nexport {\n audioFromBase64,\n audioFromBuffer,\n detectAudioMimeType,\n detectImageMimeType,\n imageFromBase64,\n imageFromBuffer,\n imageFromUrl,\n isAudioPart,\n isDataUrl,\n isImagePart,\n isTextPart,\n parseDataUrl,\n text,\n toBase64,\n} from \"./core/input-content.js\";\n\nexport type { LLMMessage, MessageContent, MessageRole } from \"./core/messages.js\";\nexport { extractMessageText, LLMMessageBuilder, normalizeMessageContent } from \"./core/messages.js\";\n// Model catalog\nexport type {\n CostEstimate,\n ModelFeatures,\n ModelLimits,\n ModelPricing,\n ModelSpec,\n} from \"./core/model-catalog.js\";\nexport { ModelRegistry } from \"./core/model-registry.js\";\n// Syntactic sugar: Model shortcuts and quick methods\nexport {\n getModelId,\n getProvider,\n hasProviderPrefix,\n MODEL_ALIASES,\n resolveModel,\n} from \"./core/model-shortcuts.js\";\n// Vision namespace for one-shot image analysis\nexport type { VisionAnalyzeOptions, VisionAnalyzeResult } from \"./core/namespaces/vision.js\";\n// Media generation types (image, speech)\nexport type {\n ImageGenerationOptions,\n ImageGenerationResult,\n ImageModelSpec,\n SpeechGenerationOptions,\n SpeechGenerationResult,\n SpeechModelSpec,\n} from \"./core/media-types.js\";\nexport type {\n LLMGenerationOptions,\n LLMStream,\n LLMStreamChunk,\n ModelDescriptor,\n ProviderIdentifier,\n TokenUsage,\n} from \"./core/options.js\";\nexport { ModelIdentifierParser } from \"./core/options.js\";\nexport type {\n HintContext,\n HintTemplate,\n PromptContext,\n PromptTemplate,\n PromptTemplateConfig,\n} from \"./core/prompt-config.js\";\nexport {\n DEFAULT_HINTS,\n DEFAULT_PROMPTS,\n resolveHintTemplate,\n resolvePromptTemplate,\n resolveRulesTemplate,\n} from \"./core/prompt-config.js\";\nexport type { TextGenerationOptions } from \"./core/quick-methods.js\";\nexport { complete, stream } from \"./core/quick-methods.js\";\nexport type { CreateGadgetConfig } from \"./gadgets/create-gadget.js\";\nexport { createGadget } from \"./gadgets/create-gadget.js\";\n// Gadget infrastructure\nexport {\n AbortException,\n HumanInputRequiredException,\n TaskCompletionSignal,\n TimeoutException,\n} from \"./gadgets/exceptions.js\";\nexport { GadgetExecutor } from \"./gadgets/executor.js\";\nexport { AbstractGadget } from \"./gadgets/gadget.js\";\n// Gadget output viewer (for custom output store integration)\nexport { createGadgetOutputViewer } from \"./gadgets/output-viewer.js\";\nexport { GadgetCallParser } from \"./gadgets/parser.js\";\nexport type { GadgetClass, GadgetOrClass } from \"./gadgets/registry.js\";\nexport { GadgetRegistry } from \"./gadgets/registry.js\";\n\n// Syntactic sugar: Typed gadgets and helpers\nexport type { GadgetConfig } from \"./gadgets/typed-gadget.js\";\nexport { Gadget } from \"./gadgets/typed-gadget.js\";\nexport type {\n CostReportingLLMist,\n ExecutionContext,\n GadgetExample,\n GadgetExecuteResult,\n GadgetExecuteResultWithMedia,\n GadgetExecuteReturn,\n GadgetExecutionResult,\n GadgetMediaOutput,\n GadgetSkippedEvent,\n // Host exports for external gadgets\n HostExports,\n // Subagent LLM call info (for CLI/TUI display)\n LLMCallInfo,\n MediaKind,\n MediaMetadata,\n ParsedGadgetCall,\n StoredMedia,\n StreamEvent,\n // Subagent config types\n SubagentConfig,\n SubagentConfigMap,\n // Subagent event types\n SubagentEvent,\n SubagentStreamEvent,\n TextOnlyAction,\n TextOnlyContext,\n TextOnlyCustomHandler,\n TextOnlyGadgetConfig,\n TextOnlyHandler,\n TextOnlyStrategy,\n} from \"./gadgets/types.js\";\n// Response and media output helpers for gadgets\nexport {\n // Response formatting\n gadgetError,\n gadgetSuccess,\n getErrorMessage,\n withErrorHandling,\n // Media output\n createMediaOutput,\n resultWithAudio,\n resultWithFile,\n resultWithImage,\n resultWithImages,\n resultWithMedia,\n} from \"./gadgets/helpers.js\";\n\n// Host exports helper for external gadgets\nimport type { ExecutionContext, HostExports } from \"./gadgets/types.js\";\n\n/**\n * Get host llmist exports from execution context.\n *\n * External gadgets MUST use this instead of importing classes directly from 'llmist'\n * to ensure they use the same version as the host CLI, enabling proper tree sharing\n * and avoiding the \"dual-package problem\".\n *\n * @param ctx - The execution context passed to gadget.execute()\n * @returns The host's llmist exports (AgentBuilder, Gadget, etc.)\n * @throws Error if ctx or ctx.hostExports is undefined\n *\n * @example\n * ```typescript\n * import { getHostExports, Gadget, z } from 'llmist';\n * import type { ExecutionContext } from 'llmist';\n *\n * class BrowseWeb extends Gadget({\n * name: 'BrowseWeb',\n * description: 'Browse a website autonomously',\n * schema: z.object({ task: z.string(), url: z.string() }),\n * }) {\n * async execute(params: this['params'], ctx?: ExecutionContext) {\n * // Get host's AgentBuilder to ensure tree sharing works correctly\n * const { AgentBuilder } = getHostExports(ctx!);\n *\n * const agent = new AgentBuilder()\n * .withParentContext(ctx!)\n * .withGadgets(Navigate, Click, Screenshot)\n * .ask(params.task);\n *\n * for await (const event of agent.run()) {\n * // Events flow through host's shared tree\n * }\n * }\n * }\n * ```\n */\nexport function getHostExports(ctx: ExecutionContext): HostExports {\n if (!ctx?.hostExports) {\n throw new Error(\n \"hostExports not available. Gadgets that create subagents must be run \" +\n \"via llmist agent, not standalone. Ensure you are using llmist >= 6.2.0.\",\n );\n }\n return ctx.hostExports;\n}\n// Media storage for gadget outputs\nexport { MediaStore } from \"./gadgets/media-store.js\";\nexport type { ValidationIssue, ValidationResult } from \"./gadgets/validation.js\";\nexport { validateAndApplyDefaults, validateGadgetParams } from \"./gadgets/validation.js\";\n// Schema utilities\nexport { schemaToJSONSchema } from \"./gadgets/schema-to-json.js\";\nexport { validateGadgetSchema } from \"./gadgets/schema-validator.js\";\nexport type { LoggerOptions } from \"./logging/logger.js\";\nexport { createLogger, defaultLogger } from \"./logging/logger.js\";\n// Re-export Logger type for external gadgets that need to type ctx.logger\nexport type { ILogObj, Logger } from \"tslog\";\n\n// Utility functions for subagent gadgets\nexport type { ResolveValueOptions } from \"./utils/config-resolver.js\";\nexport {\n resolveConfig,\n resolveSubagentModel,\n resolveSubagentTimeout,\n resolveValue,\n} from \"./utils/config-resolver.js\";\nexport {\n AnthropicMessagesProvider,\n createAnthropicProviderFromEnv,\n} from \"./providers/anthropic.js\";\nexport { discoverProviderAdapters } from \"./providers/discovery.js\";\nexport { createGeminiProviderFromEnv, GeminiGenerativeProvider } from \"./providers/gemini.js\";\nexport { createOpenAIProviderFromEnv, OpenAIChatProvider } from \"./providers/openai.js\";\nexport type { ProviderAdapter } from \"./providers/provider.js\";\n\n// ============================================================================\n// Formatting Utilities\n// ============================================================================\nexport {\n format,\n formatBytes,\n formatDate,\n formatDuration,\n truncate,\n} from \"./utils/format.js\";\n\n// ============================================================================\n// Timing Utilities\n// ============================================================================\nexport type { RetryOptions } from \"./utils/timing.js\";\nexport {\n humanDelay,\n randomDelay,\n timing,\n withRetry,\n withTimeout,\n} from \"./utils/timing.js\";\n\n// ============================================================================\n// Session Management\n// ============================================================================\nexport type { ISessionManager } from \"./session/index.js\";\nexport { BaseSessionManager, SimpleSessionManager } from \"./session/index.js\";\n\n// ============================================================================\n// Subagent Helpers\n// ============================================================================\nexport type { SubagentOptions } from \"./agent/subagent.js\";\nexport { createSubagent, hasHostExports } from \"./agent/subagent.js\";\n\n// ============================================================================\n// Package Manifest Types\n// ============================================================================\nexport type {\n GadgetFactoryExports,\n LLMistPackageManifest,\n PresetDefinition,\n SessionManifestEntry,\n SubagentManifestEntry,\n} from \"./package/index.js\";\nexport {\n getPresetGadgets,\n getSubagent,\n hasPreset,\n hasSubagents,\n listPresets,\n listSubagents,\n parseManifest,\n} from \"./package/index.js\";\n","/**\n * Ready-to-use hook configurations for common monitoring, logging, and debugging tasks.\n *\n * HookPresets provide instant observability without writing custom hooks. They're the\n * fastest way to add monitoring to your agents during development and production.\n *\n * ## Available Presets\n *\n * - **logging(options?)** - Log LLM calls and gadget execution\n * - **timing()** - Measure execution time for operations\n * - **tokenTracking()** - Track cumulative token usage and costs\n * - **progressTracking(options?)** - Track progress with iterations, tokens, cost, and timing (SHOWCASE)\n * - **errorLogging()** - Log detailed error information\n * - **silent()** - No output (useful for testing)\n * - **monitoring(options?)** - All-in-one preset combining logging, timing, tokens, and errors\n * - **merge(...hookSets)** - Combine multiple hook configurations\n *\n * ## Quick Start\n *\n * @example\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * // Basic logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging())\n * .ask(\"Your prompt\");\n *\n * // Full monitoring suite (recommended for development)\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring({ verbose: true }))\n * .ask(\"Your prompt\");\n *\n * // Combine multiple presets\n * await LLMist.createAgent()\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * .ask(\"Your prompt\");\n *\n * // Environment-based configuration\n * const hooks = process.env.NODE_ENV === 'production'\n * ? HookPresets.merge(HookPresets.errorLogging(), HookPresets.tokenTracking())\n * : HookPresets.monitoring({ verbose: true });\n *\n * await LLMist.createAgent()\n * .withHooks(hooks)\n * .ask(\"Your prompt\");\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md | Full documentation}\n */\n\nimport type { ModelRegistry } from \"../core/model-registry.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n/**\n * Options for logging preset.\n */\nexport interface LoggingOptions {\n /** Include verbose details like parameters and results */\n verbose?: boolean;\n}\n\n/**\n * Progress statistics reported by progressTracking preset.\n *\n * Contains cumulative metrics across all LLM calls in the agent session,\n * useful for building progress UI, cost monitoring, and performance tracking.\n */\nexport interface ProgressStats {\n /** Current iteration number (increments on each LLM call start) */\n currentIteration: number;\n\n /** Total number of completed LLM calls */\n totalCalls: number;\n\n /** Cumulative input tokens across all calls */\n totalInputTokens: number;\n\n /** Cumulative output tokens across all calls */\n totalOutputTokens: number;\n\n /** Total tokens (input + output) */\n totalTokens: number;\n\n /** Cumulative cost in USD (includes LLM and gadget costs; requires modelRegistry for LLM cost estimation) */\n totalCost: number;\n\n /** Elapsed time in seconds since first call */\n elapsedSeconds: number;\n}\n\n/**\n * Options for progressTracking preset.\n *\n * Controls how progress data is tracked and reported during agent execution.\n */\nexport interface ProgressTrackingOptions {\n /**\n * Model registry for cost calculation.\n *\n * If provided, enables automatic cost estimation based on token usage\n * and model pricing data. Without it, totalCost will always be 0.\n *\n * @example\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * const client = LLMist.create();\n * const hooks = HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry // Enable cost tracking\n * });\n * ```\n */\n modelRegistry?: ModelRegistry;\n\n /**\n * Callback invoked after each LLM call completion with cumulative stats.\n *\n * Use this to update progress UI, log metrics, or track budgets in real-time.\n *\n * @example\n * ```typescript\n * HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * console.log(`Iteration #${stats.currentIteration}`);\n * console.log(`Cost so far: $${stats.totalCost.toFixed(4)}`);\n * console.log(`Elapsed: ${stats.elapsedSeconds}s`);\n * }\n * })\n * ```\n */\n onProgress?: (stats: ProgressStats) => void;\n\n /**\n * Whether to log progress to console after each LLM call.\n *\n * When enabled, prints a summary line with tokens, cost, and elapsed time.\n * Useful for quick debugging without implementing a custom callback.\n *\n * Default: false\n *\n * @example\n * ```typescript\n * // Quick console-based progress tracking\n * HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * logProgress: true // Log to console\n * })\n * // Output: 📊 Progress: Iteration #2 | 1,234 tokens | $0.0056 | 12.3s\n * ```\n */\n logProgress?: boolean;\n}\n\n/**\n * Common hook presets.\n */\nexport class HookPresets {\n /**\n * Logs LLM calls and gadget execution to console with optional verbosity.\n *\n * **Output (basic mode):**\n * - LLM call start/complete events with iteration numbers\n * - Gadget execution start/complete with gadget names\n * - Token counts when available\n *\n * **Output (verbose mode):**\n * - All basic mode output\n * - Full gadget parameters (formatted JSON)\n * - Full gadget results\n * - Complete LLM response text\n *\n * **Use cases:**\n * - Basic development debugging and execution flow visibility\n * - Understanding agent decision-making and tool usage\n * - Troubleshooting gadget invocations\n *\n * **Performance:** Minimal overhead. Console writes are synchronous but fast.\n *\n * @param options - Logging options\n * @param options.verbose - Include full parameters and results. Default: false\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging())\n * .ask(\"Calculate 15 * 23\");\n * // Output: [LLM] Starting call (iteration 0)\n * // [GADGET] Executing Calculator\n * // [GADGET] Completed Calculator\n * // [LLM] Completed (tokens: 245)\n * ```\n *\n * @example\n * ```typescript\n * // Verbose logging with full details\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging({ verbose: true }))\n * .ask(\"Calculate 15 * 23\");\n * // Output includes: parameters, results, and full responses\n * ```\n *\n * @example\n * ```typescript\n * // Environment-based verbosity\n * const isDev = process.env.NODE_ENV === 'development';\n * .withHooks(HookPresets.logging({ verbose: isDev }))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsloggingoptions | Full documentation}\n */\n static logging(options: LoggingOptions = {}): AgentHooks {\n return {\n observers: {\n onLLMCallStart: async (ctx) => {\n console.log(`[LLM] Starting call (iteration ${ctx.iteration})`);\n },\n onLLMCallComplete: async (ctx) => {\n const tokens = ctx.usage?.totalTokens ?? \"unknown\";\n console.log(`[LLM] Completed (tokens: ${tokens})`);\n if (options.verbose && ctx.finalMessage) {\n console.log(`[LLM] Response: ${ctx.finalMessage}`);\n }\n },\n onGadgetExecutionStart: async (ctx) => {\n console.log(`[GADGET] Executing ${ctx.gadgetName}`);\n if (options.verbose) {\n console.log(`[GADGET] Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n }\n },\n onGadgetExecutionComplete: async (ctx) => {\n console.log(`[GADGET] Completed ${ctx.gadgetName}`);\n if (options.verbose) {\n const display = ctx.error ?? ctx.finalResult ?? \"(no result)\";\n console.log(`[GADGET] Result: ${display}`);\n }\n },\n },\n };\n }\n\n /**\n * Measures and logs execution time for LLM calls and gadgets.\n *\n * **Output:**\n * - Duration in milliseconds with ⏱️ emoji for each operation\n * - Separate timing for each LLM iteration\n * - Separate timing for each gadget execution\n *\n * **Use cases:**\n * - Performance profiling and optimization\n * - Identifying slow operations (LLM calls vs gadget execution)\n * - Monitoring response times in production\n * - Capacity planning and SLA tracking\n *\n * **Performance:** Negligible overhead. Uses Date.now() for timing measurements.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic timing\n * await LLMist.createAgent()\n * .withHooks(HookPresets.timing())\n * .withGadgets(Weather, Database)\n * .ask(\"What's the weather in NYC?\");\n * // Output: ⏱️ LLM call took 1234ms\n * // ⏱️ Gadget Weather took 567ms\n * // ⏱️ LLM call took 890ms\n * ```\n *\n * @example\n * ```typescript\n * // Combined with logging for full context\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing()\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Correlate performance with cost\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstiming | Full documentation}\n */\n static timing(): AgentHooks {\n const timings = new Map<string, number>();\n\n return {\n observers: {\n onLLMCallStart: async (ctx) => {\n timings.set(`llm-${ctx.iteration}`, Date.now());\n },\n onLLMCallComplete: async (ctx) => {\n const start = timings.get(`llm-${ctx.iteration}`);\n if (start) {\n const duration = Date.now() - start;\n console.log(`⏱️ LLM call took ${duration}ms`);\n timings.delete(`llm-${ctx.iteration}`);\n }\n },\n onGadgetExecutionStart: async (ctx) => {\n const key = `gadget-${ctx.gadgetName}-${Date.now()}`;\n timings.set(key, Date.now());\n // Store key for lookup in complete handler\n (ctx as any)._timingKey = key;\n },\n onGadgetExecutionComplete: async (ctx) => {\n const key = (ctx as any)._timingKey;\n if (key) {\n const start = timings.get(key);\n if (start) {\n const duration = Date.now() - start;\n console.log(`⏱️ Gadget ${ctx.gadgetName} took ${duration}ms`);\n timings.delete(key);\n }\n }\n },\n },\n };\n }\n\n /**\n * Tracks cumulative token usage across all LLM calls.\n *\n * **Output:**\n * - Per-call token count with 📊 emoji\n * - Cumulative total across all calls\n * - Call count for average calculations\n *\n * **Use cases:**\n * - Cost monitoring and budget tracking\n * - Optimizing prompts to reduce token usage\n * - Comparing token efficiency across different approaches\n * - Real-time cost estimation\n *\n * **Performance:** Minimal overhead. Simple counter increments.\n *\n * **Note:** Token counts depend on the provider's response. Some providers\n * may not include usage data, in which case counts won't be logged.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic token tracking\n * await LLMist.createAgent()\n * .withHooks(HookPresets.tokenTracking())\n * .ask(\"Summarize this document...\");\n * // Output: 📊 Tokens this call: 1,234\n * // 📊 Total tokens: 1,234 (across 1 calls)\n * // 📊 Tokens this call: 567\n * // 📊 Total tokens: 1,801 (across 2 calls)\n * ```\n *\n * @example\n * ```typescript\n * // Cost calculation with custom hook\n * let totalTokens = 0;\n * .withHooks(HookPresets.merge(\n * HookPresets.tokenTracking(),\n * {\n * observers: {\n * onLLMCallComplete: async (ctx) => {\n * totalTokens += ctx.usage?.totalTokens ?? 0;\n * const cost = (totalTokens / 1_000_000) * 3.0; // $3 per 1M tokens\n * console.log(`💰 Estimated cost: $${cost.toFixed(4)}`);\n * },\n * },\n * }\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstokentracking | Full documentation}\n */\n static tokenTracking(): AgentHooks {\n let totalTokens = 0;\n let totalCalls = 0;\n\n return {\n observers: {\n onLLMCallComplete: async (ctx) => {\n totalCalls++;\n if (ctx.usage?.totalTokens) {\n totalTokens += ctx.usage.totalTokens;\n console.log(`📊 Tokens this call: ${ctx.usage.totalTokens}`);\n console.log(`📊 Total tokens: ${totalTokens} (across ${totalCalls} calls)`);\n }\n },\n },\n };\n }\n\n /**\n * Tracks comprehensive progress metrics including iterations, tokens, cost, and timing.\n *\n * **This preset showcases llmist's core capabilities by demonstrating:**\n * - Observer pattern for non-intrusive monitoring\n * - Integration with ModelRegistry for cost estimation\n * - Callback-based architecture for flexible UI updates\n * - Provider-agnostic token and cost tracking\n *\n * Unlike `tokenTracking()` which only logs to console, this preset provides\n * structured data through callbacks, making it perfect for building custom UIs,\n * dashboards, or progress indicators (like the llmist CLI).\n *\n * **Output (when logProgress: true):**\n * - Iteration number and call count\n * - Cumulative token usage (input + output)\n * - Cumulative cost in USD (requires modelRegistry)\n * - Elapsed time in seconds\n *\n * **Use cases:**\n * - Building CLI progress indicators with live updates\n * - Creating web dashboards with real-time metrics\n * - Budget monitoring and cost alerts\n * - Performance tracking and optimization\n * - Custom logging to external systems (Datadog, CloudWatch, etc.)\n *\n * **Performance:** Minimal overhead. Uses Date.now() for timing and optional\n * ModelRegistry.estimateCost() which is O(1) lookup. Callback invocation is\n * synchronous and fast.\n *\n * @param options - Progress tracking options\n * @param options.modelRegistry - ModelRegistry for cost estimation (optional)\n * @param options.onProgress - Callback invoked after each LLM call (optional)\n * @param options.logProgress - Log progress to console (default: false)\n * @returns Hook configuration with progress tracking observers\n *\n * @example\n * ```typescript\n * // Basic usage with callback (RECOMMENDED - used by llmist CLI)\n * import { LLMist, HookPresets } from 'llmist';\n *\n * const client = LLMist.create();\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * // Update your UI with stats\n * console.log(`#${stats.currentIteration} | ${stats.totalTokens} tokens | $${stats.totalCost.toFixed(4)}`);\n * }\n * }))\n * .withGadgets(Calculator)\n * .ask(\"Calculate 15 * 23\");\n * // Output: #1 | 245 tokens | $0.0012\n * ```\n *\n * @example\n * ```typescript\n * // Console logging mode (quick debugging)\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * logProgress: true // Simple console output\n * }))\n * .ask(\"Your prompt\");\n * // Output: 📊 Progress: Iteration #1 | 245 tokens | $0.0012 | 1.2s\n * ```\n *\n * @example\n * ```typescript\n * // Budget monitoring with alerts\n * const BUDGET_USD = 0.10;\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * if (stats.totalCost > BUDGET_USD) {\n * throw new Error(`Budget exceeded: $${stats.totalCost.toFixed(4)}`);\n * }\n * }\n * }))\n * .ask(\"Long running task...\");\n * ```\n *\n * @example\n * ```typescript\n * // Web dashboard integration\n * let progressBar: HTMLElement;\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * // Update web UI in real-time\n * progressBar.textContent = `Iteration ${stats.currentIteration}`;\n * progressBar.dataset.cost = stats.totalCost.toFixed(4);\n * progressBar.dataset.tokens = stats.totalTokens.toString();\n * }\n * }))\n * .ask(\"Your prompt\");\n * ```\n *\n * @example\n * ```typescript\n * // External logging (Datadog, CloudWatch, etc.)\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: async (stats) => {\n * await metrics.gauge('llm.iteration', stats.currentIteration);\n * await metrics.gauge('llm.cost', stats.totalCost);\n * await metrics.gauge('llm.tokens', stats.totalTokens);\n * }\n * }))\n * .ask(\"Your prompt\");\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsprogresstrackingoptions | Full documentation}\n * @see {@link ProgressTrackingOptions} for detailed options\n * @see {@link ProgressStats} for the callback data structure\n */\n static progressTracking(options?: ProgressTrackingOptions): AgentHooks {\n const { modelRegistry, onProgress, logProgress = false } = options ?? {};\n\n // State tracking - follows same pattern as tokenTracking()\n let totalCalls = 0;\n let currentIteration = 0;\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCost = 0;\n let totalGadgetCost = 0;\n const startTime = Date.now();\n\n return {\n observers: {\n // Track iteration on each LLM call start\n onLLMCallStart: async (ctx) => {\n currentIteration++;\n },\n\n // Accumulate metrics and report progress on each LLM call completion\n onLLMCallComplete: async (ctx) => {\n totalCalls++;\n\n // Track token usage from provider response\n if (ctx.usage) {\n totalInputTokens += ctx.usage.inputTokens;\n totalOutputTokens += ctx.usage.outputTokens;\n\n // Calculate cost using ModelRegistry (core llmist feature)\n // This showcases integration with llmist's pricing catalog\n if (modelRegistry) {\n try {\n // Extract model name from provider:model format\n // Example: \"openai:gpt-4o\" -> \"gpt-4o\"\n const modelName = ctx.options.model.includes(\":\")\n ? ctx.options.model.split(\":\")[1]\n : ctx.options.model;\n\n // Use core's estimateCost() for accurate pricing\n const costEstimate = modelRegistry.estimateCost(\n modelName,\n ctx.usage.inputTokens,\n ctx.usage.outputTokens,\n );\n\n if (costEstimate) {\n totalCost += costEstimate.totalCost;\n }\n } catch (error) {\n // Graceful degradation - log error but don't crash\n // This follows llmist's principle of non-intrusive monitoring\n if (logProgress) {\n console.warn(`⚠️ Cost estimation failed:`, error);\n }\n }\n }\n }\n\n // Build comprehensive progress stats (LLM + gadget costs combined)\n const stats: ProgressStats = {\n currentIteration,\n totalCalls,\n totalInputTokens,\n totalOutputTokens,\n totalTokens: totalInputTokens + totalOutputTokens,\n totalCost: totalCost + totalGadgetCost,\n elapsedSeconds: Number(((Date.now() - startTime) / 1000).toFixed(1)),\n };\n\n // Invoke callback if provided (used by CLI and custom UIs)\n if (onProgress) {\n onProgress(stats);\n }\n\n // Optional console logging for quick debugging\n if (logProgress) {\n const formattedTokens =\n stats.totalTokens >= 1000\n ? `${(stats.totalTokens / 1000).toFixed(1)}k`\n : `${stats.totalTokens}`;\n\n const formattedCost = stats.totalCost > 0 ? `$${stats.totalCost.toFixed(4)}` : \"$0\";\n\n console.log(\n `📊 Progress: Iteration #${stats.currentIteration} | ${formattedTokens} tokens | ${formattedCost} | ${stats.elapsedSeconds}s`,\n );\n }\n },\n\n // Track gadget execution costs\n onGadgetExecutionComplete: async (ctx) => {\n if (ctx.cost && ctx.cost > 0) {\n totalGadgetCost += ctx.cost;\n }\n },\n },\n };\n }\n\n /**\n * Logs detailed error information for debugging and troubleshooting.\n *\n * **Output:**\n * - LLM errors with ❌ emoji, including model and recovery status\n * - Gadget errors with full context (parameters, error message)\n * - Separate logging for LLM and gadget failures\n *\n * **Use cases:**\n * - Troubleshooting production issues\n * - Understanding error patterns and frequency\n * - Debugging error recovery behavior\n * - Collecting error metrics for monitoring\n *\n * **Performance:** Minimal overhead. Only logs when errors occur.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic error logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.errorLogging())\n * .withGadgets(Database)\n * .ask(\"Fetch user data\");\n * // Output (on LLM error): ❌ LLM Error (iteration 1): Rate limit exceeded\n * // Model: gpt-5-nano\n * // Recovered: true\n * // Output (on gadget error): ❌ Gadget Error: Database\n * // Error: Connection timeout\n * // Parameters: {...}\n * ```\n *\n * @example\n * ```typescript\n * // Combine with monitoring for full context\n * .withHooks(HookPresets.merge(\n * HookPresets.monitoring(), // Includes errorLogging\n * customErrorAnalytics\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Error analytics collection\n * const errors: any[] = [];\n * .withHooks(HookPresets.merge(\n * HookPresets.errorLogging(),\n * {\n * observers: {\n * onLLMCallError: async (ctx) => {\n * errors.push({ type: 'llm', error: ctx.error, recovered: ctx.recovered });\n * },\n * },\n * }\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetserrorlogging | Full documentation}\n */\n static errorLogging(): AgentHooks {\n return {\n observers: {\n onLLMCallError: async (ctx) => {\n console.error(`❌ LLM Error (iteration ${ctx.iteration}):`, ctx.error.message);\n console.error(` Model: ${ctx.options.model}`);\n console.error(` Recovered: ${ctx.recovered}`);\n },\n onGadgetExecutionComplete: async (ctx) => {\n if (ctx.error) {\n console.error(`❌ Gadget Error: ${ctx.gadgetName}`);\n console.error(` Error: ${ctx.error}`);\n console.error(` Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n }\n },\n },\n };\n }\n\n /**\n * Tracks context compaction events.\n *\n * **Output:**\n * - Compaction events with 🗜️ emoji\n * - Strategy name, tokens before/after, and savings\n * - Cumulative statistics\n *\n * **Use cases:**\n * - Monitoring long-running conversations\n * - Understanding when and how compaction occurs\n * - Debugging context management issues\n *\n * **Performance:** Minimal overhead. Simple console output.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * await LLMist.createAgent()\n * .withHooks(HookPresets.compactionTracking())\n * .ask(\"Your prompt\");\n * ```\n */\n static compactionTracking(): AgentHooks {\n return {\n observers: {\n onCompaction: async (ctx) => {\n const saved = ctx.event.tokensBefore - ctx.event.tokensAfter;\n const percent = ((saved / ctx.event.tokensBefore) * 100).toFixed(1);\n console.log(\n `🗜️ Compaction (${ctx.event.strategy}): ${ctx.event.tokensBefore} → ${ctx.event.tokensAfter} tokens (saved ${saved}, ${percent}%)`,\n );\n console.log(` Messages: ${ctx.event.messagesBefore} → ${ctx.event.messagesAfter}`);\n if (ctx.stats.totalCompactions > 1) {\n console.log(\n ` Cumulative: ${ctx.stats.totalCompactions} compactions, ${ctx.stats.totalTokensSaved} tokens saved`,\n );\n }\n },\n },\n };\n }\n\n /**\n * Returns empty hook configuration for clean output without any logging.\n *\n * **Output:**\n * - None. Returns {} (empty object).\n *\n * **Use cases:**\n * - Clean test output without console noise\n * - Production environments where logging is handled externally\n * - Baseline for custom hook development\n * - Temporary disable of all hook output\n *\n * **Performance:** Zero overhead. No-op hook configuration.\n *\n * @returns Empty hook configuration\n *\n * @example\n * ```typescript\n * // Clean test output\n * describe('Agent tests', () => {\n * it('should calculate correctly', async () => {\n * const result = await LLMist.createAgent()\n * .withHooks(HookPresets.silent()) // No console output\n * .withGadgets(Calculator)\n * .askAndCollect(\"What is 15 times 23?\");\n *\n * expect(result).toContain(\"345\");\n * });\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Conditional silence based on environment\n * const isTesting = process.env.NODE_ENV === 'test';\n * .withHooks(isTesting ? HookPresets.silent() : HookPresets.monitoring())\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetssilent | Full documentation}\n */\n static silent(): AgentHooks {\n return {};\n }\n\n /**\n * Combines multiple hook configurations into one.\n *\n * Merge allows you to compose preset and custom hooks for modular monitoring\n * configurations. Understanding merge behavior is crucial for proper composition.\n *\n * **Merge behavior:**\n * - **Observers:** Composed - all handlers run sequentially in order\n * - **Interceptors:** Last one wins - only the last interceptor applies\n * - **Controllers:** Last one wins - only the last controller applies\n *\n * **Why interceptors/controllers don't compose:**\n * - Interceptors have different signatures per method, making composition impractical\n * - Controllers return specific actions that can't be meaningfully combined\n * - Only observers support composition because they're read-only and independent\n *\n * **Use cases:**\n * - Combining multiple presets (logging + timing + tokens)\n * - Adding custom hooks to presets\n * - Building modular, reusable monitoring configurations\n * - Environment-specific hook composition\n *\n * **Performance:** Minimal overhead for merging. Runtime performance depends on merged hooks.\n *\n * @param hookSets - Variable number of hook configurations to merge\n * @returns Single merged hook configuration with composed/overridden handlers\n *\n * @example\n * ```typescript\n * // Combine multiple presets\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * // All observers from all three presets will run\n * ```\n *\n * @example\n * ```typescript\n * // Add custom observer to preset (both run)\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * {\n * observers: {\n * onLLMCallComplete: async (ctx) => {\n * await saveMetrics({ tokens: ctx.usage?.totalTokens });\n * },\n * },\n * }\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Multiple interceptors (last wins!)\n * .withHooks(HookPresets.merge(\n * {\n * interceptors: {\n * interceptTextChunk: (chunk) => chunk.toUpperCase(), // Ignored\n * },\n * },\n * {\n * interceptors: {\n * interceptTextChunk: (chunk) => chunk.toLowerCase(), // This wins\n * },\n * }\n * ))\n * // Result: text will be lowercase\n * ```\n *\n * @example\n * ```typescript\n * // Modular environment-based configuration\n * const baseHooks = HookPresets.errorLogging();\n * const devHooks = HookPresets.merge(baseHooks, HookPresets.monitoring({ verbose: true }));\n * const prodHooks = HookPresets.merge(baseHooks, HookPresets.tokenTracking());\n *\n * const hooks = process.env.NODE_ENV === 'production' ? prodHooks : devHooks;\n * .withHooks(hooks)\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmergehooksets | Full documentation}\n */\n static merge(...hookSets: AgentHooks[]): AgentHooks {\n const merged: AgentHooks = {\n observers: {},\n interceptors: {},\n controllers: {},\n };\n\n // Compose observers: run all handlers for the same event\n for (const hooks of hookSets) {\n if (hooks.observers) {\n for (const [key, handler] of Object.entries(hooks.observers)) {\n const typedKey = key as keyof typeof hooks.observers;\n if (merged.observers![typedKey]) {\n // Compose: run both existing and new handler\n const existing = merged.observers![typedKey];\n merged.observers![typedKey] = async (ctx: any) => {\n await existing(ctx);\n await handler(ctx);\n };\n } else {\n merged.observers![typedKey] = handler as any;\n }\n }\n }\n\n // Interceptors: last one wins (complex signatures make composition impractical)\n // Each interceptor has different parameters (chunk, message, parameters, etc.)\n // so we can't meaningfully compose them like we do with observers\n if (hooks.interceptors) {\n Object.assign(merged.interceptors!, hooks.interceptors);\n }\n\n // Controllers: last one wins (can't meaningfully compose boolean returns)\n if (hooks.controllers) {\n Object.assign(merged.controllers!, hooks.controllers);\n }\n }\n\n return merged;\n }\n\n /**\n * Composite preset combining logging, timing, tokenTracking, and errorLogging.\n *\n * This is the recommended preset for development and initial production deployments,\n * providing comprehensive observability with a single method call.\n *\n * **Includes:**\n * - All output from `logging()` preset (with optional verbosity)\n * - All output from `timing()` preset (execution times)\n * - All output from `tokenTracking()` preset (token usage)\n * - All output from `errorLogging()` preset (error details)\n *\n * **Output format:**\n * - Event logging: [LLM]/[GADGET] messages\n * - Timing: ⏱️ emoji with milliseconds\n * - Tokens: 📊 emoji with per-call and cumulative counts\n * - Errors: ❌ emoji with full error details\n *\n * **Use cases:**\n * - Full observability during development\n * - Comprehensive monitoring in production\n * - One-liner for complete agent visibility\n * - Troubleshooting and debugging with full context\n *\n * **Performance:** Combined overhead of all four presets, but still minimal in practice.\n *\n * @param options - Monitoring options\n * @param options.verbose - Passed to logging() preset for detailed output. Default: false\n * @returns Merged hook configuration combining all monitoring presets\n *\n * @example\n * ```typescript\n * // Basic monitoring (recommended for development)\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring())\n * .withGadgets(Calculator, Weather)\n * .ask(\"What is 15 times 23, and what's the weather in NYC?\");\n * // Output: All events, timing, tokens, and errors in one place\n * ```\n *\n * @example\n * ```typescript\n * // Verbose monitoring with full details\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring({ verbose: true }))\n * .ask(\"Your prompt\");\n * // Output includes: parameters, results, and complete responses\n * ```\n *\n * @example\n * ```typescript\n * // Environment-based monitoring\n * const isDev = process.env.NODE_ENV === 'development';\n * .withHooks(HookPresets.monitoring({ verbose: isDev }))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmonitoringoptions | Full documentation}\n */\n static monitoring(options: LoggingOptions = {}): AgentHooks {\n return HookPresets.merge(\n HookPresets.logging(options),\n HookPresets.timing(),\n HookPresets.tokenTracking(),\n HookPresets.errorLogging(),\n );\n }\n}\n","/**\n * Context Compaction System\n *\n * Automatically manages conversation context to prevent context window overflow\n * in long-running agent conversations.\n *\n * Features:\n * - Automatic threshold monitoring (default: 80% of context window)\n * - Multiple strategies: sliding-window, summarization, hybrid (default)\n * - Full visibility via StreamEvents and hooks\n * - Enabled by default with sensible defaults\n *\n * @example\n * ```typescript\n * // Auto-enabled with defaults\n * const agent = await LLMist.createAgent()\n * .withModel('sonnet')\n * .ask('Help me...');\n *\n * // Custom configuration\n * const agent = await LLMist.createAgent()\n * .withModel('gpt-4')\n * .withCompaction({\n * triggerThresholdPercent: 70,\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 */\n\n// Configuration\nexport {\n type CompactionConfig,\n type CompactionEvent,\n type CompactionStats,\n DEFAULT_COMPACTION_CONFIG,\n DEFAULT_SUMMARIZATION_PROMPT,\n type ResolvedCompactionConfig,\n resolveCompactionConfig,\n} from \"./config.js\";\n// Manager\nexport { CompactionManager } from \"./manager.js\";\n\n// Strategy implementations\nexport {\n HybridStrategy,\n SlidingWindowStrategy,\n SummarizationStrategy,\n} from \"./strategies/index.js\";\n// Strategy interface and utilities\nexport {\n type CompactionContext,\n type CompactionResult,\n type CompactionStrategy,\n flattenTurns,\n groupIntoTurns,\n type MessageTurn,\n} from \"./strategy.js\";\n","/**\n * Agent module - Composable, single-responsibility architecture for LLM agents.\n * This module provides a cleaner alternative to the monolithic AgentLoop.\n */\n\nexport type { AgentOptions } from \"./agent.js\";\n// Context compaction\nexport {\n type CompactionConfig,\n type CompactionContext,\n type CompactionEvent,\n CompactionManager,\n type CompactionResult,\n type CompactionStats,\n type CompactionStrategy,\n DEFAULT_COMPACTION_CONFIG,\n DEFAULT_SUMMARIZATION_PROMPT,\n HybridStrategy,\n type MessageTurn,\n type ResolvedCompactionConfig,\n SlidingWindowStrategy,\n SummarizationStrategy,\n} from \"./compaction/index.js\";\nexport { ConversationManager } from \"./conversation-manager.js\";\n// Gadget output limiting\nexport type { StoredOutput } from \"./gadget-output-store.js\";\nexport { GadgetOutputStore } from \"./gadget-output-store.js\";\n// LLM Assistance Hints\nexport {\n createHints,\n type HintsConfig,\n type IterationHintOptions,\n iterationProgressHint,\n type ParallelGadgetHintOptions,\n parallelGadgetHint,\n} from \"./hints.js\";\n// New clean hooks system\nexport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n // Interceptor contexts\n ChunkInterceptorContext,\n Controllers,\n // Dependency skip controller\n DependencySkipAction,\n DependencySkipControllerContext,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n Interceptors,\n // Controller contexts and actions\n LLMCallControllerContext,\n LLMErrorControllerContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveCompactionContext,\n ObserveGadgetCompleteContext,\n // Gadget skip observer\n ObserveGadgetSkippedContext,\n ObserveGadgetStartContext,\n // Observer contexts\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n Observers,\n // Subagent context for distinguishing subagent events in hooks\n SubagentContext,\n} from \"./hooks.js\";\nexport type { IConversationManager } from \"./interfaces.js\";\n// StreamProcessor for advanced use cases\nexport {\n type StreamProcessingResult,\n StreamProcessor,\n type StreamProcessorOptions,\n} from \"./stream-processor.js\";\n","/**\n * LLM Assistance Hints System\n *\n * Provides reusable hook factories that inject helpful context and coaching\n * messages to guide LLM behavior during agentic execution.\n *\n * ## Two Types of Hints\n *\n * 1. **Proactive (beforeLLMCall)**: Inject context before LLM generates response\n * - Example: Iteration progress (\"You're on iteration 3/10\")\n *\n * 2. **Reactive (afterLLMCall)**: Coach based on what LLM did\n * - Example: \"Tip: You can call multiple gadgets in parallel\"\n *\n * ## Usage\n *\n * ```typescript\n * import { createHints, iterationProgressHint, parallelGadgetHint } from \"llmist\";\n *\n * // Option 1: Use individual hints\n * const agent = new AgentBuilder()\n * .withHooks(HookPresets.merge(\n * iterationProgressHint({ timing: \"late\" }),\n * parallelGadgetHint(),\n * ))\n * .build();\n *\n * // Option 2: Use convenience factory\n * const agent = new AgentBuilder()\n * .withHooks(createHints({\n * iterationProgress: { timing: \"late\" },\n * parallelGadgets: true,\n * }))\n * .build();\n * ```\n *\n * @module agent/hints\n */\n\nimport {\n DEFAULT_HINTS,\n type HintContext,\n type HintTemplate,\n resolveHintTemplate,\n} from \"../core/prompt-config.js\";\nimport { HookPresets } from \"./hook-presets.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n// ============================================================================\n// CONFIGURATION TYPES\n// ============================================================================\n\n/**\n * Options for iteration progress hint.\n */\nexport interface IterationHintOptions {\n /**\n * When to show the hint.\n * - \"always\": Show on every iteration\n * - \"late\": Show only when >= 50% through iterations\n * - \"urgent\": Show only when >= 80% through iterations\n * @default \"always\"\n */\n timing?: \"always\" | \"late\" | \"urgent\";\n\n /**\n * Whether to include urgency indicators for late iterations.\n * Adds extra text when running low on iterations.\n * @default true\n */\n showUrgency?: boolean;\n\n /**\n * Custom template. Supports placeholders: {iteration}, {maxIterations}, {remaining}\n * Or a function receiving HintContext.\n * @default DEFAULT_HINTS.iterationProgressHint\n */\n template?: HintTemplate;\n}\n\n/**\n * Options for parallel gadget usage hint.\n */\nexport interface ParallelGadgetHintOptions {\n /**\n * Minimum number of gadget calls to consider \"efficient\".\n * If response has fewer calls, hint will suggest parallelization.\n * @default 2\n */\n minGadgetsForEfficiency?: number;\n\n /**\n * Custom message when single gadget detected.\n * @default DEFAULT_HINTS.parallelGadgetsHint\n */\n message?: string;\n\n /**\n * Whether to enable this hint.\n * @default true\n */\n enabled?: boolean;\n}\n\n/**\n * Combined hints configuration for createHints().\n */\nexport interface HintsConfig {\n /**\n * Enable iteration progress hints.\n * Pass `true` for defaults, or options object for customization.\n */\n iterationProgress?: boolean | IterationHintOptions;\n\n /**\n * Enable parallel gadget hints.\n * Pass `true` for defaults, or options object for customization.\n */\n parallelGadgets?: boolean | ParallelGadgetHintOptions;\n\n /**\n * Additional custom hooks to merge.\n */\n custom?: AgentHooks[];\n}\n\n// ============================================================================\n// HINT FACTORIES\n// ============================================================================\n\n/**\n * Creates a proactive hint that informs the LLM about iteration progress.\n *\n * This hint is injected before each LLM call (via beforeLLMCall controller),\n * helping the LLM understand how much \"budget\" remains for completing the task.\n *\n * @param options - Configuration options\n * @returns AgentHooks that can be merged with other hooks\n *\n * @example\n * ```typescript\n * // Basic usage - show on every iteration\n * const hooks = iterationProgressHint();\n *\n * // Show only when running low on iterations\n * const hooks = iterationProgressHint({ timing: \"late\" });\n *\n * // Custom template\n * const hooks = iterationProgressHint({\n * template: \"Turn {iteration} of {maxIterations}. {remaining} turns left.\",\n * });\n * ```\n */\nexport function iterationProgressHint(options?: IterationHintOptions): AgentHooks {\n const { timing = \"always\", showUrgency = true, template } = options ?? {};\n\n return {\n controllers: {\n beforeLLMCall: async (ctx) => {\n const iteration = ctx.iteration + 1; // 1-based for user-friendliness\n const maxIterations = ctx.maxIterations;\n const progress = iteration / maxIterations;\n\n // Check timing condition\n if (timing === \"late\" && progress < 0.5) {\n return { action: \"proceed\" };\n }\n if (timing === \"urgent\" && progress < 0.8) {\n return { action: \"proceed\" };\n }\n\n // Build hint context with all fields populated\n const remaining = maxIterations - iteration;\n const hintContext: HintContext = {\n iteration,\n maxIterations,\n remaining,\n };\n\n // Resolve template\n let hint = resolveHintTemplate(template, DEFAULT_HINTS.iterationProgressHint, hintContext);\n\n // Add urgency indicator if late in iterations\n if (showUrgency && progress >= 0.8) {\n hint += \" ⚠️ Running low on iterations - focus on completing the task.\";\n }\n\n // Inject as system-level context in messages\n const messages = [...ctx.options.messages];\n\n // Find last user message index (compatible with older ES targets)\n let lastUserIndex = -1;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n lastUserIndex = i;\n break;\n }\n }\n\n if (lastUserIndex >= 0) {\n // Insert hint after the last user message\n messages.splice(lastUserIndex + 1, 0, {\n role: \"user\",\n content: `[System Hint] ${hint}`,\n });\n } else {\n // No user messages found - append hint at the end\n messages.push({\n role: \"user\",\n content: `[System Hint] ${hint}`,\n });\n }\n\n return {\n action: \"proceed\",\n modifiedOptions: { messages },\n };\n },\n },\n };\n}\n\n/**\n * Creates a reactive hint that encourages parallel gadget usage.\n *\n * This hint analyzes the LLM's response and, if only a single gadget was called,\n * appends a reminder that multiple gadgets can be used in parallel for efficiency.\n *\n * @param options - Configuration options\n * @returns AgentHooks that can be merged with other hooks\n *\n * @example\n * ```typescript\n * // Basic usage\n * const hooks = parallelGadgetHint();\n *\n * // Custom threshold and message\n * const hooks = parallelGadgetHint({\n * minGadgetsForEfficiency: 3,\n * message: \"Consider calling multiple gadgets at once!\",\n * });\n * ```\n */\nexport function parallelGadgetHint(options?: ParallelGadgetHintOptions): AgentHooks {\n const {\n minGadgetsForEfficiency = 2,\n message = DEFAULT_HINTS.parallelGadgetsHint,\n enabled = true,\n } = options ?? {};\n\n return {\n controllers: {\n afterLLMCall: async (ctx) => {\n if (!enabled) {\n return { action: \"continue\" };\n }\n\n // Only hint if gadgets were called but below efficiency threshold\n if (ctx.gadgetCallCount > 0 && ctx.gadgetCallCount < minGadgetsForEfficiency) {\n return {\n action: \"append_messages\",\n messages: [\n {\n role: \"user\",\n content: `[System Hint] ${message}`,\n },\n ],\n };\n }\n\n return { action: \"continue\" };\n },\n },\n };\n}\n\n// ============================================================================\n// CONVENIENCE FACTORY\n// ============================================================================\n\n/**\n * Creates combined hints from a configuration object.\n *\n * This is a convenience function that creates and merges multiple hints\n * based on a simple configuration object.\n *\n * @param config - Configuration for which hints to enable\n * @returns Merged AgentHooks\n *\n * @example\n * ```typescript\n * const hooks = createHints({\n * iterationProgress: { timing: \"late\" },\n * parallelGadgets: true,\n * });\n *\n * const agent = new AgentBuilder()\n * .withHooks(HookPresets.merge(existingHooks, hooks))\n * .build();\n * ```\n */\nexport function createHints(config: HintsConfig): AgentHooks {\n const hooksToMerge: AgentHooks[] = [];\n\n // Iteration progress hint\n if (config.iterationProgress) {\n const options = typeof config.iterationProgress === \"boolean\" ? {} : config.iterationProgress;\n hooksToMerge.push(iterationProgressHint(options));\n }\n\n // Parallel gadgets hint\n if (config.parallelGadgets) {\n const options = typeof config.parallelGadgets === \"boolean\" ? {} : config.parallelGadgets;\n hooksToMerge.push(parallelGadgetHint(options));\n }\n\n // Custom hooks\n if (config.custom) {\n hooksToMerge.push(...config.custom);\n }\n\n return HookPresets.merge(...hooksToMerge);\n}\n","/**\n * Error utilities for llmist.\n */\n\n/**\n * Detects if an error is an abort/cancellation error from any provider.\n *\n * Different providers throw different error types when a request is aborted:\n * - Standard: `AbortError` (name) - from fetch/AbortController\n * - Anthropic SDK: `APIConnectionAbortedError`\n * - OpenAI SDK: `APIUserAbortError`\n * - Generic: errors with \"abort\", \"cancelled\", or \"canceled\" in the message\n *\n * @param error - The error to check\n * @returns `true` if the error is an abort-related error, `false` otherwise\n *\n * @example\n * ```typescript\n * import { isAbortError } from \"@llmist/core/errors\";\n *\n * const controller = new AbortController();\n *\n * try {\n * for await (const chunk of client.stream({ signal: controller.signal, ... })) {\n * // Process chunks...\n * }\n * } catch (error) {\n * if (isAbortError(error)) {\n * console.log(\"Request was cancelled - this is expected\");\n * return; // Graceful exit\n * }\n * // Re-throw unexpected errors\n * throw error;\n * }\n * ```\n */\nexport function isAbortError(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n\n // Standard AbortError (from fetch/AbortController)\n if (error.name === \"AbortError\") return true;\n\n // Anthropic SDK\n if (error.name === \"APIConnectionAbortedError\") return true;\n\n // OpenAI SDK\n if (error.name === \"APIUserAbortError\") return true;\n\n // Message-based detection (fallback for edge cases)\n const message = error.message.toLowerCase();\n if (message.includes(\"abort\")) return true;\n if (message.includes(\"cancelled\")) return true;\n if (message.includes(\"canceled\")) return true;\n\n return false;\n}\n","/**\n * Unified event types for the Execution Tree.\n *\n * All events carry full tree context (nodeId, parentId, depth, path).\n * No special SubagentEvent wrapper needed - subagent events are regular\n * events with depth > 0.\n *\n * @module core/execution-events\n */\n\nimport type { GadgetMediaOutput } from \"../gadgets/types.js\";\nimport type { LLMMessage } from \"./messages.js\";\nimport type { TokenUsage } from \"./options.js\";\n\n// =============================================================================\n// Base Event Properties\n// =============================================================================\n\n/**\n * Base properties shared by all execution events.\n * Every event carries full tree context.\n */\nexport interface BaseExecutionEvent {\n /** Monotonically increasing event ID */\n eventId: number;\n /** Event timestamp */\n timestamp: number;\n /** Node that emitted this event */\n nodeId: string;\n /** Parent node ID (null for root events) */\n parentId: string | null;\n /** Nesting depth (0 = root, 1 = child, etc.) */\n depth: number;\n /** Full path from root to this node */\n path: string[];\n}\n\n// =============================================================================\n// LLM Call Events\n// =============================================================================\n\n/**\n * Emitted when an LLM call starts.\n */\nexport interface LLMCallStartEvent extends BaseExecutionEvent {\n type: \"llm_call_start\";\n /** Iteration number within agent loop (1-indexed) */\n iteration: number;\n /** Model identifier */\n model: string;\n /** Request messages */\n request?: LLMMessage[];\n}\n\n/**\n * Emitted for each streaming chunk from LLM.\n */\nexport interface LLMCallStreamEvent extends BaseExecutionEvent {\n type: \"llm_call_stream\";\n /** Text chunk */\n chunk: string;\n}\n\n/**\n * Emitted when an LLM call completes successfully.\n */\nexport interface LLMCallCompleteEvent extends BaseExecutionEvent {\n type: \"llm_call_complete\";\n /** Complete response text */\n response: string;\n /** Token usage */\n usage?: TokenUsage;\n /** Finish reason from LLM */\n finishReason?: string | null;\n /** Cost in USD */\n cost?: number;\n}\n\n/**\n * Emitted when an LLM call fails.\n */\nexport interface LLMCallErrorEvent extends BaseExecutionEvent {\n type: \"llm_call_error\";\n /** The error that occurred */\n error: Error;\n /** Whether the error was recovered by a controller */\n recovered: boolean;\n}\n\n// =============================================================================\n// Gadget Events\n// =============================================================================\n\n/**\n * Emitted when a gadget call is parsed from LLM output (before execution).\n */\nexport interface GadgetCallEvent extends BaseExecutionEvent {\n type: \"gadget_call\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Parameters */\n parameters: Record<string, unknown>;\n /** Dependencies (other invocation IDs) */\n dependencies: string[];\n}\n\n/**\n * Emitted when gadget execution starts.\n */\nexport interface GadgetStartEvent extends BaseExecutionEvent {\n type: \"gadget_start\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n}\n\n/**\n * Emitted when gadget execution completes successfully.\n */\nexport interface GadgetCompleteEvent extends BaseExecutionEvent {\n type: \"gadget_complete\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Result string */\n result: string;\n /** Execution time in ms */\n executionTimeMs: number;\n /** Cost in USD */\n cost?: number;\n /** Media outputs */\n media?: GadgetMediaOutput[];\n}\n\n/**\n * Emitted when gadget execution fails.\n */\nexport interface GadgetErrorEvent extends BaseExecutionEvent {\n type: \"gadget_error\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Error message */\n error: string;\n /** Execution time in ms */\n executionTimeMs: number;\n}\n\n/**\n * Emitted when a gadget is skipped.\n */\nexport interface GadgetSkippedEvent extends BaseExecutionEvent {\n type: \"gadget_skipped\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Reason for skipping */\n reason: \"dependency_failed\" | \"controller_skip\";\n /** Error message (combines reason and failedDependencyError for consistency with GadgetErrorEvent) */\n error: string;\n /** Failed dependency invocation ID (if dependency_failed) */\n failedDependency?: string;\n /** Error message from failed dependency */\n failedDependencyError?: string;\n}\n\n// =============================================================================\n// Text Events\n// =============================================================================\n\n/**\n * Emitted for text output from LLM (pure notification, not a tree node).\n */\nexport interface TextEvent extends BaseExecutionEvent {\n type: \"text\";\n /** Text content */\n content: string;\n}\n\n// =============================================================================\n// Other Events\n// =============================================================================\n\n/**\n * Emitted when context compaction occurs.\n */\nexport interface CompactionEvent extends BaseExecutionEvent {\n type: \"compaction\";\n /** Tokens before compaction */\n tokensBefore: number;\n /** Tokens after compaction */\n tokensAfter: number;\n /** Compaction strategy used */\n strategy: string;\n /** Messages removed */\n messagesRemoved: number;\n}\n\n/**\n * Emitted when human input is required.\n */\nexport interface HumanInputRequiredEvent extends BaseExecutionEvent {\n type: \"human_input_required\";\n /** Question for the user */\n question: string;\n /** Gadget name requesting input */\n gadgetName: string;\n /** Invocation ID */\n invocationId: string;\n}\n\n/**\n * Emitted when the execution stream completes.\n */\nexport interface StreamCompleteEvent extends BaseExecutionEvent {\n type: \"stream_complete\";\n /** Whether any gadgets were executed */\n didExecuteGadgets: boolean;\n /** Whether the agent loop should break */\n shouldBreakLoop: boolean;\n /** Total cost for this iteration */\n iterationCost?: number;\n}\n\n// =============================================================================\n// Union Types\n// =============================================================================\n\n/**\n * All LLM-related events.\n */\nexport type LLMEvent =\n | LLMCallStartEvent\n | LLMCallStreamEvent\n | LLMCallCompleteEvent\n | LLMCallErrorEvent;\n\n/**\n * All gadget-related events.\n */\nexport type GadgetEvent =\n | GadgetCallEvent\n | GadgetStartEvent\n | GadgetCompleteEvent\n | GadgetErrorEvent\n | GadgetSkippedEvent;\n\n/**\n * Union of all execution events.\n */\nexport type ExecutionEvent =\n | LLMCallStartEvent\n | LLMCallStreamEvent\n | LLMCallCompleteEvent\n | LLMCallErrorEvent\n | GadgetCallEvent\n | GadgetStartEvent\n | GadgetCompleteEvent\n | GadgetErrorEvent\n | GadgetSkippedEvent\n | TextEvent\n | CompactionEvent\n | HumanInputRequiredEvent\n | StreamCompleteEvent;\n\n/**\n * Event type discriminator.\n */\nexport type ExecutionEventType = ExecutionEvent[\"type\"] | \"*\";\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Check if an event is an LLM event.\n */\nexport function isLLMEvent(event: ExecutionEvent): event is LLMEvent {\n return event.type.startsWith(\"llm_call_\");\n}\n\n/**\n * Check if an event is a gadget event.\n */\nexport function isGadgetEvent(event: ExecutionEvent): event is GadgetEvent {\n return event.type.startsWith(\"gadget_\");\n}\n\n/**\n * Check if an event is from a subagent (nested execution).\n */\nexport function isSubagentEvent(event: ExecutionEvent): boolean {\n return event.depth > 0;\n}\n\n/**\n * Check if an event is from the root agent.\n */\nexport function isRootEvent(event: ExecutionEvent): boolean {\n return event.depth === 0;\n}\n\n// =============================================================================\n// Event Filtering Utilities\n// =============================================================================\n\n/**\n * Filter events by depth.\n */\nexport function filterByDepth(events: ExecutionEvent[], depth: number): ExecutionEvent[] {\n return events.filter((e) => e.depth === depth);\n}\n\n/**\n * Filter events by parent node.\n */\nexport function filterByParent(events: ExecutionEvent[], parentId: string): ExecutionEvent[] {\n return events.filter((e) => e.parentId === parentId);\n}\n\n/**\n * Filter events to only root-level events.\n */\nexport function filterRootEvents(events: ExecutionEvent[]): ExecutionEvent[] {\n return filterByDepth(events, 0);\n}\n\n/**\n * Group events by their parent node.\n */\nexport function groupByParent(events: ExecutionEvent[]): Map<string | null, ExecutionEvent[]> {\n const groups = new Map<string | null, ExecutionEvent[]>();\n\n for (const event of events) {\n const parentId = event.parentId;\n if (!groups.has(parentId)) {\n groups.set(parentId, []);\n }\n groups.get(parentId)?.push(event);\n }\n\n return groups;\n}\n","/**\n * Helper functions for gadget authors.\n *\n * This module provides:\n * 1. Response formatting helpers (gadgetSuccess, gadgetError, withErrorHandling)\n * 2. Media output helpers (resultWithImage, resultWithAudio, etc.)\n *\n * @example Response helpers\n * ```typescript\n * import { gadgetSuccess, gadgetError, withErrorHandling } from \"llmist\";\n *\n * // Simple response formatting\n * return gadgetSuccess({ url: \"https://example.com\", title: \"Example\" });\n * return gadgetError(\"Element not found\", { selector: \".missing\" });\n *\n * // Automatic error handling wrapper\n * const safeExecute = withErrorHandling(async (params) => {\n * // your code here - errors are automatically caught and formatted\n * return gadgetSuccess({ result: \"done\" });\n * });\n * ```\n *\n * @example Media output helpers\n * ```typescript\n * import { resultWithImage } from \"llmist\";\n *\n * const screenshotGadget = createGadget({\n * name: \"Screenshot\",\n * schema: z.object({ url: z.string() }),\n * execute: async ({ url }) => {\n * const screenshot = await takeScreenshot(url);\n * return resultWithImage(\n * `Screenshot of ${url}`,\n * screenshot,\n * { description: \"Webpage screenshot\" }\n * );\n * },\n * });\n * ```\n */\n\nimport { detectAudioMimeType, detectImageMimeType } from \"../core/input-content.js\";\nimport type {\n ExecutionContext,\n GadgetExecuteResultWithMedia,\n GadgetMediaOutput,\n MediaKind,\n MediaMetadata,\n} from \"./types.js\";\n\n// ============================================================================\n// Response Formatting Helpers\n// ============================================================================\n\n/**\n * Create a success response as JSON string.\n *\n * This is a convenience helper for gadgets that return JSON-formatted responses.\n * It automatically adds `success: true` and stringifies the result.\n *\n * @param data - Additional data to include in the response\n * @returns JSON string with success: true and provided data\n *\n * @example\n * ```typescript\n * return gadgetSuccess({ url: page.url(), title: await page.title() });\n * // Returns: '{\"success\":true,\"url\":\"...\",\"title\":\"...\"}'\n * ```\n */\nexport function gadgetSuccess(data: Record<string, unknown> = {}): string {\n return JSON.stringify({ success: true, ...data });\n}\n\n/**\n * Create an error response as JSON string.\n *\n * This is a convenience helper for gadgets that return JSON-formatted errors.\n * It stringifies the error message and any additional details.\n *\n * @param message - Error message\n * @param details - Additional error details (e.g., suggestions, context)\n * @returns JSON string with error message and details\n *\n * @example\n * ```typescript\n * return gadgetError(\"Element not found\", { selector: \".missing\", suggestions: [\"Try #id instead\"] });\n * // Returns: '{\"error\":\"Element not found\",\"selector\":\".missing\",\"suggestions\":[...]}'\n * ```\n */\nexport function gadgetError(message: string, details?: Record<string, unknown>): string {\n return JSON.stringify({ error: message, ...details });\n}\n\n/**\n * Safely extract error message from unknown error type.\n *\n * Handles both Error instances and other thrown values.\n *\n * @param error - Unknown error value\n * @returns String error message\n */\nexport function getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Wrap a gadget execute function with automatic error handling.\n *\n * This higher-order function catches any errors thrown during execution\n * and converts them to properly formatted error responses.\n *\n * @param execute - The execute function to wrap\n * @returns A wrapped function that catches errors and returns gadgetError responses\n *\n * @example\n * ```typescript\n * const safeExecute = withErrorHandling(async (params: MyParams) => {\n * // Your code here - if it throws, error is caught and formatted\n * const result = await riskyOperation(params.id);\n * return gadgetSuccess({ result });\n * });\n *\n * // In gadget:\n * execute(params) {\n * return safeExecute(params);\n * }\n * ```\n */\nexport function withErrorHandling<TParams>(\n execute: (params: TParams, ctx?: ExecutionContext) => Promise<string> | string,\n): (params: TParams, ctx?: ExecutionContext) => Promise<string> {\n return async (params: TParams, ctx?: ExecutionContext): Promise<string> => {\n try {\n return await execute(params, ctx);\n } catch (error) {\n return gadgetError(getErrorMessage(error));\n }\n };\n}\n\n// ============================================================================\n// Media Output Helpers\n// ============================================================================\n\n/**\n * Create a GadgetMediaOutput from raw data.\n *\n * @param kind - Type of media\n * @param data - Raw binary data (Buffer or Uint8Array)\n * @param mimeType - MIME type string\n * @param options - Optional description, metadata, and fileName\n * @returns A GadgetMediaOutput ready to include in results\n */\nexport function createMediaOutput(\n kind: MediaKind,\n data: Buffer | Uint8Array,\n mimeType: string,\n options?: { description?: string; metadata?: MediaMetadata; fileName?: string },\n): GadgetMediaOutput {\n const buffer = data instanceof Buffer ? data : Buffer.from(data);\n return {\n kind,\n data: buffer.toString(\"base64\"),\n mimeType,\n description: options?.description,\n metadata: options?.metadata,\n fileName: options?.fileName,\n };\n}\n\n/**\n * Create a result with multiple media outputs.\n *\n * @param result - Text result string\n * @param media - Array of GadgetMediaOutput items (must not be empty)\n * @param cost - Optional cost in USD\n * @returns A GadgetExecuteResultWithMedia\n * @throws Error if media array is empty\n *\n * @example\n * ```typescript\n * return resultWithMedia(\n * \"Generated 2 charts\",\n * [\n * createMediaOutput(\"image\", barChartPng, \"image/png\", { description: \"Bar chart\" }),\n * createMediaOutput(\"image\", pieChartPng, \"image/png\", { description: \"Pie chart\" }),\n * ],\n * 0.002\n * );\n * ```\n */\nexport function resultWithMedia(\n result: string,\n media: GadgetMediaOutput[],\n cost?: number,\n): GadgetExecuteResultWithMedia {\n if (media.length === 0) {\n throw new Error(\"resultWithMedia: media array cannot be empty\");\n }\n return {\n result,\n media,\n cost,\n };\n}\n\n/**\n * Options for resultWithImage helper.\n */\nexport interface ImageOptions {\n /** MIME type (auto-detected if not provided) */\n mimeType?: string;\n /** Human-readable description */\n description?: string;\n /** Image dimensions and other metadata */\n metadata?: MediaMetadata;\n /** Cost in USD */\n cost?: number;\n /** Filename to use when saving (if not provided, auto-generated) */\n fileName?: string;\n}\n\n/**\n * Create a result with a single image output.\n *\n * @param result - Text result string\n * @param imageData - Raw image data (PNG, JPEG, GIF, WebP)\n * @param options - Optional MIME type, description, metadata, cost\n * @returns A GadgetExecuteResultWithMedia\n *\n * @example\n * ```typescript\n * const screenshot = await page.screenshot({ type: \"png\" });\n * return resultWithImage(\n * \"Screenshot captured\",\n * screenshot,\n * { description: \"Homepage screenshot\", metadata: { width: 1920, height: 1080 } }\n * );\n * ```\n */\nexport function resultWithImage(\n result: string,\n imageData: Buffer | Uint8Array,\n options?: ImageOptions,\n): GadgetExecuteResultWithMedia {\n const buffer = imageData instanceof Buffer ? imageData : Buffer.from(imageData);\n const mimeType = options?.mimeType ?? detectImageMimeType(buffer);\n\n if (!mimeType) {\n throw new Error(\n \"Could not detect image MIME type. Please provide mimeType explicitly in options.\",\n );\n }\n\n return {\n result,\n media: [\n {\n kind: \"image\",\n data: buffer.toString(\"base64\"),\n mimeType,\n description: options?.description,\n metadata: options?.metadata,\n fileName: options?.fileName,\n },\n ],\n cost: options?.cost,\n };\n}\n\n/**\n * Image item for resultWithImages helper.\n */\nexport interface ImageItem {\n /** Raw image data */\n data: Buffer | Uint8Array;\n /** MIME type (auto-detected if not provided) */\n mimeType?: string;\n /** Human-readable description */\n description?: string;\n /** Image dimensions and other metadata */\n metadata?: MediaMetadata;\n /** Filename to use when saving (if not provided, auto-generated) */\n fileName?: string;\n}\n\n/**\n * Create a result with multiple image outputs.\n *\n * @param result - Text result string\n * @param images - Array of image items (must not be empty)\n * @param cost - Optional cost in USD\n * @returns A GadgetExecuteResultWithMedia\n * @throws Error if images array is empty\n *\n * @example\n * ```typescript\n * return resultWithImages(\n * \"Generated comparison images\",\n * [\n * { data: beforeImg, description: \"Before\" },\n * { data: afterImg, description: \"After\" },\n * ],\n * 0.01\n * );\n * ```\n */\nexport function resultWithImages(\n result: string,\n images: ImageItem[],\n cost?: number,\n): GadgetExecuteResultWithMedia {\n if (images.length === 0) {\n throw new Error(\"resultWithImages: images array cannot be empty\");\n }\n\n const media: GadgetMediaOutput[] = images.map((img, index) => {\n const buffer = img.data instanceof Buffer ? img.data : Buffer.from(img.data);\n const mimeType = img.mimeType ?? detectImageMimeType(buffer);\n\n if (!mimeType) {\n throw new Error(\n `Could not detect MIME type for image at index ${index}. Please provide mimeType explicitly.`,\n );\n }\n\n return {\n kind: \"image\" as const,\n data: buffer.toString(\"base64\"),\n mimeType,\n description: img.description,\n metadata: img.metadata,\n fileName: img.fileName,\n };\n });\n\n return { result, media, cost };\n}\n\n/**\n * Options for resultWithAudio helper.\n */\nexport interface AudioOptions {\n /** MIME type (auto-detected if not provided) */\n mimeType?: string;\n /** Human-readable description */\n description?: string;\n /** Duration in milliseconds */\n durationMs?: number;\n /** Cost in USD */\n cost?: number;\n /** Filename to use when saving (if not provided, auto-generated) */\n fileName?: string;\n}\n\n/**\n * Create a result with a single audio output.\n *\n * @param result - Text result string\n * @param audioData - Raw audio data (MP3, WAV, OGG, etc.)\n * @param options - Optional MIME type, description, duration, cost\n * @returns A GadgetExecuteResultWithMedia\n *\n * @example\n * ```typescript\n * const speech = await generateSpeech(text);\n * return resultWithAudio(\n * `Generated speech for: \"${text.slice(0, 50)}...\"`,\n * speech,\n * { mimeType: \"audio/mp3\", durationMs: 5000 }\n * );\n * ```\n */\nexport function resultWithAudio(\n result: string,\n audioData: Buffer | Uint8Array,\n options?: AudioOptions,\n): GadgetExecuteResultWithMedia {\n const buffer = audioData instanceof Buffer ? audioData : Buffer.from(audioData);\n const mimeType = options?.mimeType ?? detectAudioMimeType(buffer);\n\n if (!mimeType) {\n throw new Error(\n \"Could not detect audio MIME type. Please provide mimeType explicitly in options.\",\n );\n }\n\n const metadata: MediaMetadata | undefined = options?.durationMs\n ? { durationMs: options.durationMs }\n : undefined;\n\n return {\n result,\n media: [\n {\n kind: \"audio\",\n data: buffer.toString(\"base64\"),\n mimeType,\n description: options?.description,\n metadata,\n fileName: options?.fileName,\n },\n ],\n cost: options?.cost,\n };\n}\n\n/**\n * Options for resultWithFile helper.\n */\nexport interface FileOptions {\n /** Human-readable description */\n description?: string;\n /** Cost in USD */\n cost?: number;\n /** Filename to use when saving (if not provided, auto-generated) */\n fileName?: string;\n}\n\n/**\n * Create a result with a generic file output.\n *\n * Use this for arbitrary file types that don't fit image/audio categories.\n *\n * @param result - Text result string\n * @param fileData - Raw file data\n * @param mimeType - MIME type (required, not auto-detected)\n * @param options - Optional description and cost\n * @returns A GadgetExecuteResultWithMedia\n *\n * @example\n * ```typescript\n * const pdf = await generatePdf(content);\n * return resultWithFile(\n * \"Generated PDF report\",\n * pdf,\n * \"application/pdf\",\n * { description: \"Monthly report\" }\n * );\n * ```\n */\nexport function resultWithFile(\n result: string,\n fileData: Buffer | Uint8Array,\n mimeType: string,\n options?: FileOptions,\n): GadgetExecuteResultWithMedia {\n const buffer = fileData instanceof Buffer ? fileData : Buffer.from(fileData);\n\n return {\n result,\n media: [\n {\n kind: \"file\",\n data: buffer.toString(\"base64\"),\n mimeType,\n description: options?.description,\n fileName: options?.fileName,\n },\n ],\n cost: options?.cost,\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 { AbstractGadget } 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: AbstractGadget,\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 * Config resolution utility for subagent gadgets.\n *\n * Simplifies the common pattern of resolving configuration from multiple sources:\n * 1. Runtime params (explicit gadget call parameters)\n * 2. Subagent config (from CLI [subagents.Name] sections)\n * 3. Parent agent config (model inheritance)\n * 4. Package defaults\n *\n * @module utils/config-resolver\n */\n\nimport type { ExecutionContext } from \"../gadgets/types.js\";\n\n/**\n * Options for resolving a single config value.\n */\nexport interface ResolveValueOptions<T> {\n /** Runtime parameter value (highest priority) */\n runtime?: T;\n /** Subagent config key to check */\n subagentKey?: string;\n /** Parent config key to check (for inheritance) - \"model\" or \"temperature\" */\n parentKey?: \"model\" | \"temperature\";\n /** Default value (lowest priority) */\n defaultValue: T;\n /** Whether \"inherit\" string means use parent value */\n handleInherit?: boolean;\n}\n\n/**\n * Resolve a single configuration value through the priority chain.\n *\n * Priority (highest to lowest):\n * 1. Runtime parameter (if provided and not undefined)\n * 2. Subagent config (from ctx.subagentConfig[gadgetName][key])\n * 3. Parent config (from ctx.agentConfig[key], if parentKey specified)\n * 4. Default value\n *\n * Special handling for \"inherit\" string:\n * - If handleInherit is true and value is \"inherit\", falls through to parent/default\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget (e.g., \"BrowseWeb\")\n * @param options - Resolution options\n * @returns Resolved value\n *\n * @example\n * ```typescript\n * const model = resolveValue(ctx, \"BrowseWeb\", {\n * runtime: params.model,\n * subagentKey: \"model\",\n * parentKey: \"model\",\n * defaultValue: \"sonnet\",\n * handleInherit: true,\n * });\n * ```\n */\nexport function resolveValue<T>(\n ctx: ExecutionContext,\n gadgetName: string,\n options: ResolveValueOptions<T>,\n): T {\n const { runtime, subagentKey, parentKey, defaultValue, handleInherit } = options;\n\n // Priority 1: Runtime parameter\n if (runtime !== undefined) {\n // Handle \"inherit\" string if enabled\n if (handleInherit && runtime === \"inherit\") {\n // Fall through to lower priorities\n } else {\n return runtime;\n }\n }\n\n // Priority 2: Subagent config\n if (subagentKey && ctx.subagentConfig) {\n const subagentCfg = ctx.subagentConfig[gadgetName];\n if (subagentCfg && subagentKey in subagentCfg) {\n const value = subagentCfg[subagentKey] as T;\n // Handle \"inherit\" string if enabled\n if (handleInherit && value === \"inherit\") {\n // Fall through to parent/default\n } else if (value !== undefined) {\n return value;\n }\n }\n }\n\n // Priority 3: Parent config (inheritance)\n if (parentKey && ctx.agentConfig && parentKey in ctx.agentConfig) {\n const parentValue = ctx.agentConfig[parentKey] as T;\n if (parentValue !== undefined) {\n return parentValue;\n }\n }\n\n // Priority 4: Default value\n return defaultValue;\n}\n\n/**\n * Bulk configuration resolution for subagent gadgets.\n *\n * Takes a map of config keys to their resolution options and returns\n * a fully resolved configuration object.\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget (e.g., \"BrowseWeb\")\n * @param config - Map of config keys to resolution options\n * @returns Fully resolved configuration object\n *\n * @example\n * ```typescript\n * // Before: 27 lines of manual fallback logic\n * const subagentConfig = ctx.subagentConfig?.Dhalsim ?? {};\n * const parentModel = ctx.agentConfig?.model;\n * const model = params.model ?? subagentConfig.model ?? parentModel ?? \"sonnet\";\n * const maxIterations = params.maxIterations ?? subagentConfig.maxIterations ?? 15;\n * const headless = params.headless ?? subagentConfig.headless ?? true;\n *\n * // After: One function call\n * const { model, maxIterations, headless } = resolveConfig(ctx, \"BrowseWeb\", {\n * model: { runtime: params.model, subagentKey: \"model\", parentKey: \"model\", defaultValue: \"sonnet\", handleInherit: true },\n * maxIterations: { runtime: params.maxIterations, subagentKey: \"maxIterations\", defaultValue: 15 },\n * headless: { runtime: params.headless, subagentKey: \"headless\", defaultValue: true },\n * });\n * ```\n */\nexport function resolveConfig<T extends Record<string, unknown>>(\n ctx: ExecutionContext,\n gadgetName: string,\n config: { [K in keyof T]: ResolveValueOptions<T[K]> },\n): T {\n const result: Record<string, unknown> = {};\n\n for (const [key, options] of Object.entries(config)) {\n result[key] = resolveValue(ctx, gadgetName, options as ResolveValueOptions<unknown>);\n }\n\n return result as T;\n}\n\n/**\n * Convenience function for resolving subagent model with \"inherit\" support.\n *\n * This is the most common resolution pattern for subagent gadgets:\n * - Use runtime model if provided\n * - Check subagent config for model override\n * - Inherit parent model if configured\n * - Fall back to default\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget\n * @param runtimeModel - Model from gadget parameters\n * @param defaultModel - Default model if nothing else specified\n * @returns Resolved model string\n *\n * @example\n * ```typescript\n * const model = resolveSubagentModel(ctx, \"BrowseWeb\", params.model, \"sonnet\");\n * ```\n */\nexport function resolveSubagentModel(\n ctx: ExecutionContext,\n gadgetName: string,\n runtimeModel: string | undefined,\n defaultModel: string,\n): string {\n return resolveValue(ctx, gadgetName, {\n runtime: runtimeModel,\n subagentKey: \"model\",\n parentKey: \"model\",\n defaultValue: defaultModel,\n handleInherit: true,\n });\n}\n\n/**\n * Convenience function for resolving subagent timeout.\n *\n * Resolves timeout from the configuration priority chain:\n * - Use runtime timeout if provided\n * - Check subagent config for timeout override\n * - Fall back to default\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget\n * @param runtimeTimeout - Timeout from gadget parameters\n * @param defaultTimeout - Default timeout if nothing else specified\n * @returns Resolved timeout in milliseconds\n *\n * @example\n * ```typescript\n * const timeoutMs = resolveSubagentTimeout(ctx, \"BrowseWeb\", params.timeoutMs, 300000);\n * ```\n */\nexport function resolveSubagentTimeout(\n ctx: ExecutionContext,\n gadgetName: string,\n runtimeTimeout: number | undefined,\n defaultTimeout: number,\n): number {\n return resolveValue(ctx, gadgetName, {\n runtime: runtimeTimeout,\n subagentKey: \"timeoutMs\",\n defaultValue: defaultTimeout,\n });\n}\n","/**\n * Formatting utilities for gadget authors and CLI output.\n *\n * Provides common formatting functions for:\n * - Text truncation\n * - Byte size formatting\n * - Date formatting\n * - Duration formatting\n *\n * @module utils/format\n *\n * @example\n * ```typescript\n * import { format } from \"llmist\";\n *\n * format.truncate(\"Long text...\", 10); // \"Long tex...\"\n * format.bytes(1536); // \"1.5 KB\"\n * format.date(\"2024-01-15T10:30:00Z\"); // \"Jan 15, 2024 10:30 AM\"\n * format.duration(125000); // \"2m 5s\"\n * ```\n */\n\n/**\n * Truncate text to a maximum length, adding suffix if truncated.\n *\n * @param text - Text to truncate\n * @param maxLength - Maximum length including suffix\n * @param suffix - Suffix to append when truncated (default: \"...\")\n * @returns Truncated text\n *\n * @example\n * ```typescript\n * truncate(\"Hello, World!\", 10); // \"Hello, ...\"\n * truncate(\"Short\", 10); // \"Short\"\n * truncate(\"Custom\", 6, \"…\"); // \"Custo…\"\n * ```\n */\nexport function truncate(text: string, maxLength: number, suffix = \"...\"): string {\n if (text.length <= maxLength) return text;\n const truncateAt = maxLength - suffix.length;\n if (truncateAt <= 0) return suffix.slice(0, maxLength);\n return text.slice(0, truncateAt) + suffix;\n}\n\n/**\n * Format bytes as human-readable string.\n *\n * @param bytes - Number of bytes\n * @param decimals - Number of decimal places (default: 1)\n * @returns Formatted string (e.g., \"1.5 KB\", \"2.3 MB\")\n *\n * @example\n * ```typescript\n * formatBytes(0); // \"0 B\"\n * formatBytes(1024); // \"1 KB\"\n * formatBytes(1536); // \"1.5 KB\"\n * formatBytes(1048576); // \"1 MB\"\n * ```\n */\nexport function formatBytes(bytes: number, decimals = 1): string {\n if (bytes === 0) return \"0 B\";\n\n const k = 1024;\n const sizes = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n const size = bytes / Math.pow(k, i);\n\n // Use integer for whole numbers, decimals otherwise\n const formatted = size % 1 === 0 ? size.toString() : size.toFixed(decimals);\n\n return `${formatted} ${sizes[i]}`;\n}\n\n/**\n * Format ISO date string as human-readable date.\n *\n * @param isoDate - ISO date string (e.g., \"2024-01-15T10:30:00Z\")\n * @param options - Intl.DateTimeFormat options\n * @returns Formatted date string\n *\n * @example\n * ```typescript\n * formatDate(\"2024-01-15T10:30:00Z\");\n * // \"Jan 15, 2024, 10:30 AM\" (in local timezone)\n *\n * formatDate(\"2024-01-15T10:30:00Z\", { dateStyle: \"short\" });\n * // \"1/15/24\"\n * ```\n */\nexport function formatDate(\n isoDate: string,\n options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n },\n): string {\n try {\n const date = new Date(isoDate);\n return date.toLocaleString(undefined, options);\n } catch {\n return isoDate; // Return original if parsing fails\n }\n}\n\n/**\n * Format duration in milliseconds as human-readable string.\n *\n * @param ms - Duration in milliseconds\n * @param options - Formatting options\n * @returns Formatted duration string\n *\n * @example\n * ```typescript\n * formatDuration(500); // \"500ms\"\n * formatDuration(1500); // \"1.5s\"\n * formatDuration(65000); // \"1m 5s\"\n * formatDuration(3725000); // \"1h 2m 5s\"\n * ```\n */\nexport function formatDuration(\n ms: number,\n options: { compact?: boolean } = {},\n): string {\n if (ms < 1000) {\n return `${Math.round(ms)}ms`;\n }\n\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n\n if (hours > 0) {\n const remainingMinutes = minutes % 60;\n const remainingSeconds = seconds % 60;\n if (options.compact) {\n return `${hours}h ${remainingMinutes}m`;\n }\n return remainingSeconds > 0\n ? `${hours}h ${remainingMinutes}m ${remainingSeconds}s`\n : `${hours}h ${remainingMinutes}m`;\n }\n\n if (minutes > 0) {\n const remainingSeconds = seconds % 60;\n return remainingSeconds > 0\n ? `${minutes}m ${remainingSeconds}s`\n : `${minutes}m`;\n }\n\n // Less than a minute - show seconds with one decimal if not whole\n const secs = ms / 1000;\n return secs % 1 === 0 ? `${secs}s` : `${secs.toFixed(1)}s`;\n}\n\n/**\n * Format namespace object for convenient access.\n *\n * @example\n * ```typescript\n * import { format } from \"llmist\";\n *\n * format.truncate(\"text\", 5);\n * format.bytes(1024);\n * format.date(\"2024-01-15\");\n * format.duration(5000);\n * ```\n */\nexport const format = {\n truncate,\n bytes: formatBytes,\n date: formatDate,\n duration: formatDuration,\n} as const;\n","/**\n * Timing utilities for gadget authors.\n *\n * Provides common timing functions for:\n * - Random delays (human-like timing)\n * - Timeout handling\n * - Retry logic with backoff\n *\n * @module utils/timing\n *\n * @example\n * ```typescript\n * import { timing } from \"llmist\";\n *\n * // Human-like delays for browser automation\n * await timing.humanDelay(50, 150);\n *\n * // Add timeout to async operations\n * const result = await timing.withTimeout(\n * () => fetchData(),\n * 5000,\n * signal\n * );\n *\n * // Retry with exponential backoff\n * const data = await timing.withRetry(\n * () => unreliableApi(),\n * { maxRetries: 3, delay: 1000, backoff: \"exponential\" }\n * );\n * ```\n */\n\n/**\n * Generate a random delay within a range.\n *\n * @param min - Minimum delay in milliseconds\n * @param max - Maximum delay in milliseconds\n * @returns Random integer between min and max (inclusive)\n *\n * @example\n * ```typescript\n * const delay = randomDelay(50, 150); // e.g., 87\n * ```\n */\nexport function randomDelay(min: number, max: number): number {\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\n/**\n * Sleep for a random duration (for human-like timing).\n *\n * Useful for browser automation to appear more human-like.\n *\n * @param min - Minimum delay in milliseconds (default: 50)\n * @param max - Maximum delay in milliseconds (default: 150)\n * @returns Promise that resolves after the random delay\n *\n * @example\n * ```typescript\n * // Default human-like delay (50-150ms)\n * await humanDelay();\n *\n * // Custom range for slower actions\n * await humanDelay(100, 300);\n * ```\n */\nexport async function humanDelay(min = 50, max = 150): Promise<void> {\n const delay = randomDelay(min, max);\n return new Promise((resolve) => setTimeout(resolve, delay));\n}\n\n/**\n * Execute an async function with a timeout.\n *\n * @param fn - Async function to execute\n * @param timeoutMs - Timeout in milliseconds\n * @param signal - Optional AbortSignal for early cancellation\n * @returns Promise that resolves with the function result or rejects on timeout\n * @throws Error with \"Operation timed out\" message if timeout is exceeded\n *\n * @example\n * ```typescript\n * const result = await withTimeout(\n * () => fetch(\"https://api.example.com/data\"),\n * 5000\n * );\n *\n * // With abort signal\n * const controller = new AbortController();\n * const result = await withTimeout(\n * () => longRunningTask(),\n * 30000,\n * controller.signal\n * );\n * ```\n */\nexport async function withTimeout<T>(\n fn: () => Promise<T>,\n timeoutMs: number,\n signal?: AbortSignal,\n): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n // Check if already aborted\n if (signal?.aborted) {\n reject(new Error(\"Operation aborted\"));\n return;\n }\n\n let settled = false;\n const timeoutId = setTimeout(() => {\n if (!settled) {\n settled = true;\n reject(new Error(`Operation timed out after ${timeoutMs}ms`));\n }\n }, timeoutMs);\n\n // Handle external abort\n const abortHandler = () => {\n if (!settled) {\n settled = true;\n clearTimeout(timeoutId);\n reject(new Error(\"Operation aborted\"));\n }\n };\n\n signal?.addEventListener(\"abort\", abortHandler);\n\n fn()\n .then((result) => {\n if (!settled) {\n settled = true;\n clearTimeout(timeoutId);\n signal?.removeEventListener(\"abort\", abortHandler);\n resolve(result);\n }\n })\n .catch((error) => {\n if (!settled) {\n settled = true;\n clearTimeout(timeoutId);\n signal?.removeEventListener(\"abort\", abortHandler);\n reject(error);\n }\n });\n });\n}\n\n/**\n * Options for retry logic.\n */\nexport interface RetryOptions {\n /** Maximum number of retry attempts (default: 3) */\n maxRetries?: number;\n /** Initial delay between retries in milliseconds (default: 1000) */\n delay?: number;\n /** Backoff strategy: \"linear\" adds delay, \"exponential\" doubles it (default: \"exponential\") */\n backoff?: \"linear\" | \"exponential\";\n /** Maximum delay cap in milliseconds (default: 30000) */\n maxDelay?: number;\n /** Optional function to determine if error is retryable (default: all errors) */\n shouldRetry?: (error: unknown, attempt: number) => boolean;\n /** Optional callback on each retry attempt */\n onRetry?: (error: unknown, attempt: number, delay: number) => void;\n}\n\n/**\n * Execute an async function with retry logic.\n *\n * @param fn - Async function to execute\n * @param options - Retry options\n * @returns Promise that resolves with the function result or rejects after all retries exhausted\n *\n * @example\n * ```typescript\n * // Basic retry with defaults (3 retries, exponential backoff)\n * const result = await withRetry(() => unreliableApi());\n *\n * // Custom retry configuration\n * const result = await withRetry(\n * () => fetchWithErrors(),\n * {\n * maxRetries: 5,\n * delay: 500,\n * backoff: \"exponential\",\n * shouldRetry: (error) => error.status === 429 || error.status >= 500,\n * onRetry: (error, attempt, delay) => {\n * console.log(`Retry ${attempt} after ${delay}ms`);\n * }\n * }\n * );\n * ```\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n options: RetryOptions = {},\n): Promise<T> {\n const {\n maxRetries = 3,\n delay = 1000,\n backoff = \"exponential\",\n maxDelay = 30000,\n shouldRetry = () => true,\n onRetry,\n } = options;\n\n let lastError: unknown;\n let currentDelay = delay;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n\n // Check if we should retry\n if (attempt >= maxRetries || !shouldRetry(error, attempt)) {\n throw error;\n }\n\n // Calculate delay for next attempt\n const waitTime = Math.min(currentDelay, maxDelay);\n\n // Call onRetry callback\n onRetry?.(error, attempt + 1, waitTime);\n\n // Wait before retry\n await new Promise((resolve) => setTimeout(resolve, waitTime));\n\n // Update delay for next iteration\n if (backoff === \"exponential\") {\n currentDelay *= 2;\n } else {\n currentDelay += delay;\n }\n }\n }\n\n // Should never reach here, but TypeScript needs it\n throw lastError;\n}\n\n/**\n * Timing namespace object for convenient access.\n *\n * @example\n * ```typescript\n * import { timing } from \"llmist\";\n *\n * await timing.humanDelay();\n * const result = await timing.withTimeout(() => fetch(url), 5000);\n * const data = await timing.withRetry(() => api.call(), { maxRetries: 3 });\n * ```\n */\nexport const timing = {\n randomDelay,\n humanDelay,\n withTimeout,\n withRetry,\n} as const;\n","/**\n * Session management interface and base class for gadget packages.\n *\n * Provides a standardized way to manage sessions (browser instances, API clients, etc.)\n * across gadgets. This enables:\n * - Consistent session lifecycle management\n * - Per-agent session isolation\n * - Automatic cleanup\n *\n * @module session/manager\n *\n * @example\n * ```typescript\n * import { BaseSessionManager, ISessionManager } from \"llmist\";\n *\n * // Extend for browser sessions\n * class BrowserSessionManager extends BaseSessionManager<Page, BrowserConfig> {\n * async createSession(config?: BrowserConfig): Promise<string> {\n * const browser = await launchBrowser(config);\n * const page = await browser.newPage();\n * const id = this.generateId(\"p\");\n * this.sessions.set(id, page);\n * return id;\n * }\n *\n * async closeSession(id: string): Promise<void> {\n * const page = this.sessions.get(id);\n * if (page) {\n * await page.close();\n * this.sessions.delete(id);\n * }\n * }\n * }\n * ```\n */\n\n/**\n * Interface for session managers.\n *\n * Session managers track and manage external resources (browser pages, API connections, etc.)\n * that need to be shared across multiple gadgets and properly cleaned up.\n *\n * @typeParam TSession - Type of session object (e.g., Page, APIClient)\n * @typeParam TConfig - Configuration type for creating sessions\n */\nexport interface ISessionManager<TSession = unknown, TConfig = unknown> {\n /**\n * Create a new session.\n *\n * @param config - Optional configuration for the session\n * @returns Promise resolving to the session ID\n */\n createSession(config?: TConfig): Promise<string>;\n\n /**\n * Get a session by ID.\n *\n * @param id - Session ID\n * @returns Session object or undefined if not found\n */\n getSession(id: string): TSession | undefined;\n\n /**\n * Get a session by ID, throwing if not found.\n *\n * @param id - Session ID\n * @returns Session object\n * @throws Error if session not found\n */\n requireSession(id: string): TSession;\n\n /**\n * Close and remove a session.\n *\n * @param id - Session ID to close\n */\n closeSession(id: string): Promise<void>;\n\n /**\n * Close all sessions.\n */\n closeAll(): Promise<void>;\n\n /**\n * List all active session IDs.\n *\n * @returns Array of session IDs\n */\n listSessions(): string[];\n\n /**\n * Check if a session exists.\n *\n * @param id - Session ID\n * @returns True if session exists\n */\n hasSession(id: string): boolean;\n}\n\n/**\n * Base implementation of session manager with common functionality.\n *\n * Extend this class to create domain-specific session managers.\n * You only need to implement `createSession` and `closeSession`.\n *\n * @typeParam TSession - Type of session object\n * @typeParam TConfig - Configuration type for creating sessions\n *\n * @example\n * ```typescript\n * class APIClientManager extends BaseSessionManager<APIClient, APIConfig> {\n * async createSession(config?: APIConfig): Promise<string> {\n * const client = new APIClient(config);\n * const id = this.generateId(\"api\");\n * this.sessions.set(id, client);\n * return id;\n * }\n *\n * async closeSession(id: string): Promise<void> {\n * const client = this.sessions.get(id);\n * if (client) {\n * await client.disconnect();\n * this.sessions.delete(id);\n * }\n * }\n * }\n * ```\n */\nexport abstract class BaseSessionManager<TSession, TConfig = unknown>\n implements ISessionManager<TSession, TConfig>\n{\n /** Map of session ID to session object */\n protected sessions = new Map<string, TSession>();\n\n /** Counter for generating unique session IDs */\n protected idCounter = 0;\n\n /**\n * Generate a unique session ID with the given prefix.\n *\n * @param prefix - Prefix for the ID (e.g., \"p\" for pages, \"b\" for browsers)\n * @returns Unique ID like \"p1\", \"p2\", etc.\n */\n protected generateId(prefix: string): string {\n return `${prefix}${++this.idCounter}`;\n }\n\n /**\n * Create a new session.\n * Must be implemented by subclasses.\n */\n abstract createSession(config?: TConfig): Promise<string>;\n\n /**\n * Close and remove a session.\n * Must be implemented by subclasses.\n */\n abstract closeSession(id: string): Promise<void>;\n\n /**\n * Get a session by ID.\n */\n getSession(id: string): TSession | undefined {\n return this.sessions.get(id);\n }\n\n /**\n * Get a session by ID, throwing if not found.\n */\n requireSession(id: string): TSession {\n const session = this.sessions.get(id);\n if (!session) {\n throw new Error(`Session not found: ${id}`);\n }\n return session;\n }\n\n /**\n * List all active session IDs.\n */\n listSessions(): string[] {\n return Array.from(this.sessions.keys());\n }\n\n /**\n * Check if a session exists.\n */\n hasSession(id: string): boolean {\n return this.sessions.has(id);\n }\n\n /**\n * Close all sessions.\n * Closes sessions in reverse order (most recent first).\n */\n async closeAll(): Promise<void> {\n const ids = this.listSessions().reverse();\n for (const id of ids) {\n try {\n await this.closeSession(id);\n } catch {\n // Continue closing other sessions even if one fails\n }\n }\n }\n}\n\n/**\n * Simple in-memory session manager for testing or lightweight use cases.\n *\n * Sessions are just stored objects with no special cleanup logic.\n *\n * @example\n * ```typescript\n * const manager = new SimpleSessionManager<MyData>();\n * const id = await manager.createSession({ value: 42 });\n * const data = manager.requireSession(id); // { value: 42 }\n * await manager.closeSession(id);\n * ```\n */\nexport class SimpleSessionManager<TSession> extends BaseSessionManager<TSession, TSession> {\n /**\n * Create a session by storing the provided data.\n */\n async createSession(data?: TSession): Promise<string> {\n const id = this.generateId(\"s\");\n if (data !== undefined) {\n this.sessions.set(id, data);\n }\n return id;\n }\n\n /**\n * Close a session by removing it from the map.\n */\n async closeSession(id: string): Promise<void> {\n this.sessions.delete(id);\n }\n\n /**\n * Set session data directly.\n */\n setSession(id: string, data: TSession): void {\n this.sessions.set(id, data);\n }\n}\n","/**\n * Subagent creation helper for gadget authors.\n *\n * Simplifies the common pattern of creating subagents from within gadgets.\n * Handles:\n * - Getting host exports (AgentBuilder, LLMist) from context\n * - Model resolution with \"inherit\" support\n * - Parent context sharing for cost tracking\n * - Common configuration options\n *\n * @module agent/subagent\n *\n * @example\n * ```typescript\n * import { createSubagent, Gadget, z } from \"llmist\";\n * import type { ExecutionContext } from \"llmist\";\n *\n * class BrowseWeb extends Gadget({\n * name: \"BrowseWeb\",\n * schema: z.object({\n * task: z.string(),\n * url: z.string().url(),\n * model: z.string().optional(),\n * }),\n * }) {\n * async execute(params: this[\"params\"], ctx?: ExecutionContext) {\n * const agent = createSubagent(ctx!, {\n * name: \"BrowseWeb\",\n * gadgets: [Navigate, Click, Screenshot],\n * systemPrompt: BROWSER_SYSTEM_PROMPT,\n * model: params.model, // Optional override\n * maxIterations: 15,\n * }).ask(params.task);\n *\n * for await (const event of agent.run()) {\n * // Process events...\n * }\n *\n * return result;\n * }\n * }\n * ```\n */\n\nimport type { AbstractGadget } from \"../gadgets/gadget.js\";\nimport type { ExecutionContext, HostExports } from \"../gadgets/types.js\";\nimport { resolveSubagentModel, resolveValue } from \"../utils/config-resolver.js\";\nimport type { AgentBuilder } from \"./builder.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n/**\n * Options for creating a subagent.\n */\nexport interface SubagentOptions {\n /**\n * Name of the subagent (used for config resolution).\n * Should match the gadget name in CLI config, e.g., \"BrowseWeb\".\n */\n name: string;\n\n /**\n * Gadgets to register with the subagent.\n */\n gadgets: AbstractGadget[];\n\n /**\n * System prompt for the subagent.\n */\n systemPrompt?: string;\n\n /**\n * Model to use. If not provided, inherits from parent or uses default.\n * Can be a runtime parameter from gadget params.\n */\n model?: string;\n\n /**\n * Default model if no other source provides one.\n * @default \"sonnet\"\n */\n defaultModel?: string;\n\n /**\n * Maximum iterations for the agent loop.\n */\n maxIterations?: number;\n\n /**\n * Default max iterations if not specified.\n * @default 15\n */\n defaultMaxIterations?: number;\n\n /**\n * Agent hooks for observers, interceptors, controllers.\n */\n hooks?: AgentHooks;\n\n /**\n * Temperature for LLM calls.\n */\n temperature?: number;\n}\n\n/**\n * Get host exports from execution context.\n *\n * This helper ensures gadgets use the same llmist version as the host CLI,\n * avoiding the \"dual-package problem\" where different versions have\n * incompatible classes.\n *\n * @param ctx - Execution context from gadget execute()\n * @returns Host exports (AgentBuilder, LLMist, etc.)\n * @throws Error if host exports not available\n */\nfunction getHostExports(ctx: ExecutionContext): HostExports {\n if (!ctx?.hostExports) {\n throw new Error(\n \"hostExports not available. Subagent gadgets must be run via llmist agent. \" +\n \"Ensure you are using llmist >= 6.2.0 and running through the CLI or AgentBuilder.\",\n );\n }\n return ctx.hostExports;\n}\n\n/**\n * Create a subagent from within a gadget.\n *\n * This helper simplifies the common pattern of creating nested agents.\n * It automatically:\n * - Gets the correct AgentBuilder from host exports\n * - Resolves model with \"inherit\" support from CLI config\n * - Shares the parent's execution tree for cost tracking\n * - Forwards the abort signal for proper cancellation\n * - Inherits human input handler (for 2FA, CAPTCHAs, etc.)\n *\n * @param ctx - ExecutionContext passed to gadget's execute()\n * @param options - Subagent configuration options\n * @returns Configured AgentBuilder ready for .ask()\n *\n * @example\n * ```typescript\n * // Basic usage\n * const agent = createSubagent(ctx, {\n * name: \"BrowseWeb\",\n * gadgets: [Navigate, Click],\n * }).ask(\"Go to google.com\");\n *\n * // With all options\n * const agent = createSubagent(ctx, {\n * name: \"BrowseWeb\",\n * gadgets: [Navigate, Click, Screenshot],\n * systemPrompt: \"You are a browser automation agent...\",\n * model: params.model, // Runtime override\n * defaultModel: \"sonnet\",\n * maxIterations: 20,\n * hooks: {\n * observers: {\n * onLLMCallReady: () => refreshPageState(),\n * },\n * },\n * }).ask(params.task);\n *\n * for await (const event of agent.run()) {\n * // Events flow through shared tree automatically\n * }\n *\n * // Human input bubbles up automatically:\n * // If a gadget throws HumanInputRequiredException,\n * // the parent's onHumanInput handler will be called\n * ```\n */\nexport function createSubagent(\n ctx: ExecutionContext,\n options: SubagentOptions,\n): AgentBuilder {\n const {\n name,\n gadgets,\n systemPrompt,\n model: runtimeModel,\n defaultModel = \"sonnet\",\n maxIterations: runtimeMaxIterations,\n defaultMaxIterations = 15,\n hooks,\n temperature,\n } = options;\n\n // Get host's AgentBuilder to ensure tree sharing works correctly\n const { AgentBuilder, LLMist } = getHostExports(ctx);\n\n // Create LLMist client for the subagent\n const client = new LLMist();\n\n // Resolve model with config hierarchy support\n const model = resolveSubagentModel(ctx, name, runtimeModel, defaultModel);\n\n // Resolve max iterations\n const maxIterations = resolveValue(ctx, name, {\n runtime: runtimeMaxIterations,\n subagentKey: \"maxIterations\",\n defaultValue: defaultMaxIterations,\n });\n\n // Build the subagent\n let builder = new AgentBuilder(client)\n .withModel(model)\n .withGadgets(...gadgets)\n .withMaxIterations(maxIterations)\n .withParentContext(ctx); // Share tree, forward signal\n\n // Inherit human input capability from parent context\n // This allows subagents to bubble up input requests (e.g., 2FA codes)\n if (ctx.requestHumanInput) {\n builder = builder.onHumanInput(ctx.requestHumanInput);\n }\n\n // Apply optional configuration\n if (systemPrompt) {\n builder = builder.withSystem(systemPrompt);\n }\n\n if (hooks) {\n builder = builder.withHooks(hooks);\n }\n\n if (temperature !== undefined) {\n builder = builder.withTemperature(temperature);\n }\n\n // Forward logger from parent context if available\n if (ctx.logger) {\n builder = builder.withLogger(ctx.logger);\n }\n\n return builder;\n}\n\n/**\n * Check if an execution context has valid host exports.\n *\n * Useful for conditional logic when gadgets may run standalone or via agent.\n *\n * @param ctx - Execution context\n * @returns True if host exports are available\n */\nexport function hasHostExports(ctx?: ExecutionContext): boolean {\n return ctx?.hostExports !== undefined;\n}\n","/**\n * Package manifest types for llmist gadget packages.\n *\n * These types define the structure of the `llmist` field in package.json\n * for gadget packages. This enables:\n * - Preset-based gadget loading\n * - Subagent discovery\n * - Factory function support\n * - Session management metadata\n *\n * @module package/manifest\n *\n * @example package.json\n * ```json\n * {\n * \"name\": \"dhalsim\",\n * \"llmist\": {\n * \"gadgets\": \"./dist/index.js\",\n * \"factory\": \"./dist/index.js\",\n * \"presets\": {\n * \"minimal\": [\"Navigate\", \"GetFullPageContent\"],\n * \"readonly\": [\"Navigate\", \"GetFullPageContent\", \"Screenshot\"],\n * \"all\": \"*\"\n * },\n * \"subagents\": {\n * \"BrowseWeb\": {\n * \"entryPoint\": \"./dist/index.js\",\n * \"export\": \"Dhalsim\",\n * \"description\": \"Autonomous web browser agent\",\n * \"defaultModel\": \"sonnet\",\n * \"maxIterations\": 15\n * }\n * },\n * \"session\": {\n * \"factory\": \"getSessionManager\",\n * \"type\": \"browser\"\n * }\n * }\n * }\n * ```\n */\n\n/**\n * Subagent definition in the manifest.\n */\nexport interface SubagentManifestEntry {\n /**\n * Entry point file path relative to package root.\n * @example \"./dist/index.js\"\n */\n entryPoint: string;\n\n /**\n * Export name from the entry point.\n * @example \"Dhalsim\" or \"BrowseWeb\"\n */\n export: string;\n\n /**\n * Human-readable description of what this subagent does.\n */\n description?: string;\n\n /**\n * List of gadget names this subagent uses internally.\n * Useful for documentation and dependency tracking.\n */\n uses?: string[];\n\n /**\n * Default model for this subagent.\n * Can be \"inherit\" to use parent's model.\n * @default \"inherit\"\n */\n defaultModel?: string;\n\n /**\n * Default maximum iterations.\n * @default 15\n */\n maxIterations?: number;\n}\n\n/**\n * Session factory metadata in the manifest.\n */\nexport interface SessionManifestEntry {\n /**\n * Export name of the session factory function.\n * @example \"getSessionManager\"\n */\n factory: string;\n\n /**\n * Type of session for categorization.\n * @example \"browser\", \"api\", \"database\"\n */\n type: string;\n}\n\n/**\n * Preset definition - either an array of gadget names or \"*\" for all.\n */\nexport type PresetDefinition = string[] | \"*\";\n\n/**\n * llmist package manifest structure.\n *\n * This is the shape of the `llmist` field in package.json\n * for gadget packages.\n */\nexport interface LLMistPackageManifest {\n /**\n * Entry point for all gadgets.\n * The module should export gadgets or a gadgets array.\n * @example \"./dist/index.js\"\n */\n gadgets?: string;\n\n /**\n * Entry point for factory functions.\n * Should export `createGadgetsByPreset(preset)` and/or `createGadgetsByName(names)`.\n * @example \"./dist/index.js\"\n */\n factory?: string;\n\n /**\n * Subagent definitions.\n * Key is the subagent name as it appears in CLI config.\n */\n subagents?: Record<string, SubagentManifestEntry>;\n\n /**\n * Preset definitions.\n * Key is preset name, value is array of gadget names or \"*\" for all.\n * @example { \"minimal\": [\"Navigate\", \"Screenshot\"], \"all\": \"*\" }\n */\n presets?: Record<string, PresetDefinition>;\n\n /**\n * Session factory metadata.\n */\n session?: SessionManifestEntry;\n}\n\n/**\n * Factory function types that packages can export.\n */\nexport interface GadgetFactoryExports {\n /**\n * Create gadgets by preset name.\n */\n createGadgetsByPreset?: (preset: string, config?: unknown) => unknown;\n\n /**\n * Create gadgets by specific names.\n */\n createGadgetsByName?: (names: string[], config?: unknown) => unknown;\n\n /**\n * Create all gadgets with optional config.\n */\n createGadgets?: (config?: unknown) => unknown;\n}\n\n/**\n * Read and parse the llmist manifest from a package.json object.\n *\n * @param packageJson - Parsed package.json object\n * @returns Manifest or undefined if not present\n *\n * @example\n * ```typescript\n * import { readFileSync } from \"fs\";\n *\n * const pkg = JSON.parse(readFileSync(\"package.json\", \"utf-8\"));\n * const manifest = parseManifest(pkg);\n *\n * if (manifest?.presets?.minimal) {\n * console.log(\"Minimal preset:\", manifest.presets.minimal);\n * }\n * ```\n */\nexport function parseManifest(\n packageJson: Record<string, unknown>,\n): LLMistPackageManifest | undefined {\n const llmist = packageJson.llmist;\n if (!llmist || typeof llmist !== \"object\") {\n return undefined;\n }\n return llmist as LLMistPackageManifest;\n}\n\n/**\n * Check if a manifest has a specific preset.\n */\nexport function hasPreset(\n manifest: LLMistPackageManifest | undefined,\n presetName: string,\n): boolean {\n return manifest?.presets?.[presetName] !== undefined;\n}\n\n/**\n * Get gadget names for a preset.\n * Returns undefined if preset not found, empty array if preset is invalid.\n */\nexport function getPresetGadgets(\n manifest: LLMistPackageManifest | undefined,\n presetName: string,\n): string[] | \"*\" | undefined {\n const preset = manifest?.presets?.[presetName];\n if (preset === undefined) return undefined;\n return preset;\n}\n\n/**\n * Check if a manifest has subagent definitions.\n */\nexport function hasSubagents(manifest: LLMistPackageManifest | undefined): boolean {\n return manifest?.subagents !== undefined && Object.keys(manifest.subagents).length > 0;\n}\n\n/**\n * Get subagent entry by name.\n */\nexport function getSubagent(\n manifest: LLMistPackageManifest | undefined,\n name: string,\n): SubagentManifestEntry | undefined {\n return manifest?.subagents?.[name];\n}\n\n/**\n * List all subagent names in a manifest.\n */\nexport function listSubagents(manifest: LLMistPackageManifest | undefined): string[] {\n if (!manifest?.subagents) return [];\n return Object.keys(manifest.subagents);\n}\n\n/**\n * List all preset names in a manifest.\n */\nexport function listPresets(manifest: LLMistPackageManifest | undefined): string[] {\n if (!manifest?.presets) return [];\n return Object.keys(manifest.presets);\n}\n"],"mappings":"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","names":["init_constants","import_node_path","z","import_node_crypto","Anthropic","init_constants","stream","init_constants","response","images","cost","stream","text","OpenAI","init_constants","format","stream","text","providerSpecs","text","pointer","import_zod","equal","stream","stream","pRetry","getHostExports","import_zod","init_constants","timing","text","AgentBuilder","LLMist","getHostExports"]}