llmist 17.5.1 → 17.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -631,7 +631,7 @@ Produces: { "items": ["first", "second"] }`);
631
631
  * @param mediaIds - Optional IDs for the media outputs
632
632
  * @param storedMedia - Optional stored media info including file paths
633
633
  */
634
- addGadgetCallResult(gadget, parameters, result, invocationId, media, mediaIds, storedMedia) {
634
+ addGadgetCallResult(gadget, parameters, result, invocationId, media, mediaIds, storedMedia, metadata) {
635
635
  const paramStr = this.formatBlockParameters(parameters, "");
636
636
  this.messages.push({
637
637
  role: "assistant",
@@ -655,11 +655,12 @@ ${idRefs}`;
655
655
  parts.push(audioFromBase64(item.data, item.mimeType));
656
656
  }
657
657
  }
658
- this.messages.push({ role: "user", content: parts });
658
+ this.messages.push({ role: "user", content: parts, metadata });
659
659
  } else {
660
660
  this.messages.push({
661
661
  role: "user",
662
- content: `Result (${invocationId}): ${result}`
662
+ content: `Result (${invocationId}): ${result}`,
663
+ metadata
663
664
  });
664
665
  }
665
666
  return this;
@@ -1242,6 +1243,22 @@ var init_gadget = __esm({
1242
1243
  * This is a safety floor: external config cannot weaken it.
1243
1244
  */
1244
1245
  exclusive;
1246
+ /**
1247
+ * If true, results produced by this gadget are marked sticky on the
1248
+ * conversation (`message.metadata.sticky === true`). Compaction strategies
1249
+ * preserve sticky messages past the truncation point, so the agent retains
1250
+ * the gadget's output for the rest of the conversation rather than having
1251
+ * it dropped on the next compaction pass.
1252
+ *
1253
+ * Use for gadgets whose output is *reference material* the agent will keep
1254
+ * consulting — `LoadSkill` is the canonical example: a multi-KB skill body
1255
+ * the agent needs to remember across iterations. Don't use for routine
1256
+ * gadget outputs (file reads, computation results) — those should churn
1257
+ * normally with the conversation.
1258
+ *
1259
+ * Has no effect on agents that don't enable compaction.
1260
+ */
1261
+ stickyResult;
1245
1262
  /**
1246
1263
  * Throws an AbortException if the execution has been aborted.
1247
1264
  *
@@ -1438,6 +1455,7 @@ function createGadget(config) {
1438
1455
  timeoutMs = config.timeoutMs;
1439
1456
  examples = config.examples;
1440
1457
  maxConcurrent = config.maxConcurrent;
1458
+ stickyResult = config.stickyResult;
1441
1459
  execute(params, ctx) {
1442
1460
  return config.execute(params, ctx);
1443
1461
  }
@@ -2249,4 +2267,4 @@ export {
2249
2267
  mcpToolToGadget,
2250
2268
  init_tool_adapter
2251
2269
  };
2252
- //# sourceMappingURL=chunk-HM7PUGPA.js.map
2270
+ //# sourceMappingURL=chunk-EXFIXEGW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/constants.ts","../src/core/input-content.ts","../src/core/prompt-config.ts","../src/core/messages.ts","../src/gadgets/exceptions.ts","../src/logging/logger.ts","../src/gadgets/schema-to-json.ts","../src/gadgets/schema-validator.ts","../src/gadgets/gadget.ts","../src/gadgets/create-gadget.ts","../src/mcp/errors.ts","../src/mcp/allowlist.ts","../src/mcp/client.ts","../src/mcp/lifecycle.ts","../src/gadgets/helpers.ts","../src/mcp/json-schema-to-zod.ts","../src/mcp/tool-adapter.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 output limit calculation.\n * Conservative value of 2 errs toward overestimating tokens, which is safer. */\nexport const CHARS_PER_TOKEN = 2;\n\n/** Fallback context window size if model is not in registry */\nexport const FALLBACK_CONTEXT_WINDOW = 128_000;\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 * 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, StoredMedia } 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 * @param storedMedia - Optional stored media info including file paths\n */\n addGadgetCallResult(\n gadget: string,\n parameters: Record<string, unknown>,\n result: string,\n invocationId: string,\n media?: GadgetMediaOutput[],\n mediaIds?: string[],\n storedMedia?: StoredMedia[],\n // Optional metadata attached to the result `user` message. The compaction\n // layer consults `metadata.sticky === true` to preserve specific tool\n // results past truncation. Other keys are passthrough — providers and\n // history serializers ignore `LLMMessage.metadata` by design.\n metadata?: Record<string, unknown>,\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, including file paths if available\n const idRefs = media\n .map((m, i) => {\n const path = storedMedia?.[i]?.path;\n const pathInfo = path ? ` → saved to: ${path}` : \"\";\n return `[Media: ${mediaIds[i]} (${m.kind})${pathInfo}]`;\n })\n .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, metadata });\n } else {\n // Simple text result\n this.messages.push({\n role: \"user\",\n content: `Result (${invocationId}): ${result}`,\n metadata,\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 * 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/**\n * Exception thrown when a budget limit is set but the model has no valid pricing information.\n *\n * This is thrown during agent construction when:\n * - `budget` is set in agent options\n * - The model is not found in the model registry, or has zero pricing (input === 0 && output === 0)\n *\n * To fix: either register pricing for the model via `client.modelRegistry.registerModel()`,\n * or remove the budget constraint.\n *\n * @example\n * ```typescript\n * // This will throw BudgetPricingUnavailableError because \"my-custom-model\"\n * // has no pricing in the registry:\n * const agent = LLMist.createAgent()\n * .withModel(\"my-custom-model\")\n * .withBudget(1.00)\n * .ask(\"Hello\");\n * ```\n */\nexport class BudgetPricingUnavailableError extends Error {\n public readonly model: string;\n public readonly budget: number;\n\n constructor(model: string, budget: number) {\n super(\n `Budget of $${budget.toFixed(2)} was set but model \"${model}\" has no valid pricing ` +\n `information in the model registry. Either register pricing for this model via ` +\n `client.modelRegistry.registerModel() or remove the budget constraint.`,\n );\n this.name = \"BudgetPricingUnavailableError\";\n this.model = model;\n this.budget = budget;\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 * When true AND file logging is active (LLMIST_LOG_FILE),\n * also write formatted log lines to stdout (console).\n * Useful for Docker/container environments where you need both\n * file logs for upload and stdout for container log aggregation.\n * No effect when file logging is not active.\n * @default false\n */\n teeToConsole?: 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 const envLogTee = parseEnvBoolean(process.env.LLMIST_LOG_TEE);\n const teeToConsole = options.teeToConsole ?? envLogTee ?? 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: (logMetaMarkup: string, logArgs: unknown[], _logErrors: string[]) => {\n const args = logArgs.map((arg) =>\n typeof arg === \"string\" ? arg : JSON.stringify(arg),\n );\n\n // File: strip ANSI for clean plaintext\n if (sharedLogFileStream) {\n const meta = stripAnsi(logMetaMarkup);\n const fileArgs = args.map((a) => stripAnsi(a));\n sharedLogFileStream.write(`${meta}${fileArgs.join(\" \")}\\n`);\n }\n\n // Console: preserve ANSI colors\n if (teeToConsole) {\n process.stdout.write(`${logMetaMarkup}${args.join(\" \")}\\n`);\n }\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\";\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 { 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(\n formatParamsForBlockExample(item as Record<string, unknown>, itemPath, argPrefix),\n );\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(\n formatParamsForBlockExample(value as Record<string, unknown>, fullPath, argPrefix),\n );\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 * Maximum number of concurrent executions allowed for this gadget.\n * Use this to prevent race conditions in gadgets that modify shared state.\n *\n * - `1` = Sequential execution (only one instance runs at a time)\n * - `0` or `undefined` = Unlimited concurrency (default)\n * - `N > 1` = At most N concurrent executions\n *\n * This property sets a safety floor: external configuration (SubagentConfig)\n * can only make concurrency MORE restrictive, never less. For example, if\n * a gadget declares `maxConcurrent: 1`, external config cannot override it\n * to allow parallel execution.\n *\n * @example\n * ```typescript\n * // File writer that must run sequentially to avoid race conditions\n * class WriteFile extends Gadget({\n * description: 'Writes content to a file',\n * schema: z.object({ path: z.string(), content: z.string() }),\n * maxConcurrent: 1, // Sequential - prevents race conditions\n * }) {\n * execute(params: this['params']) { ... }\n * }\n * ```\n */\n maxConcurrent?: number;\n\n /**\n * If true, this gadget must execute alone — no other gadgets in the same\n * LLM response can run in parallel. When an exclusive gadget arrives and\n * other gadgets are already in-flight, it is deferred until they complete.\n *\n * Use for gadgets that terminate the agent loop (e.g., Finish), where\n * sibling tool results must be visible to the LLM before the loop ends.\n *\n * This is a safety floor: external config cannot weaken it.\n */\n exclusive?: boolean;\n\n /**\n * If true, results produced by this gadget are marked sticky on the\n * conversation (`message.metadata.sticky === true`). Compaction strategies\n * preserve sticky messages past the truncation point, so the agent retains\n * the gadget's output for the rest of the conversation rather than having\n * it dropped on the next compaction pass.\n *\n * Use for gadgets whose output is *reference material* the agent will keep\n * consulting — `LoadSkill` is the canonical example: a multi-KB skill body\n * the agent needs to remember across iterations. Don't use for routine\n * gadget outputs (file reads, computation results) — those should churn\n * normally with the conversation.\n *\n * Has no effect on agents that don't enable compaction.\n */\n stickyResult?: boolean;\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 * 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(\n example.params as Record<string, unknown>,\n \"\",\n effectiveArgPrefix,\n ),\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 * 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 * Maximum concurrent executions. Use to prevent race conditions.\n * - `1` = Sequential (one at a time)\n * - `0` or `undefined` = Unlimited (default)\n * - `N > 1` = At most N concurrent\n */\n maxConcurrent?: number;\n\n /**\n * If true, this gadget's results are marked sticky and survive compaction.\n * See `AbstractGadget.stickyResult` for the full contract.\n */\n stickyResult?: boolean;\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 maxConcurrent = config.maxConcurrent;\n stickyResult = config.stickyResult;\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 * Typed errors raised by the MCP integration.\n *\n * These wrap underlying SDK and transport errors so the rest of llmist can\n * react to MCP failures with stable, narrow types instead of catching the\n * SDK's internal error classes.\n *\n * @module mcp/errors\n */\n\nexport class McpError extends Error {\n readonly serverName?: string;\n\n constructor(message: string, serverName?: string) {\n super(message);\n this.name = \"McpError\";\n this.serverName = serverName;\n }\n}\n\nexport class McpUntrustedCommandError extends McpError {\n readonly command: string;\n\n constructor(command: string, serverName?: string) {\n super(\n `Refusing to spawn MCP stdio command \"${command}\" because its basename ` +\n `is not in the default allowlist. To opt in, set { trust: true } on the ` +\n `server spec (library), or trust = true in your TOML mcp.servers block, ` +\n `or pass --mcp-trust ${serverName ?? \"<name>\"} on the CLI. ` +\n `See https://llmist.dev/library/advanced/mcp-security/ for context ` +\n `(CVE-2026-30623).`,\n serverName,\n );\n this.name = \"McpUntrustedCommandError\";\n this.command = command;\n }\n}\n\nexport class McpConnectError extends McpError {\n readonly cause?: unknown;\n\n constructor(message: string, opts?: { serverName?: string; cause?: unknown }) {\n super(message, opts?.serverName);\n this.name = \"McpConnectError\";\n this.cause = opts?.cause;\n }\n}\n\nexport class McpToolCallError extends McpError {\n readonly toolName: string;\n readonly cause?: unknown;\n\n constructor(toolName: string, message: string, opts?: { serverName?: string; cause?: unknown }) {\n super(message, opts?.serverName);\n this.name = \"McpToolCallError\";\n this.toolName = toolName;\n this.cause = opts?.cause;\n }\n}\n\nexport class McpTimeoutError extends McpError {\n readonly operation: string;\n readonly timeoutMs: number;\n\n constructor(operation: string, timeoutMs: number, serverName?: string) {\n super(\n `MCP operation \"${operation}\" on server \"${serverName ?? \"<unknown>\"}\" timed out after ${timeoutMs}ms`,\n serverName,\n );\n this.name = \"McpTimeoutError\";\n this.operation = operation;\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class JsonSchemaConversionError extends Error {\n readonly schemaFragment: unknown;\n readonly reason: string;\n\n constructor(reason: string, schemaFragment: unknown) {\n super(`JSON Schema → Zod conversion failed: ${reason}`);\n this.name = \"JsonSchemaConversionError\";\n this.reason = reason;\n this.schemaFragment = schemaFragment;\n }\n}\n","/**\n * Default-safe allowlist for MCP STDIO server commands.\n *\n * Mitigates the CVE-2026-30623 family of stdio-spawn RCE vulnerabilities. The\n * gate refuses to spawn any executable whose basename is not in the allowlist\n * unless the spec is marked `trust: true` (library) / `trust = true` (TOML)\n * / `--mcp-trust <name>` (CLI). It also rejects whole-string commands that\n * embed args or shell metacharacters — callers must pass arguments as a\n * separate array.\n *\n * @module mcp/allowlist\n */\n\nimport path from \"node:path\";\nimport { McpUntrustedCommandError } from \"./errors.js\";\n\n/**\n * Default allowlist of MCP stdio server runtimes that are safe to spawn\n * without explicit user opt-in. Add entries to this list only when the\n * basename is universally a runtime, not a tool that takes arbitrary code\n * (e.g. don't add `bash` or `sh`).\n */\nexport const DEFAULT_MCP_COMMAND_ALLOWLIST: ReadonlySet<string> = new Set([\n \"npx\",\n \"node\",\n \"uvx\",\n \"uv\",\n \"python\",\n \"python3\",\n \"deno\",\n \"bun\",\n]);\n\nconst WHITESPACE_OR_META_RE = /[\\s;|&`$<>()'\"\\\\]/;\n\n/**\n * Throws McpUntrustedCommandError if `command` is not safe to spawn under\n * the allowlist policy.\n */\nexport function assertCommandAllowed(\n command: string,\n trusted: boolean,\n customAllowlist?: ReadonlySet<string>,\n): void {\n if (!command || typeof command !== \"string\") {\n throw new McpUntrustedCommandError(String(command));\n }\n\n if (WHITESPACE_OR_META_RE.test(command)) {\n // Whitespace or shell metachars in the command string mean the caller\n // is trying to pass args via the command line. Refuse; they must use\n // `args` instead.\n throw new McpUntrustedCommandError(command);\n }\n\n if (trusted) return;\n\n const allowlist = customAllowlist ?? DEFAULT_MCP_COMMAND_ALLOWLIST;\n const base = path.basename(command);\n if (!allowlist.has(base)) {\n throw new McpUntrustedCommandError(command);\n }\n}\n","/**\n * Wraps the official MCP SDK's stdio Client into a small, llmist-flavored\n * surface. Encapsulates the SDK so the rest of llmist depends on the typed\n * shapes in `./types.ts` rather than vendor types.\n *\n * Lazy-imports the SDK so agents that don't use MCP pay zero overhead at\n * load time.\n *\n * @module mcp/client\n */\n\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport { assertCommandAllowed } from \"./allowlist.js\";\nimport { McpConnectError, McpTimeoutError, McpToolCallError } from \"./errors.js\";\nimport type {\n McpPromptDescriptor,\n McpPromptResult,\n McpServerCapabilities,\n McpServerSpec,\n McpToolDescriptor,\n McpToolResult,\n} from \"./types.js\";\n\ninterface SdkClientLike {\n connect(transport: Transport): Promise<void>;\n close(): Promise<void>;\n listTools(): Promise<{ tools: McpToolDescriptor[] }>;\n callTool(params: { name: string; arguments?: unknown }): Promise<{\n content: unknown[];\n isError?: boolean;\n }>;\n listPrompts?(): Promise<{ prompts: McpPromptDescriptor[] }>;\n getPrompt?(params: { name: string; arguments?: Record<string, unknown> }): Promise<{\n description?: string;\n messages: Array<{ role: \"user\" | \"assistant\"; content: unknown }>;\n }>;\n getServerCapabilities(): McpServerCapabilities | undefined;\n}\n\nlet cachedSdk: Promise<{\n Client: new (\n info: { name: string; version: string },\n opts?: { capabilities?: object },\n ) => SdkClientLike;\n StdioClientTransport: new (params: {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n }) => Transport & { pid: number | null };\n StreamableHTTPClientTransport: new (\n url: URL,\n opts?: { requestInit?: { headers?: Record<string, string> } },\n ) => Transport;\n}> | null = null;\n\nasync function loadSdk() {\n if (!cachedSdk) {\n cachedSdk = (async () => {\n const [client, stdio, http] = await Promise.all([\n import(\"@modelcontextprotocol/sdk/client/index.js\"),\n import(\"@modelcontextprotocol/sdk/client/stdio.js\"),\n import(\"@modelcontextprotocol/sdk/client/streamableHttp.js\"),\n ]);\n return {\n Client: client.Client as unknown as new (\n info: { name: string; version: string },\n opts?: { capabilities?: object },\n ) => SdkClientLike,\n StdioClientTransport: stdio.StdioClientTransport,\n StreamableHTTPClientTransport: http.StreamableHTTPClientTransport as unknown as new (\n url: URL,\n opts?: { requestInit?: { headers?: Record<string, string> } },\n ) => Transport,\n };\n })();\n }\n return cachedSdk;\n}\n\nexport interface McpClientOptions {\n /**\n * Inject a pre-built transport for testing. When omitted, the client\n * builds a stdio transport from the spec at connect() time.\n */\n transport?: Transport;\n /**\n * Override the client identity sent during initialize.\n */\n clientInfo?: { name: string; version: string };\n}\n\nconst DEFAULT_CLIENT_INFO = { name: \"llmist\", version: \"0.0.0\" };\n\nexport class McpClient {\n private sdkClient: SdkClientLike | null = null;\n private spawnedPid: number | null = null;\n private closed = false;\n private readonly injectedTransport?: Transport;\n private readonly clientInfo: { name: string; version: string };\n\n constructor(\n readonly spec: McpServerSpec,\n opts?: McpClientOptions,\n ) {\n this.injectedTransport = opts?.transport;\n this.clientInfo = opts?.clientInfo ?? DEFAULT_CLIENT_INFO;\n }\n\n get serverName(): string {\n return this.spec.name;\n }\n\n get pid(): number | null {\n return this.spawnedPid;\n }\n\n get serverCapabilities(): McpServerCapabilities | null {\n if (!this.sdkClient) return null;\n return this.sdkClient.getServerCapabilities() ?? null;\n }\n\n async connect(): Promise<void> {\n if (this.sdkClient) return;\n\n let transport: Transport;\n if (this.injectedTransport) {\n transport = this.injectedTransport;\n } else if (this.spec.transport === \"stdio\") {\n // Production stdio path — spawn a child process via the SDK's stdio\n // transport, gated by the allowlist.\n assertCommandAllowed(this.spec.command, this.spec.trust === true);\n const { StdioClientTransport } = await loadSdk();\n const stdioTransport = new StdioClientTransport({\n command: this.spec.command,\n args: this.spec.args,\n env: this.spec.env,\n });\n transport = stdioTransport;\n this.spawnedPid = null; // populated after start\n } else {\n // Streamable HTTP path — no allowlist gating (no process spawn).\n const { StreamableHTTPClientTransport } = await loadSdk();\n let url: URL;\n try {\n url = new URL(this.spec.url);\n } catch (err) {\n throw new McpConnectError(\n `MCP server \"${this.spec.name}\" has an invalid URL: ${(err as Error).message}`,\n { serverName: this.spec.name, cause: err },\n );\n }\n transport = new StreamableHTTPClientTransport(url, {\n requestInit: this.spec.headers ? { headers: this.spec.headers } : undefined,\n });\n }\n\n const { Client } = await loadSdk();\n const client = new Client(this.clientInfo, { capabilities: {} });\n\n try {\n await this.withTimeout(() => client.connect(transport), \"connect\");\n } catch (err) {\n throw new McpConnectError(\n `Failed to connect to MCP server \"${this.spec.name}\": ${(err as Error).message}`,\n { serverName: this.spec.name, cause: err },\n );\n }\n\n this.sdkClient = client;\n\n // Capture pid if the production stdio transport exposed one.\n const maybePid = (transport as { pid?: number | null }).pid;\n if (typeof maybePid === \"number\") {\n this.spawnedPid = maybePid;\n }\n }\n\n async listTools(): Promise<McpToolDescriptor[]> {\n const client = this.requireClient();\n const res = await this.withTimeout(() => client.listTools(), \"tools/list\");\n return res.tools.map((t) => ({\n name: t.name,\n description: t.description,\n inputSchema: t.inputSchema,\n }));\n }\n\n async callTool(name: string, args: unknown): Promise<McpToolResult> {\n const client = this.requireClient();\n try {\n const res = await this.withTimeout(\n () =>\n client.callTool({\n name,\n arguments: (args as Record<string, unknown> | undefined) ?? {},\n }),\n `tools/call ${name}`,\n );\n return {\n content: (res.content as McpToolResult[\"content\"]) ?? [],\n isError: res.isError,\n };\n } catch (err) {\n throw new McpToolCallError(\n name,\n `MCP tool call \"${name}\" on server \"${this.spec.name}\" failed: ${(err as Error).message}`,\n { serverName: this.spec.name, cause: err },\n );\n }\n }\n\n async listPrompts(): Promise<McpPromptDescriptor[]> {\n const client = this.requireClient();\n if (!client.listPrompts) {\n return [];\n }\n const listPrompts = client.listPrompts.bind(client);\n const res = await this.withTimeout(() => listPrompts(), \"prompts/list\");\n return res.prompts.map((p) => ({\n name: p.name,\n description: p.description,\n arguments: p.arguments,\n }));\n }\n\n async getPrompt(name: string, args?: Record<string, unknown>): Promise<McpPromptResult> {\n const client = this.requireClient();\n if (!client.getPrompt) {\n throw new McpToolCallError(name, \"Server has no getPrompt method\", {\n serverName: this.spec.name,\n });\n }\n const getPrompt = client.getPrompt.bind(client);\n try {\n const res = await this.withTimeout(\n () => getPrompt({ name, arguments: args ?? {} }),\n `prompts/get ${name}`,\n );\n return {\n description: res.description,\n messages: res.messages.map((m) => ({\n role: m.role,\n content: m.content as McpPromptResult[\"messages\"][number][\"content\"],\n })),\n };\n } catch (err) {\n throw new McpToolCallError(\n name,\n `MCP prompts/get \"${name}\" on server \"${this.spec.name}\" failed: ${(err as Error).message}`,\n { serverName: this.spec.name, cause: err },\n );\n }\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n if (this.sdkClient) {\n try {\n await this.sdkClient.close();\n } catch {\n // Closing on a teardown path must not throw.\n }\n this.sdkClient = null;\n }\n }\n\n private requireClient(): SdkClientLike {\n if (!this.sdkClient) {\n throw new McpConnectError(\n `MCP client for server \"${this.spec.name}\" is not connected. Call connect() first.`,\n { serverName: this.spec.name },\n );\n }\n return this.sdkClient;\n }\n\n private async withTimeout<T>(fn: () => Promise<T>, operation: string): Promise<T> {\n const timeoutMs = this.spec.timeoutMs;\n if (timeoutMs === undefined || timeoutMs <= 0) {\n return fn();\n }\n\n return new Promise<T>((resolve, reject) => {\n let settled = false;\n const timeoutId = setTimeout(() => {\n if (settled) return;\n settled = true;\n reject(new McpTimeoutError(operation, timeoutMs, this.spec.name));\n }, timeoutMs);\n\n fn()\n .then((result) => {\n if (settled) return;\n settled = true;\n clearTimeout(timeoutId);\n resolve(result);\n })\n .catch((err) => {\n if (settled) return;\n settled = true;\n clearTimeout(timeoutId);\n reject(err);\n });\n });\n }\n}\n","/**\n * Tracks spawned MCP clients for an agent run and closes them all on\n * teardown. Plan 1 ships the basics: register, closeAll, idempotent. Signal\n * handling and graceful shutdown windows are added in plan 2.\n *\n * @module mcp/lifecycle\n */\n\nimport { defaultLogger } from \"../logging/logger.js\";\nimport type { McpClient } from \"./client.js\";\n\nexport class McpLifecycle {\n private clients: McpClient[] = [];\n private closing: Promise<void> | null = null;\n private signalHandlersInstalled = false;\n private sigtermHandler: (() => void) | null = null;\n private sigintHandler: (() => void) | null = null;\n\n get size(): number {\n return this.clients.length;\n }\n\n register(client: McpClient): void {\n this.clients.push(client);\n }\n\n /**\n * Attach SIGTERM/SIGINT handlers that close every registered client when\n * the parent process is asked to exit. Idempotent (double install is a\n * no-op) and removable via `removeSignalHandlers()`.\n */\n installSignalHandlers(): void {\n if (this.signalHandlersInstalled) return;\n this.signalHandlersInstalled = true;\n this.sigtermHandler = () => {\n void this.closeAll();\n };\n this.sigintHandler = () => {\n void this.closeAll();\n };\n process.on(\"SIGTERM\", this.sigtermHandler);\n process.on(\"SIGINT\", this.sigintHandler);\n }\n\n removeSignalHandlers(): void {\n if (!this.signalHandlersInstalled) return;\n if (this.sigtermHandler) process.off(\"SIGTERM\", this.sigtermHandler);\n if (this.sigintHandler) process.off(\"SIGINT\", this.sigintHandler);\n this.sigtermHandler = null;\n this.sigintHandler = null;\n this.signalHandlersInstalled = false;\n }\n\n /**\n * Close every registered client in parallel. Errors from individual close()\n * calls are swallowed (logged via console.warn) — a teardown path must not\n * throw because that would mask the original reason the agent is shutting\n * down. Idempotent: concurrent calls all return the same in-flight promise.\n */\n async closeAll(): Promise<void> {\n if (this.closing) return this.closing;\n\n const toClose = this.clients;\n this.clients = [];\n\n this.closing = (async () => {\n const results = await Promise.allSettled(toClose.map((c) => c.close()));\n for (const r of results) {\n if (r.status === \"rejected\") {\n // Best-effort log; never re-throw on a teardown path.\n defaultLogger.debug(\"MCP client close failed during teardown:\", r.reason);\n }\n }\n })();\n\n try {\n await this.closing;\n } finally {\n this.closing = null;\n this.removeSignalHandlers();\n }\n }\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 * Minimal JSON Schema → Zod converter for MCP tool input schemas.\n *\n * MCP tool descriptors expose `inputSchema` as JSON Schema (typically a\n * subset of draft-2020-12 with `type`, `properties`, `required`, `items`,\n * `enum`, `default`, `description`, `nullable`). This converter handles\n * exactly that subset — anything richer ($ref, allOf, format-only schemas,\n * non-primitive oneOf composition) throws so we surface the gap rather than\n * silently coercing a wrong schema.\n *\n * @module mcp/json-schema-to-zod\n */\n\nimport { type ZodTypeAny, z } from \"zod\";\nimport { JsonSchemaConversionError } from \"./errors.js\";\n\nexport interface JSONSchemaLike {\n type?: string | string[];\n description?: string;\n default?: unknown;\n enum?: unknown[];\n nullable?: boolean;\n properties?: Record<string, JSONSchemaLike>;\n required?: string[];\n items?: JSONSchemaLike | JSONSchemaLike[];\n oneOf?: JSONSchemaLike[];\n anyOf?: JSONSchemaLike[];\n allOf?: JSONSchemaLike[];\n $ref?: string;\n // Tolerate but ignore unknown keys (e.g. $schema, title, examples).\n [k: string]: unknown;\n}\n\n/**\n * Convert a JSON Schema fragment into a Zod schema.\n *\n * Throws JsonSchemaConversionError on features that have no clean Zod analog\n * in the MCP subset.\n */\nexport function jsonSchemaToZod(schema: JSONSchemaLike | undefined): ZodTypeAny {\n if (!schema || typeof schema !== \"object\") {\n return z.unknown();\n }\n\n if (schema.$ref) {\n throw new JsonSchemaConversionError(\"$ref is not supported in MCP tool schemas\", schema);\n }\n if (schema.allOf) {\n throw new JsonSchemaConversionError(\n \"allOf is not supported (MCP tools should use a single composed schema)\",\n schema,\n );\n }\n\n // Union via oneOf / anyOf (primitives only — non-primitive composition is\n // outside the supported subset).\n const union = schema.oneOf ?? schema.anyOf;\n if (union) {\n if (!Array.isArray(union) || union.length < 2) {\n throw new JsonSchemaConversionError(\"oneOf/anyOf must have at least two members\", schema);\n }\n const branches = union.map((m) => jsonSchemaToZod(m));\n return applyDecorators(z.union(branches as [ZodTypeAny, ZodTypeAny, ...ZodTypeAny[]]), schema);\n }\n\n const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;\n\n if (type === undefined && schema.enum && Array.isArray(schema.enum)) {\n return applyDecorators(buildEnum(schema.enum), schema);\n }\n\n if (type === undefined) {\n return applyDecorators(z.unknown(), schema);\n }\n\n switch (type) {\n case \"string\": {\n let s: ZodTypeAny;\n if (schema.enum && Array.isArray(schema.enum)) {\n s = buildEnum(schema.enum);\n } else {\n s = z.string();\n }\n return applyDecorators(s, schema);\n }\n\n case \"number\":\n return applyDecorators(z.number(), schema);\n\n case \"integer\":\n return applyDecorators(z.number().int(), schema);\n\n case \"boolean\":\n return applyDecorators(z.boolean(), schema);\n\n case \"null\":\n return applyDecorators(z.null(), schema);\n\n case \"array\": {\n const items = schema.items;\n if (Array.isArray(items)) {\n throw new JsonSchemaConversionError(\"tuple-style items arrays are not supported\", schema);\n }\n const inner = items ? jsonSchemaToZod(items) : z.unknown();\n return applyDecorators(z.array(inner), schema);\n }\n\n case \"object\": {\n const props = schema.properties ?? {};\n const required = new Set(schema.required ?? []);\n const keys = Object.keys(props);\n if (keys.length === 0) {\n // No declared properties → permissive record.\n return applyDecorators(z.record(z.string(), z.unknown()), schema);\n }\n const shape: Record<string, ZodTypeAny> = {};\n for (const key of keys) {\n const inner = jsonSchemaToZod(props[key]);\n shape[key] = required.has(key) ? inner : inner.optional();\n }\n return applyDecorators(z.object(shape), schema);\n }\n\n default:\n throw new JsonSchemaConversionError(`unknown JSON Schema type \"${type}\"`, schema);\n }\n}\n\nfunction buildEnum(values: unknown[]): ZodTypeAny {\n if (values.every((v) => typeof v === \"string\")) {\n const literals = values as string[];\n if (literals.length === 0) {\n throw new JsonSchemaConversionError(\"enum cannot be empty\", values);\n }\n return z.enum(literals as [string, ...string[]]);\n }\n // Non-string enums become a union of literals.\n const literals = values.map((v) => z.literal(v as string | number | boolean));\n if (literals.length === 0) {\n throw new JsonSchemaConversionError(\"enum cannot be empty\", values);\n }\n if (literals.length === 1) {\n return literals[0]!;\n }\n return z.union(literals as unknown as [ZodTypeAny, ZodTypeAny, ...ZodTypeAny[]]);\n}\n\nfunction applyDecorators(base: ZodTypeAny, schema: JSONSchemaLike): ZodTypeAny {\n let s = base;\n if (schema.nullable === true) {\n s = s.nullable();\n }\n if (schema.description) {\n s = s.describe(schema.description);\n }\n if (schema.default !== undefined) {\n s = s.default(schema.default as never);\n }\n return s;\n}\n","/**\n * Wraps an MCP tool descriptor as a native llmist gadget so the existing\n * gadget executor consumes it without any awareness of MCP.\n *\n * @module mcp/tool-adapter\n */\n\nimport { z } from \"zod\";\nimport { createGadget } from \"../gadgets/create-gadget.js\";\nimport type { AbstractGadget } from \"../gadgets/gadget.js\";\nimport { resultWithImage } from \"../gadgets/helpers.js\";\nimport type { GadgetExecuteReturn } from \"../gadgets/types.js\";\nimport type { McpClient } from \"./client.js\";\nimport { type JSONSchemaLike, jsonSchemaToZod } from \"./json-schema-to-zod.js\";\nimport type { McpContentBlock, McpToolDescriptor, McpToolResult } from \"./types.js\";\n\nexport interface McpToolAdapterOptions {\n /** Prefix prepended to the gadget name. Used for multi-server name conflict resolution (plan 2). */\n prefix?: string;\n}\n\n/**\n * Convert an MCP tool descriptor into a native gadget that delegates to the\n * supplied MCP client.\n */\nexport function mcpToolToGadget(\n tool: McpToolDescriptor,\n client: McpClient,\n opts?: McpToolAdapterOptions,\n): AbstractGadget {\n const gadgetName = (opts?.prefix ?? \"\") + tool.name;\n const schema = buildSchema(tool.inputSchema as JSONSchemaLike | undefined);\n const description =\n tool.description ?? `MCP tool \"${tool.name}\" from server \"${client.serverName}\"`;\n\n return createGadget({\n name: gadgetName,\n description,\n schema,\n execute: async (params) => {\n const result = await client.callTool(tool.name, params);\n return mcpResultToGadgetReturn(result, tool.name);\n },\n });\n}\n\nfunction buildSchema(inputSchema: JSONSchemaLike | undefined) {\n if (!inputSchema) {\n return z.object({});\n }\n // The MCP spec mandates inputSchema is an object schema, but be defensive:\n // if a server returns a non-object, fall back to an open record.\n const converted = jsonSchemaToZod(inputSchema);\n // If the converted schema is not an object, wrap so createGadget gets an\n // object shape (which the gadget executor expects).\n if (!(converted instanceof z.ZodObject) && !(converted instanceof z.ZodRecord)) {\n return z.object({}).passthrough();\n }\n return converted as unknown as z.ZodObject<z.ZodRawShape>;\n}\n\n/**\n * Convert an MCP tools/call result into the gadget's expected return shape.\n *\n * - Pure-text content: returns the joined text as a string.\n * - Mixed text + media: returns an object with `result` (text) and `media`.\n * - Unknown content kinds: round-tripped as JSON in the text result.\n * - isError: throws so the gadget executor surfaces it as a tool error.\n */\nfunction mcpResultToGadgetReturn(result: McpToolResult, toolName: string): GadgetExecuteReturn {\n const blocks = result.content ?? [];\n const textParts: string[] = [];\n const media: Array<{ kind: \"image\" | \"audio\"; data: string; mimeType: string }> = [];\n\n for (const block of blocks) {\n const kind = (block as McpContentBlock).type;\n if (kind === \"text\" && typeof (block as { text?: unknown }).text === \"string\") {\n textParts.push((block as { text: string }).text);\n } else if (kind === \"image\") {\n const b = block as { data: string; mimeType: string };\n media.push({ kind: \"image\", data: b.data, mimeType: b.mimeType });\n } else if (kind === \"audio\") {\n const b = block as { data: string; mimeType: string };\n media.push({ kind: \"audio\", data: b.data, mimeType: b.mimeType });\n } else {\n // Unknown content kind — preserve as JSON in text so the LLM can see it.\n try {\n textParts.push(JSON.stringify(block));\n } catch {\n textParts.push(String(block));\n }\n }\n }\n\n const text = textParts.join(\"\\n\");\n\n if (result.isError) {\n throw new Error(\n text ? text : `MCP tool \"${toolName}\" returned an error result with no text content`,\n );\n }\n\n if (media.length === 0) {\n return text;\n }\n\n // Mixed media + text. Use the existing media helpers for images; for audio,\n // construct the result-with-media shape directly since detection helpers\n // can't recover from a base64-only audio payload without seeking.\n if (media.length === 1 && media[0]!.kind === \"image\") {\n const img = media[0]!;\n return resultWithImage(text, Buffer.from(img.data, \"base64\"), {\n mimeType: img.mimeType,\n });\n }\n\n return {\n result: text,\n media: media.map((m) => ({\n kind: m.kind,\n data: m.data,\n mimeType: m.mimeType,\n })),\n };\n}\n"],"mappings":"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","names":["path","path","z","path","z","literals","z","text"]}